I'm having some trouble with this code:
my $file= '../xml/news.xml';
my $parser= XML::LibXML->new();
my $doc = $parser->parse_file($file);
my $xpc = XML::LibXML::XPathContext->new($doc);
my $query = '/notizie/news[@id='.$newsId.']';
print $query;
my $node = $xpc->findnodes($query)->get_node(1);
print $node;
In particular "print $node" prints an empty string, even if the XML file path is correct and the XPath query should return a node.
The "funny" thing is that if i use:
my $query = '/*/*[@id='.$newsId.']';
i got the right result.
This is the news.xml file:
<?xml version="1.0"?>
<notizie xmlns="http://www.9armonie.com/news"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.9armonie.com/news news.xsd">
<news id="3">
<data>2015-01-01</data>
<ora>12:00:00</ora>
<titolo>Title 3</titolo>
<descrizione> Description 3</descrizione>
</news>
<news id="2">
<data>2014-12-19</data>
<ora>12:00:00</ora>
<titolo>Title 2</titolo>
<descrizione> Description 2</descrizione>
</news>
<news id="1">
<data>2014-12-18</data>
<ora>12:00:00</ora>
<titolo>News 1</titolo>
<descrizione> Desc 1</descrizione>
</news>
<news id="0">
<data>2014-12-18</data>
<ora>12:00:00</ora>
<titolo> asdasd</titolo>
<descrizione> First! </descrizione>
</news>
</notizie>
Your input XML document is in a default namespace:
This element and all its descendants are in that namespace, and an expression like
//notizie
will never be successful because it looks for an element without a namespace.On the other hand, that's also why
/*/*
returns the elements - because*
matches elements in any (or no) namespace. There is nothing funny about it really.Either declare this namespace in your Perl code (the better option), or ignore namespaces in your XPath expression.
Declaring the namespace with LibXML
I believe declaring namespaces in LibXML is done with
registerNs()
, see the relevant CPAN page. Declare the namespace URI from the input XML together with a prefix (news:
, in this example) that you can then use to qualify the element names in the XPath expression.Ignoring namespaces
The second option means modifying your XPath expression to
The above expression will find the
notizie
element in all of the following documents: