liverpaul
liverpaul

Reputation: 179

Perl, how to parse XML file, xpath

I want to parse an XML file using Perl. I was able to do it using the XML::Simple module, but now I want to start using the XML::XPath module instead because it uses XPath expressions. From my limited knowledge I think XPaths will make future parsing easier, right? Here's the Perl code I have so far:

use strict;
use warnings;
use XML::XPath;

my $file = "data.xml";
my $path = XML::XPath->new(filename => $file);

my $name = $path->find('/category/event/@name');
print $name."\n";

My question is how do I separate each name attribute (category/event/@name) so that I can perform tests on each value I parse. At the moment I'm just getting a big string full of the parsed data, whereas I want several small strings that I can test. How can I do this? Thanks :-)

Upvotes: 12

Views: 21231

Answers (2)

Borodin
Borodin

Reputation: 126722

The find method returns an XML::XPath::NodeSet object which is a collection of all the nodes found. I can't imagine what you can have done to see one long string with all of the attribute values.

Having retrieved the set of nodes, you work on its contents with methods like size, get_node and get_nodelist (see the docs I've linked above). get_nodelist will return a Perl list of, in this case, XML::XPath::Node::Attribute objects which also have their own methods. This program should get you started

use strict;
use warnings;

use XML::XPath;

my $xp = XML::XPath->new(ioref => \*DATA);

my $names = $xp->find('/category/event/@name');

for my $node ($names->get_nodelist) {
  say $node->getNodeValue;
}


__DATA__
  <category name="a">
    <event name="cat1" />  
    <event name="cat2" />  
    <event name="cat3" />  
    <event name="cat4" />  
    <event name="cat5" />  
  </category>

OUTPUT

cat1
cat2
cat3
cat4
cat5

Upvotes: 7

daxim
daxim

Reputation: 39158

This review points out that XML::XPath hasn't been updated since 2003, and recommends XML::LibXML instead

use 5.010;
use strict;
use warnings;
use XML::LibXML;

my $dom = XML::LibXML->new->parse_file('data.xml');
for my $node ($dom->findnodes('/category/event/@name')) {
    say $node->toString;
}

See XML::LibXML::Parser and XML::LibXML::Node.

Upvotes: 20

Related Questions