How can I access attributes and elements from XML::LibXML in Perl?

14,448

Make sure you XML file is valid then use $node->getAttribute("someAttribute") to access attributes.

@name is a attribute name. You'd use it in findnodes() to specify elements with a given attribute set. Eg. a path like:

//camelids/species[@name="Camelus bactrianus"]/

Here is a simple/contrived example:

#!/usr/bin/perl -w
use XML::LibXML;

my $parser = XML::LibXML->new();
my $doc = $parser->parse_file('/Users/castle/Desktop/animal.xml');

my $xc = XML::LibXML::XPathContext->new( $doc->documentElement()  );
$xc->registerNs('ns', 'http://moleculardevices.com/microplateML');

my @n = $xc->findnodes('//ns:species');
foreach $nod (@n) {
    print "A: ".$nod->getAttribute("name")."\n";

    my @c = $xc->findnodes("./ns:common-name", $nod);
    foreach $cod (@c) {
        print "B: ".$cod->nodeName;
        print " = ";
        print $cod->getFirstChild()->getData()."\n";
    }
}

Output is:

perl ./xmltest.pl 
A: Camelus bactrianus
B: common-name = Bactrian Camel
Share:
14,448
John
Author by

John

Updated on June 14, 2022

Comments

  • John
    John almost 2 years

    I am having trouble understanding / using name spaces with XML::LibXML package in Perl. I can access an element successfully but not an attribute. I have the following code which accesses an XML file (http://pastebin.com/f3fb9d1d0).

    my $tree = $parser->parse_file($file); # parses the file contents into the new libXML object.
    my $xpc = XML::LibXML::XPathContext->new($tree); 
    $xpc->registerNs(microplateML => 'http://moleculardevices.com/microplateML');   
    

    I then try and access an element called common-name and an attribute called name.

    foreach my $camelid ($xpc->findnodes('//microplateML:species')) {
      my $latin_name = $camelid->findvalue('@name');   
      my $common_name = $camelid->findvalue('common-name');  
      print "$latin_name, $common_name" ;
    }
    

    But only the latin-name (@name) is printing out, the common-name is not. What am I doing wrong and how can I get the common-name to print out as well?

    What does the @name do in this case? I presume it is an array, and that attributes should be put into an array as there can be more than one, but elements (like common-name) should not be because there should just be one?

    I've been following the examples here: http://www.xml.com/pub/a/2001/11/14/xml-libxml.html and here: http://perl-xml.sourceforge.net/faq/#namespaces_xpath, and trying to get their example camel script working with my namespace, hence the weird namespace.

  • John
    John over 14 years
    Thanks Niels, I got my original question the wrong way around, the latin-name (@name) was printing out fine, the common-name was not. Not sure if that changes your answer. I tried your example but I wasn't able to print anything out at all. The problem I'm having is more to do with the namespace I think. If I don't use the first two namespace lines (with $xpc in them) and just reference the elemtents like the examples here xml.com/pub/a/2001/11/14/xml-libxml.html then everything is fine, but when I include the namespace, it doesn't work, somehow I'm not getting the elementIwant
  • Niels Castle
    Niels Castle over 14 years
    I removed the namespace and balanced the tags in the XML file you were referring to make the example run. I'll add the namespace to the example.
  • John
    John over 14 years
    Thanks again Neils, I think there was another error in the xml file, this line should have been first (<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>) I fixed it (pastebin.com/f63e6d7a3) and tried running your example script above (thanks for doing that) but I do not get any output at all from the script. Did you try to run it? It seems that this line is not working my @n = $xc->findnodes('*/species'); Do you have any idea why it is not working? Thanks.
  • John
    John over 14 years
    I re-asked this specific question and got the answer that I should use this: my @n = $xc->findnodes('//ns:species'); which now works. thanks again. stackoverflow.com/questions/2079435/…
  • Niels Castle
    Niels Castle about 14 years
    Man, that was embarrassing. I had removed the namespace declaration from the XML file while poking around with pasteboard and forgot to add it again before running the Perl script. Your comment is of course correct. I added it to the example script. The XML on pasteboard is still unbalanced, you need to add a closing </camelids>. Cheers, mate!