http://www.perlmonks.org?node_id=1052705

topola1882 has asked for the wisdom of the Perl Monks concerning the following question:

Hello everybody, i think i have a simple question but i can't find an aswer to it anywhere so i hope you can help.
I have an xml file with namespace and i want to select a node with an attribute with a specific value. Here is the xml file:

<?xml version="1.0" encoding="UTF-8"?> <guestbook xmlns="http://myweb.com" xmlns:xs="http://www.w3.org/2001/X +MLSchema-instance" nome="740" xs:schemaLocation="http://myweb.com gue +stbook.xsd"> <comment confermato="true" timestamp="20130627112554"> <guest>...</guest> </comment> <comment confermato="false" timestamp="20130903225513"> <guest>...</guest> </comment> <comment confermato="false" timestamp="20130904191337"> <guest>...</guest> </comment> </guestbook>

I need, with a cgi script, to select the node "comment" with the timestamp "20130903225513". The problem is that i don't know hot to put the namespace correctly. Here is the code for the script

#!/usr/bin/perl use strict; use XML::LibXML; use HTML::Entities; use CGI; use CGI::Carp qw(fatalsToBrowser warningsToBrowser); use Fcntl qw(:flock); my $cgi = new CGI; print "Content-type: text/html\n\n"; my $file_dati = "../data/xml/guestbook_xml.xml"; my $parser = XML::LibXML->new(); my $doc = $parser->parse_file($file_dati) || die("dead1"); my $root = $doc->getDocumentElement || die("dead2"); my $nodetobefound= "xs:commento[xs:\@timestamp='20130903225513']"; print "$nodetobefound\n"; my $commento = $root->findnodes("$nodetobefound") || die("dead3"); print $commento->get_node(0)->toString();

If i don't insert any namespace in the query i finish in the "dead3" die, if i put any kind of namespace i receive an "Xpath error: invalid expression".
Any hint on how to write the correct xpath query?
thanx in advance, Giulia

Replies are listed 'Best First'.
Re: How to write an xpath query including attributes for an XML with namespace
by choroba (Cardinal) on Sep 06, 2013 at 12:59 UTC
    To use a namespace in an XPath expression, you have to register it first. The following works for me:
    #!/usr/bin/perl use warnings; use strict; use XML::LibXML; my $file_dati = '/path/to/file.xml'; my $parser = 'XML::LibXML'->new(); my $doc = $parser->parse_file($file_dati) || die('dead1'); my $xc = 'XML::LibXML::XPathContext'->new($doc); $xc->registerNs('mw', 'http://myweb.com'); my $nodetobefound = '//mw:comment[@timestamp="20130903225513"]'; print "To be found: $nodetobefound\n"; my $commento = $xc->findnodes($nodetobefound) || die('dead3'); print $commento->get_node(0)->toString();

    As Corion suggested, I changed the name of the element and added // for recursive search.

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Thanks Choroba, it worked!!

Re: How to write an xpath query including attributes for an XML with namespace
by Corion (Patriarch) on Sep 06, 2013 at 12:53 UTC

    You have no commento nodes in your XML. Maybe that's already the whole problem?

    Also, when trying XPath queries, I find it often more beneficial to use unanchored queries while trying things out. You may want to search for //comment instead of commento.

      thanks Corion, that was not the problem (i just copied the wrong code). Anyway i resolved with the hint from Choroba