in reply to Re^2: Xpath not working
in thread Xpath not working

... it should be noted it ...

Thanks ; yeah, if the xml changes it change

You can add attribute test

and @xmlns="http://www.crtp.it"
or use the xpath function
and namespace-uri() = "http://www.crpt.com"

The idea is to keep the xpath stuff where it belong, in the xpath string

Replies are listed 'Best First'.
Re^4: Xpath not working
by Anonymous Monk on Mar 29, 2014 at 01:22 UTC
    if the xml changes it change

    The three listed changes produce semantically equivalent XML documents. For example, if you make any or all of those changes, the document will still validate perfectly fine against the same schema. If the OP doesn't have full control over the source of the XML, those changes might happen, and the XPath using just name() would break.

    Even though TIMTOWTDI, I prefer writing this

    my $xpc = XML::LibXML::XPathContext->new($doc); $xpc->registerNs('p', 'http://www.crtp.it'); $xpc->registerNs('p2', 'http://www.crpt.com'); my $result = $xpc->findnodes("/p2:login/p:utenti[p:email='$email' and +p:password='$digestpass']/p:admin");

    over this

    my $result = $doc->findnodes(qq{ /*[ local-name()="login" and namespace-uri()="http://www.crpt.com" ] /*[ local-name()="utenti" and namespace-uri()="http://www.crtp.it" ] [ *[ local-name()="email" and namespace-uri()="http://www.crtp.it" a +nd string(node())="$email" ] and *[ local-name()="password" and namespace-uri()="http://www.crtp.it +" and string(node())="$digestpass" ] ] /*[ local-name()="admin" and namespace-uri()="http://www.crtp.it" ] });

    because it's shorter, has less repetition, and uses the recommended API.

    The idea is to keep the xpath stuff where it belong

    In the first piece of code above, the XPath stuff is already where it belongs: in an XPath expression context. From the XPath spec:

    Expression evaluation occurs with respect to a context. ... The context consists of:
    • ...
    • the set of namespace declarations in scope for the expression

    Also, it's what is recommended by findnodes:

    There are several possible ways to deal with namespaces in XPath:
    • The recommended way is to use the XML::LibXML::XPathContext module to define an explicit context for XPath evaluation, in which a document independent prefix-to-namespace mapping can be defined.

      Even though TIMTOWTDI, I prefer writing this

      Hah, my way :)

      over this

      Well, you only really need the first one ... unless all of a sudden the xml switches the default namespace ... which makes for weak xml

      because it's shorter, has less repetition, and uses the recommended API... the XPath stuff is already where it belongs: in an XPath expression context.

      Yes, the completely unspecified part of the api that is up to each implementer to implement

      To use the recommended API xpather.pl would have to switch to printing perl code instead of xpaths ....

      With xpather.pl you copy/paste the xpaths, edit minimally , practically no writing involved :) and even the dumbest newbie can copy/paste (and xml/xpath not exactly newbie friendly)

      FWIW , this is F2.0

      $node->F("//f:p/g:h", qw[ f http://f.example.com g http://g.example.co +m ]); sub XML::LibXML::Node::F { my $self = shift; my $xpath = shift; my %prefix = @_; our $XPATHCONTEXT; $XPATHCONTEXT ||= XML::LibXML::XPathContext->new(); while( my( $p, $u ) = each %prefix ){ $XPATHCONTEXT->registerNs( $p, $u ); } $XPATHCONTEXT->findnodes( $xpath, $self ); }