I am trying to parse some simple XML in XML::LibXML and I have struck a problem. The domain is WebDAV.

A PROPFIND request from a user can send some very simple XML, but in a variety of semantically identical but syntactically different forms.

For a simple example:

<?xml version="1.0" encoding="utf-8" ?> <propfind xmlns="DAV:"> <propname/> </propfind>
<?xml version="1.0" encoding="utf-8" ?> <D:propfind xmlns:D="DAV:"> <D:propname/> </D:propfind>

TO get the 'propfind' node valid XPaths are

//propname
//DAV:propname
/propfind/propname
/DAV:propfind/DAV:propname

surely? But none of them work with XPathContext except in one special case (below) where there is no need for it anyway.

Below are my test code and the results. In it I register 'D' as a prefix for 'DAV:' and so using a XPath with 'D' as prefix works where the XML uses it too. But that is not good enough for where the XML uses 'DAV:' as a default namespace 'D' as a prefix should work too. Surely?

#!/usr/bin/perl -w use strict; use XML::LibXML; sub testfn { my $content = shift or die; my $xpath = shift or die; $|++; my $parser = XML::LibXML->new(); my $dom = $parser->parse_string($content); my @propfind = (); @propfind = $dom->findnodes($xpath); print ref($dom)."::findnodes('$xpath') (NOT XPathContext) ". scalar(@propfind)." nodes\n"; my $xc = XML::LibXML::XPathContext->new($dom); $xc->registerNs('D', 'DAV:'); @propfind = $xc->findnodes($xpath); print ref($xc)."::findnodes('$xpath') ".scalar(@propfind)." nodes\ +n"; } # Example from RFC4918 my $txt1 = '<?xml version="1.0" encoding="utf-8" ?> <D:propfind xmlns:D="DAV:"> <D:propname/> </D:propfind> '; my $txt2 = '<?xml version="1.0" encoding="utf-8" ?> <propfind xmlns="DAV:"> <propname/> </propfind> '; my $xpath1 = '/DAV:propfind/DAV:propname'; my $xpath2 = '/propfind/propname'; my $xpath3 = '/D:propfind/D:propname'; print "\$txt1\n".$txt1."\n"; print "\$txt1 \$xpath1 \n"; eval { &testfn($txt1, $xpath1); }; if($@){ print "Failed \$xpath $xpath1\n"; } print "\$txt1 \$xpath2 \n"; eval{ &testfn($txt1, $xpath2); }; if($@){ print "Failed \$xpath $xpath2\n"; } print "\$txt1 \$xpath3 \n"; eval{ &testfn($txt1, $xpath3); }; if($@){ print "Failed \$xpath $xpath3\n"; } print "\$txt2\n".$txt2."\n"; print "\$txt2 \$xpath1 \n"; eval{ &testfn($txt2, $xpath1); }; if($@){ print "Failed \$xpath $xpath1\n"; } print "\$txt2 \$xpath2 \n"; eval { &testfn($txt2, $xpath2); }; if($@){ print "Failed \$xpath $xpath2\n"; } print "\$txt2 \$xpath3 \n"; eval { &testfn($txt2, $xpath3); }; if($@){ print "Failed \$xpath $xpath3\n"; }

The results:

$txt1 <?xml version="1.0" encoding="utf-8" ?> <D:propfind xmlns:D="DAV:"> <D:propname/> </D:propfind> $txt1 $xpath1 Failed $xpath /DAV:propfind/DAV:propname $txt1 $xpath2 XML::LibXML::Document::findnodes('/propfind/propname') (NOT XPathConte +xt) 0 nodes XML::LibXML::XPathContext::findnodes('/propfind/propname') 0 nodes $txt1 $xpath3 XML::LibXML::Document::findnodes('/D:propfind/D:propname') (NOT XPathC +ontext) 1 nodes XML::LibXML::XPathContext::findnodes('/D:propfind/D:propname') 1 nodes $txt2 <?xml version="1.0" encoding="utf-8" ?> <propfind xmlns="DAV:"> <propname/> </propfind> $txt2 $xpath1 Failed $xpath /DAV:propfind/DAV:propname $txt2 $xpath2 XML::LibXML::Document::findnodes('/propfind/propname') (NOT XPathConte +xt) 0 nodes XML::LibXML::XPathContext::findnodes('/propfind/propname') 0 nodes $txt2 $xpath3 Failed $xpath /D:propfind/D:propname

In reply to Using XPaths with XML::LibXML and XPathContext by worik

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.