worik has asked for the wisdom of the Perl Monks concerning the following question:
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
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Using XPaths with XML::LibXML and XPathContext
by Anonymous Monk on Jun 03, 2015 at 00:40 UTC | |
|
Re: Using XPaths with XML::LibXML and XPathContext
by Anonymous Monk on Jun 02, 2015 at 23:37 UTC | |
by Anonymous Monk on Jun 03, 2015 at 01:05 UTC | |
by ikegami (Patriarch) on Jun 03, 2015 at 16:44 UTC | |
by worik (Sexton) on Jun 03, 2015 at 01:03 UTC | |
by Anonymous Monk on Jun 03, 2015 at 01:30 UTC |