Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!

I am working on a program that has to read a large xml file, I have a sample here of both, Perl and xml file, and its driving me crazy, I can get an attribute from a duplicated node into my variable to print, where and what am I missing here please!
Thanks, and here is a sample code of what I am trying to do:

#!/perl/bin/perl use strict; use CGI qw/:standard/; use CGI::Carp qw(fatalsToBrowser); use XML::XPath; use XML::XPath::XMLParser; print header(); my $xp = XML::XPath->new(filename => 'test_x.xml'); foreach my $row ($xp->findnodes('/HOME/Trans')) { # extract from the XML my $trans = $row->find('//@ID')->string_value; my $cert = $row->find('Cert')->string_value; my $cert = $row->find('/AD/@XREF')->string_value; my $fname = $row->find('AD/FName')->string_value; my $lname = $row->find('AD/LName')->string_value; my $bdate = $row->find('AD/BDate')->string_value; my $no = $row->find('AD/No')->string_value; my $state = $row->find('AD/State')->string_value; my $ssss = $row->find('AD/SSSS')->string_value; my $train = $row->find('AD/Train')->string_value; my $volume = $row->find('AD/Volume')->string_value; my $cno = $row->find('AD/CNo')->string_value; my $id = $row->find('AD/ID')->string_value; print "1-$trans - 2-$cert - 3-$cert - 4-$fname - 5-$lname - 6-$bdate - + 7-$no - 8-$state - 9-$ssss - 10-$train - 11-$volume - 12-$cno - + 13-$id\n"; } =comment test_x.xml <?xml version="1.0"?> <HOME> <Trans ID="0164754"> <Cert>8280164754</Cert> <AD XREF="DELTA1"> <FName>Joe</FName> <LName>Frost</LName> <BDate>19650420</BDate> <No>X0000000</No> <State>RI</State> <Date>19980401</Date> <SSSS>07</SSSS> <Train>N</Train> <Volume>N</Volume> </AD> <AD XREF="DELTA2"> <FName>MARY </FName> <LName>FROST</LName> <BDate>19861107</BDate> <No>Y0000000</No> <State>NY</State> <Date>20030824</Date> <SSSS>00</SSSS> <Train>Y</Train> <CNo>153</CNo> <ID>WC204338</ID> <Volume>N</Volume> </AD> <Total>111</Total> </Trans> </HOME> =cut

Replies are listed 'Best First'.
Re: XML Path and Perl
by derby (Abbot) on Feb 25, 2008 at 20:30 UTC

    Do you want the first child? The last child? All the kids? If just the first:

    my $xref = $row->find('AD[1]/@XREF')->string_value;
    If just the last:
    my $xref = $row->find('AD[last()]/@XREF')->string_value;
    If all ... well ... that's where my XPATH foo breaks down.

    -derby
      How would I print the values for all the nodes, like this node shows twice, <AD XREF...>, and all the nodes after that.
      I have to get everything!

        Dude ... it's right there in the first couple of lines of XML::XPath:

        my $nodeset = $row->find('AD'); foreach my $node ( $nodeset->get_nodelist ) { my $xref = $node->find( '@XREF' )->string_value; my $fname = $node->find( 'FName')->string_value; my $lname = $node->find('LName')->string_value; my $bdate = $node->find('BDate')->string_value; my $no = $node->find('No')->string_value; my $state = $node->find('State')->string_value; my $ssss = $node->find('SSSS')->string_value; my $train = $node->find('Train')->string_value; my $volume = $node->find('Volume')->string_value; my $cno = $node->find('CNo')->string_value; my $id = $node->find('ID')->string_value; print "1-$trans - 2-$cert - 3-$xref - 4-$fname - 5-$lname - 6-$b +date - 7-$no - 8-$state - 9-$ssss - 10-$train - 11-$volume - 12- +$cno - 13-$id\n"; }

        but then again ... I prefer to use XSLT for stuff like this ... I love the pain

        -derby
Re: XML Path and Perl
by Anonymous Monk on Feb 25, 2008 at 20:28 UTC
    Let me correct this line:
    Wrong: my $cert = $row->find('/AD/@XREF')->string_value; Correct: my $xref = $row->find('//@XREF')->string_value;

    Print this:
    print "1-$trans - 2-$cert - 3-$xref - 4-$fname - 5-$lname - 6-$bdate - + 7-$no - 8-$state - 9-$ssss - 10-$train - 11-$volume - 12-$cno - + 13-$id - 14-$total\n";