xpath expression in findnodes() returning empty nodelist

perl, xlib, xml, xpath

Solution

The URI for the deafult namespace in your XML is `http://www.zoo.com`, so you must specify this in your XPath expressions for the nodes to be picked up.

The way to do this is to declare a `XML::LibXML::XPathContext` object that assigns a name to this namespace. The name can then be used in XPath expressions to access the nodes.

If you write

my $xpc = XML::LibXML::XPathContext->new;
$xpc->registerNs('zoo', 'http://www.zoo.com');

you now have a context in which the XML's default namespace is named `zoo`. Now you can write

my $area_element = $xpc->findnodes("//zoo:area[\@id=$area]", $doc)->get_node(1);

and you will find the correct `<area>` element.

Problem

XML: ``` <zoo xmlns="http://www.zoo.com" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://www.zoo.com employee.xsd"> <area id="1" posizione="nord" nome="scimmie"> <animale> <nome>Gigi</nome> <sesso>Male</sesso> <eta>3</eta> </animale> <animale> <nome>Gigia</nome> <sesso>Female</sesso> <eta>2</eta> </animale> </area> <area id="2" posizione="nord" nome="giraffe"> <animale> <nome>Giro</nome> <sesso>Male</sesso> <eta>6</eta> </animale> <animale> <nome>Gira</nome> <sesso>Female</sesso> <eta>5</eta> </animale> </area> </zoo> ``` code: ``` my $parser = XML::LibXML->new; my $doc = $parser->parse_file("../xml/animals.xml"); my $root = $doc->getDocumentElement(); my $new_animal = $doc->createElement("animale"); my $name_element = $doc->createElement("nome"); $name_element->appendTextNode($name); my $gender_element = $doc->createElement("sesso"); $gender_element->appendTextNode($gender); my $age_element = $doc->createElement("eta"); $age_element->appendTextNode($age); $new_animal->appendChild($name_element); $new_animal->appendChild($gender_element); $new_animal->appendChild($age_element); my $area_element = $root -> findnodes("//area[\@id=$area]")->get_node(1); $area_element->appendChild($new_animal); ``` $area is the id of an area (usually 1 now that I'm testing) my purpose is to create a new animal and to add it to the proper area but I have the problem that the istruction ``` my $area_element = $root -> findnodes("//area[\@id=$area]")->get_node(1); ``` won't work, because $area_element is undef, because findnodes always returns an empty nodelist (checked printing the size()). I think that the problem is the xpath expression inside findnodes, but I can't understand what's wrong, I use the same expression with another library (XML::XPath) and it's working. What's wrong?

Original source