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

I had to tweak it just a bit... for some reason I was getting the error Can't use global $_ in "my" at ./twig3.pl line 15, near "my $_ " and I added passing the filename as a command line variable.

#!/usr/opt/perl5/bin/perl -sw # use strict; use XML::Twig; # my $xmlfile=@ARGV; my $twig = XML::Twig->new(); $twig->parsefile($xmlfile); my $root = $twig->root; my @nodes1 = $root->get_xpath('//Holding'); for my $hold (@nodes1){ print "\nId = ".$hold->att('id')."\n"; my @nodes2 = $hold->get_xpath('Policy/KeyedValue/KeyValue'); for $_ (@nodes2){ print $_->prev_sibling_text." = "; print $_->text."\n"; } } ./twig3.pl -xmlfile=a2b9f375-51fe-41a1-86ab-069561517890.xml Id = Holding_a344e55a-1471-4c90-aa94-481b434a5b12 AccountType = UTMA_UGMA CheckIndicator = No 1035ExchangeIncluded = No SponsorName = Transamerica Id = Holding_8f6e6000-6cc5-4e7a-b5e8-3acd2ee03468 OldProductType = 401K

this will get me on my way! Thank you, you help is much appreciated. Also a note, I've discovered during this adventure that the file is an ACORD standard file https://www.acord.org/standards/downloads/Pages/PCSPublic1.aspx for what its worth. Now I just need to figure out how to dissect the sub-attributes and insert them into the XPath.

Again, thank you.

Replies are listed 'Best First'.
Re^5: Xpath value query
by poj (Abbot) on Sep 17, 2015 at 20:58 UTC

    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

      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
        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 };
      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!