in reply to Re^4: Xpath value query
in thread Xpath value query

XML::Twig has this note against get_xpath

XML::Twig does not provide natively full XPATH support, but you can use XML::Twig::XPath to get findnodes to use XML::XPath as the XPath engine, with full coverage of the spec.
so try this
#!perl use strict; use XML::Twig::XPath; my $twig = XML::Twig::XPath->new(); $twig->parsefile('txlife.xml'); my $root = $twig->root; my $xpath = q!//Party[@id=//Relation[child::RelationRoleCode[@tc='37'] +]/@RelatedObjectID]/Producer/CarrierAppointment/CompanyProducerID!; my @nodes = $root->findnodes($xpath); for (@nodes){ print $_->text; }
Outputs : 459JQ
poj

Replies are listed 'Best First'.
Re^6: Xpath value query
by SDwerner (Initiate) on Sep 18, 2015 at 17:08 UTC

    So, I tried to use a variable to return the values from the XPath, and it's not liking it.. I get an invalid query error. Here is the subroutine I'm using. I must be missing something. I added a few statements to help me see what was happening. The goal is for the XPaths to come from a configuration file (as there are about a dozen, and there are other formats that will be added in the future so there may be hundreds ultimatley) rather than hard coded, but for testing and development I'm doing it this way.

    $twig = XML::Twig::XPath->new(); $twig->parsefile($xmlfile); $root = $twig->root; $XPV='//Party[@id=//Relation[child::RelationRoleCode[@tc="37"]]/@Relat +edObjectID]/Producer/CarrierAppointment/CompanyProducerID'; my $retval1 = get_xpath_value($XPV); $XPV='//OLifE/Party[@id=//OLifE/Relation[RelationRoleCode@tc=8]/@Relat +edObjectID]/Person/FirstName'; my $retval2 = get_xpath_value($XPV); print "CompanyProducerID: $retval1 \nFirstName: $retval2\n"; sub get_xpath_value { my ($argvalx) = @_; print "argvalx: $argvalx\n"; my $xpath = "q!" . $argvalx . "!"; print "doing XPATH query on $xpath\n"; my @nodes = $root->findnodes($xpath); for (@nodes){ print $_->text; return $_->text; } } ./twig4.pl -xmlfile=a2b9f375-51fe-41a1-86ab-069561517890.xml argvalx: //Party[@id=//Relation[child::RelationRoleCode[@tc="37"]]/@Re +latedObjectID]/Producer/CarrierAppointment/CompanyProducerID doing XPATH query on q!//Party[@id=//Relation[child::RelationRoleCode[ +@tc="37"]]/@RelatedObjectID]/Producer/CarrierAppointment/CompanyProdu +cerID! Query: q!//Party... ^^^ Invalid query somewhere around here (I think)

      This was one problem, you don't need to my $xpath = "q!" . $argvalx . "!";

      see http://perldoc.perl.org/perlop.html#Quote-Like-Operators

      and the second XPATH was missing a [] here [@tc="8"]].
      Assuming you will only get a single match try

      #!perl use strict; use XML::Twig::XPath; my $xmlfile = $ARGV[0] || 'txlife.xml'; my $twig = XML::Twig::XPath->new(); $twig->parsefile($xmlfile); my $root = $twig->root; my @XPV = (); $XPV[0] = '//Party[@id=//Relation[child::RelationRoleCode[@tc="37"]]/@ +RelatedObjectID]/Producer/CarrierAppointment/CompanyProducerID'; $XPV[1] = '//OLifE/Party[@id=//OLifE/Relation[RelationRoleCode[@tc=8]] +/@RelatedObjectID]/Person/FirstName'; for my $i (0..1){ my ($name,$value) = get_xpath_value($XPV[$i]); print " $name : $value\n"; } sub get_xpath_value { my ($xpath) = @_; my @nodes = $root->findnodes($xpath); my $value = $nodes[0]->text; my $name = $nodes[0]->getName; return ($name,$value); }
      Update : added getName and simplified
      poj

        My most humble thanks.. I think that get's me exactly what I need to make this work.

        What I don't understand I guess is why in the original example you surrounded the XPath string with the q!..!? Just curious, I realize it doesn't matter with this solution.

        again, thanks.

      FWIW, xpather.pl, and xpath is also not afraid of whitespace
      $XPV[1] = q{ //Party[ @id = //Relation[ child::RelationRoleCode[ @tc="37" ] ] /@RelatedObjectID ] /Producer/CarrierAppointment/CompanyProducerID }; $XPV[1] = q{ //OLifE/Party[ @id=//OLifE /Relation[ RelationRoleCode[ @tc=8 ] ] /@RelatedObjectID ] /Person/FirstName };
Re^6: Xpath value query
by SDwerner (Initiate) on Sep 18, 2015 at 15:45 UTC
    my $xpath = q!//Party[@id=//Relation[child::RelationRoleCode[@tc='37'] +]/@RelatedObjectID]/Producer/CarrierAppointment/CompanyProducerID!; my @nodes = $root->findnodes($xpath); for (@nodes){ print $_->text; }

    OK, that seems to work... I think that was a big piece of the puzzle I was missing. I had not seen the Twig/Xpath module come up anywhere when I was googling.

    Thank you!