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

updated: i should have include a little more complex xml the first time. looking at page 213 of "Learning XML", it would appear that not even rudimentery xpath expressions are handled. or... i am sadly mistaken. trying "lastChild()" and "firstChild()" yielded same results! *sigh* hello, tried to use discussion for xml::dom::lite on cpan, but no response... looking for a module that is "pure perl" that does xpath. if i have some xml fragment like:
<quotelist> <quotation style="wise" id="q4"> <source> Juan Ramon Jiminez </source> <quotation id="q5" style="political"> <source> Thomas Jefferson </source> </quotation> </quotelist>
what is the proper to way to get the "id" attribute's value? what is the proper way to get the string "political" and the string "Thomas Jefferson" returned? what i am trying:
use warnings; use strict; use Data::Dumper; use XML::DOM::Lite qw( Parser XPath ); my $doc = Parser->parseFile( '/rshome/jaw2/xml/practice.xml' ); my $result1 = XPath->evaluate( 'quotelist/quotation[@id="q5"/@style', +$doc ); print Dumper $result1; my $result2 = XPath->evaluate( '/quotelist/quotation[id="q5"]/source/t +ext()', $doc ); print Dumper $result2;
i thought i would get "Thomas Jefferson" with this. not finding enough xpath examples to know if i am even using xpath correctly. i have both "XML in a Nutshell" and "Learning XML". thanks in advance for advice and pointers.

Replies are listed 'Best First'.
Re: trying to use XML::DOM::Lite
by whereiskurt (Friar) on Jul 03, 2007 at 01:42 UTC

    jim:

    You are right that the documentation out there is a bit tough. That being said, though, here's my first XML::DOM::Lite snipper ever ;-)

    use warnings; use strict; use Data::Dumper; use XML::DOM::Lite qw( Parser XPath ); my $doc = Parser->parseFile( 'test.xml' ); my $node = $doc->selectSingleNode('quotelist/quotation[@id="q5"]/sourc +e'); print $node->firstChild()->nodeValue();

    This uses your XPath query (minus the @) and gets the text from 'Node' object. (See the documentation for more info on what you can do with node object.)

    BTW - I used the output from the 'Data::Dumper' to confirm that the 'Thomas Jefferson' was in the output, and with that I knew the XPath was correct.

    The tricky part is realising that nodes can have multiple children (apparently!)

    Anyway! Hope that get things off to a good start for you!

    Kurt

    PS: Happy Birthday Canada!!

    Updated code for requested output.

      i have since given up on XML::DOM::Lite. here is my complete xml document copied out of "Learning XML":
      <?xml version="1.0"?> <quotelist> <quotation style="wise" id="q1"> <text>Expect nothing; be ready for anything.</text> <source>Samuri Chant</source> </quotation> <quotation style="political" id="q2"> <text>If one morning I walked on top of the water across the Potom +ac River, the headline that afternoon would read "President Can't Swim."</text> <source>Lyndon B. Johnson</source> </quotation> <quotation style="silly" id="q3"> <?human laugh?> <text>What if the hokey-pokey IS what it's all about?</text> </quotation> <quotation style="wise" id="q4"> <text>If they give you ruled paper, write the other way.</text> <source>Juan Ramon Jiminez</source> </quotation> <!-- the checkbook is mighter than the sword? --> <quotation style="political" id="q5"> <text>Banking establishments are more dangerous than standing armies.</text> <source>Thomas Jefferson</source> </quotation> </quotelist>
      this code:
      use warnings; use strict; use Data::Dumper; use XML::LibXML; my $parser = XML::LibXML->new; my $doc = $parser->parse_file( 'practice.xml' ); my $xpath = '/quotelist/quotation[@id="q5"]/source/text()'; my $result = $doc->find( $xpath ); print Dumper $result->string_value; exit 0;
      produces: $VAR1 = 'Thomas Jefferson';

      will go back to XML::DOM::Lite when i have more time. for the time being concentrating on XML::LibXML which because we have seven unixen and ms-windows to compile for, creates new and improved headaches. :)

        never did get XML::DOM::Lite to do what i wanted, but that could easily be my misunderstanding the doc. wanted to share my experiences with LIB::LibXML.

        i was able to compile, test, install for axp, ibm, sgi, hp (pa-risc), rhe3(linux), and sun 5.8.

        special notes:
        * check the generated makefile very carefully for correct include path and libary path. neither of the two methods for spcifying the libxml2 work correctly on all platforms. (putting path to xml2-config in your PATH nor XMLPREFIX=... to Makefile.PL). will try to figure that out and report to authors.
        * on hp11 if one sees: /usr/lib/pa20_64/dld.sl: '/lib/pa20_64/libpthread.1' contains a static TLS reference to '__thread_specific_seg' defined in a dynamically loaded library '/lib/pa20_64/libpthread.1'. Use +tls=dynamic to re-compile '/lib/pa20_64/libpthread.1'. then set and export LD_PRELOAD=/lib/pa20_64/libpthread.1
        * on linux, be sure to ensure that you are not linking with native lbxml2

        meanwhile my little test program:
        use warnings; use strict; use Data::Dumper; use XML::LibXML; my $parser = XML::LibXML->new; my $doc = $parser->parse_file( 'practice.xml' ); my $xpath1 = '/quotelist/quotation[source = "Thomas Jefferson"]/@style +'; my $result1 = $doc->find( $xpath1 ); print Dumper $result1->string_value; my $xpath2 = '/quotelist/quotation[@id="q5"]/source/text()'; my $result2 = $doc->find( $xpath2 ); print Dumper $result2->string_value; exit 0;
        produces:
        $VAR1 = 'political'; $VAR1 = 'Thomas Jefferson';
        yea! hth someone.