Skip Menu |

This queue is for tickets about the XML-LibXML CPAN distribution.

Report information
The Basics
Id: 56092
Status: resolved
Priority: 0/
Queue: XML-LibXML

People
Owner: Nobody in particular
Requestors: holborn-bitcard [...] real-life.tm
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 1.70
Fixed in: (no value)



Subject: find/findnodes/findvalue fail to find a node/element
I'm probably being an idiot, but I cannot get XML::LibXML to pull a certain node from the attached xml. Test Code Show quoted text
--- BEGIN --- #! /usr/bin/perl use warnings; use strict; use Data::Dumper; use XML::LibXML; my $xml; my $libxml_parser = XML::LibXML->new(); my $dom = $libxml_parser->parse_file( 'playing.xml' ); my $root = $dom->getDocumentElement; my $elname = $root -> getName(); print "Root element is a $elname and it contains ...\n"; my @kids = $root -> childNodes(); foreach my $child (@kids) { $elname = $child -> getName(); my @atts = $child -> getAttributes(); print "$elname ("; foreach my $at (@atts) { my $na = $at -> getName(); my $va = $at -> getValue(); print " ${na}[$va] "; } print ")\n"; } print "\n\n"; # Note Signature appears in the above code... # However on using find/findnodes/findvalue with an XPath fails to # find the node... my $xpath = '//Signature'; my @nodes = $root->findnodes( $xpath ); my $result = $root->find( $xpath ); print "\@nodes: " . Dumper (@nodes) . "\n"; print "result: " . Dumper( $result ) . "\n"; print "size: " . $result->size() . "\n"; print "Value: " . $root->findvalue( $xpath ) . "\n"; foreach $elname ( $result->get_nodelist ) { print $elname->getName() . "\n"; } 1; --- END --- On Running: $ ./broken.pl Root element is a saml:Assertion and it contains ... #text () saml:Issuer ( Format[urn:oasis:names:tc:SAML:2.0:nameid-format:entity] ) #text () Signature ( xmlns[http://www.w3.org/2000/09/xmldsig#] ) #text () saml:Subject () #text () saml:Conditions ( NotBefore[2010-03-05T15:38:29Z] NotOnOrAfter[2010-03-05T15:58:29Z] ) #text () saml:AuthnStatement ( AuthnInstant[2010-03-05T15:48:29Z] ) #text () saml:AttributeStatement () #text () @nodes: result: $VAR1 = bless( [], 'XML::LibXML::NodeList' ); size: 0 Value: Using the above code to pull any of the "saml:...." values works fine. I'm using XML-LibXML-1.70, with libxml2-2.7.6, perl v5.10.1 built for amd64-freebsd, On Freebsd v8.0-RELEASE. Prod me if you need any more details.
Subject: playing.xml
<?xml version="1.0"?> <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_faeeb326-1d4707118d13" IssueInstant="2010-03-05T15:48:29Z"> <saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://example.com/foobiz</saml:Issuer> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <Reference URI="#_faeeb326-1d4707118d13"> <Transforms> <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> <InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="#default saml ds xs xsi"/> </Transform> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue>ODy9/ZBgqbLLsD39fdd4MpDAtQ=</DigestValue> </Reference> </SignedInfo> <SignatureValue>wRqELB7X/SMKEw4clDPqryUTizkeQfCyIvlk5GJR6Z13MTwBrOlbJFYnbqHHcH8Z8j7EO8EOE5GRydShLf/FpDOedUcBnqEsddvIcwOebmLsc=</SignatureValue> <KeyInfo> <X509Data> <X509Certificate>MIIB2jCCOlCaAe6BJUVKh8OUCAwEAAaNLMEkwRwYDVR0BBEAwPoAQEuQJLQYdHU8AjWEh3BZkY6EYMBYxFDASBgNVBAMTC1Jvb3QgQWdlbmN5ghAGN2wAqgBkihHPuNSqXDX0MA0GCSqGSIb3DQEBBAUAA0EAMvQOfC24ELwXPgiXP3YrGUSAguSyNAyikMD+0wUuABAUVOwi1Orz2Y3RIGO8XIy/YBdq+2h5mMi2CieOpEo35g==</X509Certificate> </X509Data> </KeyInfo> </Signature> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">137371</saml:NameID> </saml:Subject> <saml:Conditions NotBefore="2010-03-05T15:38:29Z" NotOnOrAfter="2010-03-05T15:58:29Z"/> <saml:AuthnStatement AuthnInstant="2010-03-05T15:48:29Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocolPassword</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="companyCode" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue>562</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="userId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue>test019</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="firstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue>Test019</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="surname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue>Test 119</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="emailAddress" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue>xx</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion>
You use the wrong function. Your problem is connected to the document and using findnodes(). findnodes() is just a simple interface to XPath to select nodes directly from a DOM element. It is so simple that it does not automatically include namespaces into the query. However, if your document includes namespaces and therefore the simple tricks will fail. You should have a look at perldoc XML::LibXML::XPathContext. This package provides a nice interface for using easy to read and namespace aware XPath queries. Hope this helps. Christian On Tue Mar 30 04:53:20 2010, dravster wrote: Show quoted text
> I'm probably being an idiot, but I cannot get XML::LibXML to pull a > certain node from the attached xml. > > Test Code > > --- BEGIN --- > > #! /usr/bin/perl > > use warnings; > use strict; > use Data::Dumper; > use XML::LibXML; > > my $xml; > > my $libxml_parser = XML::LibXML->new(); > my $dom = $libxml_parser->parse_file( 'playing.xml' ); > my $root = $dom->getDocumentElement; > my $elname = $root -> getName(); > > print "Root element is a $elname and it contains ...\n"; > > my @kids = $root -> childNodes(); > foreach my $child (@kids) { > $elname = $child -> getName(); > my @atts = $child -> getAttributes(); > print "$elname ("; > foreach my $at (@atts) { > my $na = $at -> getName(); > my $va = $at -> getValue(); > print " ${na}[$va] "; > } > print ")\n"; > } > print "\n\n"; > > # Note Signature appears in the above code... > > # However on using find/findnodes/findvalue with an XPath fails to > # find the node... > my $xpath = '//Signature'; > my @nodes = $root->findnodes( $xpath ); > my $result = $root->find( $xpath ); > print "\@nodes: " . Dumper (@nodes) . "\n"; > print "result: " . Dumper( $result ) . "\n"; > print "size: " . $result->size() . "\n"; > print "Value: " . $root->findvalue( $xpath ) . "\n"; > > foreach $elname ( $result->get_nodelist ) { > print $elname->getName() . "\n"; > } > > 1; > > --- END --- > > On Running: > > $ ./broken.pl > Root element is a saml:Assertion and it contains ... > #text () > saml:Issuer ( Format[urn:oasis:names:tc:SAML:2.0:nameid-format:entity] ) > #text () > Signature ( xmlns[http://www.w3.org/2000/09/xmldsig#] ) > #text () > saml:Subject () > #text () > saml:Conditions ( NotBefore[2010-03-05T15:38:29Z] > NotOnOrAfter[2010-03-05T15:58:29Z] ) > #text () > saml:AuthnStatement ( AuthnInstant[2010-03-05T15:48:29Z] ) > #text () > saml:AttributeStatement () > #text () > > > @nodes: > result: $VAR1 = bless( [], 'XML::LibXML::NodeList' ); > > size: 0 > Value: > > > Using the above code to pull any of the "saml:...." values works > fine. > > > I'm using XML-LibXML-1.70, with libxml2-2.7.6, perl v5.10.1 built for > amd64-freebsd, On Freebsd v8.0-RELEASE. > > Prod me if you need any more details.
From: holborn-bitcard [...] real-life.tm
On Tue Mar 30 05:10:54 2010, PHISH wrote: Show quoted text
> You use the wrong function. Your problem is connected to the document > and using findnodes(). > > findnodes() is just a simple interface to XPath to select nodes directly > from a DOM element. It is so simple that it does not automatically > include namespaces into the query. However, if your document includes > namespaces and therefore the simple tricks will fail. > > You should have a look at perldoc XML::LibXML::XPathContext. This > package provides a nice interface for using easy to read and namespace > aware XPath queries.
Ah okay! For the record (if other people come across this and wonder what the "code solution" is: #! /usr/bin/perl use warnings; use strict; use Data::Dumper; use XML::LibXML; my $xml; my $libxml_parser = XML::LibXML->new(); my $dom = $libxml_parser->parse_file( 'playing.xml' ); my $root = $dom->getDocumentElement; my $xc = XML::LibXML::XPathContext->new( $root ); $xc->registerNs(sig => 'http://www.w3.org/2000/09/xmldsig#'); my $xpath = '//sig:Signature'; my @nodes = $xc->findnodes( $xpath, $dom ); my $result = $xc->find( $xpath, $dom ); print "\@nodes: " . Dumper (@nodes) . "\n"; print "result: " . Dumper( $result ) . "\n"; print "size: " . $result->size() . "\n"; print "Value: " . $xc->findvalue( $xpath, $dom ) . "\n"; foreach my $elname ( $result->get_nodelist ) { print $elname->getName() . "\n"; }
From: holborn-bitcard [...] real-life.tm
Eeeep! Sorry for making this move to status "open" again :P
Resolving per the discussion as an answer was supplied.