Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: XML::LibXML drives me to drinking

by Anonymous Monk
on Oct 23, 2016 at 01:47 UTC ( #1174530=note: print w/replies, xml ) Need Help??


in reply to XML::LibXML drives me to drinking

What you're wanting is $xpathcontext->findnodes( $xpathstring, $startnode )

I much prefer my version $node->F($xpathstr, 'prefix'=>'http...')

#!/usr/bin/perl -- use strict; use XML::LibXML; my $string = qq~<?xml version="1.0"?> <ItemLookupResponse xmlns="http://webservices.amazon.com/AWSECommerceS +ervice/2013-08-01"> <Items> <Item> <ASIN>B01KI4JSQY</ASIN> </Item> </Items> </ItemLookupResponse> ~; my $dom = XML::LibXML->new(qw/ recover 2 / )->load_xml(string => $str +ing, {no_blanks => 1}); # *register* namespace $dom->F( '/', 'x', 'http://webservices.amazon.com/AWSECommerceService/2013-08-01 +' ); foreach my $item ( $dom->F('/x:ItemLookupResponse/x:Items/x:Item' )){ print $item->firstChild->nodeName, "\n"; print $item->firstChild->toString, "\n"; print $item->F('x:ASIN')->shift()->string_value, "\n"; print $item->F('./x:ASIN/text()'), "\n"; print $item->F('./x:ASIN')->[0]->textContent, "\n"; } 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 ); }

Replies are listed 'Best First'.
Re^2: XML::LibXML drives me to drinking
by tunafish (Beadle) on Oct 23, 2016 at 03:59 UTC

    Wait, are you saying I need to create a new XML::LibXML::XPathContext object for each node as I loop through them?!

    I modified my code in the following way:

    # Parse items foreach my $item ($xml->findnodes('/x:ItemLookupResponse/x:Items/x:Ite +m', $parser)){ my $item_xml = XML::LibXML::XPathContext->new($item); $item_xml->registerNs('x', 'http://webservices.amazon.com/AWSE +CommerceService/2013-08-01'); print $item_xml->findvalue('x:ASIN'), "\n"; print $item_xml->findnodes('x:ASIN')->shift->textContent, "\n" +; }

    And bingo!

    B01KI4JSQY B01KI4JSQY

    Oy vey! Wouldn't it be much more convenient if a XML::LibXML::XPathContext object calling the findnodes() method returned another XML::LibXML::XPathContext object, rather than a XML::LibXML::Node or XML::LibXML::Element object?

    I haven't pulled this much hair in one day for a coding-related reason IN YEARS.

      Wait, are you saying I need to create a new XML::LibXML::XPathContext object for each node as I loop through them?!

      No, what gave you that idea?

      All XML::LibXML::XPathContext does is map prefixes to namespaces, and that only needs to be done once.

      See https://metacpan.org/pod/XML::LibXML::Node#findnodes

      I haven't pulled this much hair in one day for a coding-related reason IN YEARS.

      step away from the keyboard, lunch, nap, vacation, whatever it takes

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1174530]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (10)
As of 2020-02-27 15:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What numbers are you going to focus on primarily in 2020?










    Results (120 votes). Check out past polls.

    Notices?