-1

I have a simple xml like this

<Rows><Row name="23"><product_id>23</product_id><product_name>Final
Fantasy</product_name><Row>
.
.
.
<Row name="25"><product_id>25</product_id><product_name>Final
</product_name><Row>
<Rows>

I have the code like this :

use strict;
use XML::Simple;
my $source = XMLin("$source_of_file");

    my $v = $source->{Row};

    if($v && ref($v) eq 'ARRAY'){
        my @v = @{$v};
        foreach my $object(@v) {
                my %data = %{$object};
                my $id = $data{product_id};
                print $id;

                my $title;
                unless (ref($data{product_name}) eq 'HASH') {
                    $title  = $data{product_name};
                }
                print $title;

        .....
        }
     }

I want to get output like this :

23
Final Fantasy
...
25
Final

Can you help me to get the data of XML? I have no idea.

  • 4
    "The use of this module in new code is discouraged. Other modules are available which provide more straightforward and consistent interfaces. In particular, XML::LibXML is highly recommended" — https://metacpan.org/pod/XML::Simple – Quentin Jul 03 '15 at 09:21
  • 1
    I started trying to figure out what was wrong with the code (beyond the XML itself simply being invalid). That was the first time I've ever really tried to use XML::Simple and it is utterly insane. Use a different module. – Quentin Jul 03 '15 at 09:29
  • What data are you trying to extract specifically? Can you give a sample output? – Sobrique Jul 03 '15 at 09:29
  • Thank you for your suggest @Quentin – Irwan Mulyawan Jul 03 '15 at 15:05
  • I was added a sample output. Can you help me? @Sobrique – Irwan Mulyawan Jul 03 '15 at 15:07
  • `XML::Simple` is pretty horrible. It doesn't make _much_ difference for trivial problems, but pretty much inherently it's "converting" to make arrays when XML doesn't have arrays at all. That's always going to end ugly. – Sobrique Jul 03 '15 at 15:42

2 Answers2

2

OK, so - XML::Simple lies. It's not simple. It's for simple XML. And it's basically horrible, don't use it.

"The use of this module in new code is discouraged. Other modules are available which provide more straightforward and consistent interfaces."

I would suggest XML::Twig instead:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig; 

my $twig = XML::Twig -> new ( 'pretty_print' => 'indented_a', 
                              'twig_handlers' => { 'Row' => sub { $_ -> print } } );
$twig -> parsefile ( "yourXmlFile.xml" );

##print the whole thing, formatted:
$twig -> print; 

Something like that. If you can give a desired input/output, then we can give you a better example to work from.

Edit: Based on your example given:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new(
    'pretty_print'  => 'indented_a',
    'twig_handlers' => {
        'Row' => sub {
            print $_ ->first_child_text('product_id'),   "\n";
            print $_ ->first_child_text('product_name'), "\n";
        }
    }
);
$twig->parsefile("yourXmlFile.xml");

Although note - I've had to correct your XML. If that's because of a typing problem on your end (and I'm assuming it is because of the dots) that's fine. If you have broken XML on the other hand, then you're scuppered, because broken XML is supposed to be fatal, and anything that parses them is supposed to break.

Dealing with malformed XML

XML::Twig allows you to set a handler that is called each time a particular element is seen. So in the example above, it's as simple as 'print every Row element.

But you can set it to a subroutine:

'twig_handlers' => { 'Row' => \&process_row }

And then have a more detailed handler:

sub process_row {
     my ( $twig, $row ) = @_; 
     print $row -> att{'name'},"\n";
     print $row -> first_child('product_name')->text,"\n";
}

You can also use xpath to find elements in your XML:

my $row23 = $twig -> get_xpath ( 'row[@name="23"]', 0 ); 
$row23 -> print; 
Community
  • 1
  • 1
Sobrique
  • 52,974
  • 7
  • 60
  • 101
2

I like XML::LibXML for processing XML.

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use XML::LibXML;

my $parser = XML::LibXML->new();
my $doc = $parser->parse_fh(*DATA);

foreach ($doc->findnodes('//Row')) {
  say $_->findvalue('product_id');
  say $_->findvalue('product_name');
}

__END__
<Rows><Row name="23"><product_id>23</product_id><product_name>Final
Fantasy</product_name></Row>
<Row name="25"><product_id>25</product_id><product_name>Final
</product_name></Row>
</Rows>

The example you gave us wasn't valid XML. Some of the closing tags were incorrect. If you want our help, please paste the data into your question - don't try to re-type it.

Dave Cross
  • 68,119
  • 3
  • 51
  • 97
  • Sorry for my mistake. Last question : How can I save say $_->findvalue('product_id'); say $_->findvalue('product_name'); To some variable, like : my product_id my product_name – Irwan Mulyawan Jul 06 '15 at 03:28
  • `my $product_id = $_->findvalue('product_id')`. But if you don't know how to store values in variables, then you should really spend a few days reading [Learning Perl](http://shop.oreilly.com/product/0636920018452.do) before embarking on a project like this. – Dave Cross Jul 06 '15 at 05:14