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

Hi everyone, I'm new with Perl and tried to parse the following xml file. I try thing's like libXML and other thing's, but I couldn't get values like code_a / name. Can someone Help me with this. Thanks in Advance Tiago
<?xml version="1.0"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envel +ope/"> <soapenv:Body> <dlwmin:getBookById xmlns:dlwmin="http://www.test.com/integration" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <result xmlns="http://www.test.com/integration/integration"> <status> <state>0</state> </status> <books> <num>12345</num> <book> <code_a>11111</code_a> <name>Come to the Dark Side 1st Ed</name> <otherVal>ABC</otherVal> <otherVal2>1999</otherVal2> </book> <book> <code_a>22222</code_a> <name>Come to the Dark Side 2nd Ed</name> <otherVal>ABC</otherVal> <otherVal2>2001</otherVal2> </book> <Title>Come to the Dark Side</Title> <typeOfBook>SciFi</typeOfBook> <writer>Darth Vader</writer> </books> </result> </dlwmin:getBookById> </soapenv:Body> </soapenv:Envelope>
Like I said before I'm new with perl :) 4 hours, I need to parse a lot of files in a Production Env, I tried the code bellow:
use strict; use warnings; use XML::LibXML; use XML::LibXML qw( ); my $parser = XML::LibXML->new(); my $doc = $parser->parse_file('out.xml'); for my $result ($doc->findnodes('/books/book')) { for my $interv ($result->findnodes('book')) { my $bk = $interv->find('code_a'); my $bk_name = $interv->find('name'); print("$bk - $bk_name"); } }
and this one (I couldn't understand how to interate with the hash):
use strict; use XML::Simple; use Data::Dumper; my $doc = XMLin('out.xml'); print Dumper($doc);
antoher thing the xml was in one line. thanks

Replies are listed 'Best First'.
Re: XML Parse
by choroba (Cardinal) on Jun 02, 2015 at 17:23 UTC
    You have to register the needed namespaces first. For example, in xsh, a wrapper around XML::LibXML:
    open file.xml ; register-namespace i http://www.test.com/integration/integration ; for //i:book echo (i:code_a) (i:name) ;
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: XML Parse
by jellisii2 (Hermit) on Jun 03, 2015 at 11:39 UTC
    You'll want to skip XML::Simple. Quoting:
    STATUS OF THIS MODULE ^
    
    The use of this module in new code is discouraged. Other modules are available which provide more straightforward and consistent interfaces. In particular, XML::LibXML is highly recommended.
    
    The major problems with this module are the large number of options and the arbitrary ways in which these options interact - often with unexpected results.
    
    Patches with bug fixes and documentation fixes are welcome, but new features are unlikely to be added.
    
    My typical contribution to these kinds of conversations are "Use XML::Twig".
Re: XML Parse
by Anonymous Monk on Jun 02, 2015 at 17:14 UTC
    Please show the code you used and explain the problems you had with it (error messages, etc.).
Re: XML Parse
by thargas (Deacon) on Jun 04, 2015 at 11:09 UTC

    Your key problem is that in the line:

    <result xmlns="http://www.test.com/integration/integration">

    The xmlns is declaring that everything contained in the result is in that namespace, so there are no, e.g., code_a named elements in the empty namespace, which is what your findnodes call is looking for. They are instead in the http://www.test.com/integration/integration namespace. As choroba notes, you'll have to register that namespace in order to be able to look for elements within it. So you'll need something like:

    my $xpc = XML::LibXML::XPathContext->new($doc); $xpc->registerNs('t', 'http://www.test.com/integration/integration'); foreach my $book_node ($xpc->findnodes('/t:books/t:book') ) { say "book name is " .$book_name->findvalue('/t:name'); }

    See also XML::LibXML::Node

Re: XML Parse
by Anonymous Monk on Jun 02, 2015 at 21:48 UTC