in reply to XML::LibXML - parsing question!!

You're asking to match "request" elements in the null namespace, but the closest your XML contains are "request" elements in the "http://www.somedomain.tld/market_reg/admin_server/1.0" namespace.

What you do is create is a prefix, associate it with that namespace, and use that prefix in the XPath.

use strict; use warnings; use XML::LibXML qw( ); use XML::LibXML::XPathContext qw( ); ( my $file = $0 ) =~ s/\.pl\z/.xml/i; my $parser = XML::LibXML->new (); my $dom = $parser->load_xml( location => $file ); my $root = $dom->getDocumentElement(); my $xpc = XML::LibXML::XPathContext->new($root); $xpc->registerNs( p => 'http://www.somedomain.tld/market_reg/admin_server/1.0' ); for my $node ( $xpc->findnodes('//p:request/*/p:action') ) { print $node->textContent(), "\n"; }
START STOP GET_INFO

Note that "p" is arbitrary. You can use something more meaningful. Or not.

By the way, you never have to call setContextNode. You can simply pass the context node as the second argument to find* as the following demonstrates:

use strict; use warnings; use XML::LibXML qw( ); use XML::LibXML::XPathContext qw( ); ( my $file = $0 ) =~ s/\.pl\z/.xml/i; my $parser = XML::LibXML->new (); my $dom = $parser->load_xml( location => $file ); my $root = $dom->getDocumentElement(); my $xpc = XML::LibXML::XPathContext->new($root); $xpc->registerNs( p => 'http://www.somedomain.tld/market_reg/admin_server/1.0' ); for my $req_node ( $xpc->findnodes('//p:request') ) { for my $action_node ( $xpc->findnodes('*/p:action', $req_node) ) { print $action_node->textContent(), "\n"; } }

Replies are listed 'Best First'.
Re^2: XML::LibXML - parsing question!!
by MarkovChain (Sexton) on Dec 19, 2009 at 05:37 UTC

    Ahh my friend Ikegami...

    I had tried with the namespace ... will try it again...

    Yay it worked.... I realized my mistake... although I had registered the namespace, I was only associating the namespace with the first element and naively assumed that it would get implicitly associated with child / siblings.

    Hats off Sir!!

      I was only associating the namespace with the first element

      Do you mean you "only specified a prefix for the first node test in the XPath"? There's no way to not specify a namespace for a node test in an XPath, so there's no opportunity to default to anything.

        I was doing this...

        $action_requests = $xpc->findnodes('//admin_server:request/*/action');

      Hmm I've been trying to validate the xml with my schema and my schema validation works perfectly in my xml editor (I'm using Oxygen XML Editor... not that it matters).

      The validation fails when using XML::LibXML::Schema.

      #---------------------------------------------------------- # Validate against XML schema. #---------------------------------------------------------- my $xml_schema = XML::LibXML::Schema->new( location => '/Users/dattanik/Programs/XML/admin_server.xsd' ); eval { $xml_schema->validate($dom); }; if ($@) { print "Looks like schema validation has failed. \n"; print "$@", "\n"; } else { print "XML Schema validation succeeded.\n"; }

      I have a primitive facet for validating IP addresses...(\d{1,3}\.){3}\d{1,3} that's embedded in my XML Schema. I am also collapsing the embedded spaces in the application_host_ip element.

      Nothing special here but it fails there when validating thru XML::LibXML::Schema.... the validation of the exact same XML document is successful using my schema. My relevant schema code is:

      <xs:element name="application_host_ip"> <xs:annotation> <xs:documentation>The IP address of the host on wh +ich the application is executing.</xs:documentation> </xs:annotation> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="(\d{1,3}\.){3}\d{1,3}"> <xs:annotation> <xs:documentation>This regular express +ion does a rudimentary check on the IP address.</xs:documentation> </xs:annotation> </xs:pattern> <xs:maxLength value="15"/> <xs:minLength value="7"/> <xs:whiteSpace value="collapse"/> </xs:restriction> </xs:simpleType> </xs:element>

      Now I checked the support docs in XML::LibXML::Schema but it does not seem to provide any additional info besides the class interface.

      The relevant output from STDOUT is printed...

      Looks like schema validation has failed Element 'application_host_ip' [ST local, facet 'pattern']: The value ' +123.123.24.56' is not accepted by the pattern '(\d{1,3}\.){3}\d{1,3}' +. Element 'application_host_ip' [ST local, facet 'pattern']: The value ' +123.123.24.56' is not accepted by the pattern '(\d{1,3}\.){3}\d{1,3}' +.

      I am doing all this as part of my pet project to monitor a myriad of applications running across my production network. These guys have log4j writers and currently the maintenance folks are individually logging into those boxes via ssh and running standard maintenance procedures. I am automating this process by writing a POE server that listens on these log4j and presents status info to a web client. The web user agent can then send requests in standard XML format that is interpreted by the server and it does the maintenance tasks... much more reliable. This is the last part :)....

        Try replacing \d with [0-9]. I seem to remember having run into that problem. [0-9] is better anyway, since \d matches way more than [0-9].