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

Hi Monks,

Once again I am fighting with XML. I would like to get values set for 'value': where the 'field name="Name"' and 'class="FILENAME' and where 'field name="Size"'. (independent the class)

The (simplified) version of the XML file is as follows:

<?xml version="1.0" encoding="UTF-16" standalone="yes"?> <files> <xml version="12.0.0.1" /> <file name="Image"> <item> <field name="Name" value="Smile.JPG" class="FILENAME"/> <field name="Compression" value="0" class="INFO"/> <field name="Type" value="OS" class="INFO"/> <field name="Size" value="4120893467kB" class="RAM"/> </item> <item> <field name="Name" value="WALLPAPER.JPG" class="FILENAME"/> <field name="Compression" value="1" class="INFO"/> <field name="Type" value="OS" class="INFO"/> <field name="Size" value="2MB" class="DISK"/> </item> </file> </files>

This is what I have so far:

#!/usr/bin/env perl use warnings; use strict; use feature qw{ say }; use XML::LibXML; my $dom = 'XML::LibXML'->load_xml(location => 'imgfile.xml'); say 'XML Version is: ', $dom->version; say 'Document encoding is: ', $dom->encoding; # RETURNS ONLY WHERE name="Name" IN ONE ITEM for my $fileline ( $dom->findnodes('/files/file[@name="Image"]/item/fi +eld[@name="Name"]') ) { say 'Name : ', $fileline->getAttribute('value'); } # RETURNS ALL VALUES IN ONE ITEM for my $fileline ( $dom->findnodes('/files/file[@name="Image"]/item/fi +eld') ) { say 'Value: ', $fileline->getAttribute('value'); } # NOT WORKING for my $fileline ( $dom->findnodes('/files/file[@name="Image"]/item') +) { say 'Name : ', $fileline->getAttribute('field[@name="Name"]/value' +); say 'Size : ', $fileline->getAttribute('field[@name="Size"]/value' +); }

Anyone can help?

The great mistake is to anticipate the outcome of the engagement; Let nature take its course, and your tools will strike at the right moment.

Replies are listed 'Best First'.
Re: LibXML: Can't get value
by poj (Abbot) on Mar 16, 2017 at 18:03 UTC

    You can use logical operators on the attributes.

    #!/usr/bin/env perl use warnings; use strict; use feature qw{ say }; use XML::LibXML; my $dom = 'XML::LibXML'->load_xml(location => 'imgfile.xml'); say 'XML Version is: ', $dom->version; say 'Document encoding is: ', $dom->encoding; my $query = '(@name="Name" and @class="FILENAME") or (@name="Size")'; my $xpath = '/files/file[@name="Image"]/item/field['.$query.']'; for my $node ( $dom->findnodes($xpath) ) { print "\n"; say 'Name : ', $node->getAttribute('name'); say 'Class : ', $node->getAttribute('class'); say 'Value : ', $node->getAttribute('value'); }
    poj

      Hi,

      You can use also whitespace in xpath

      my $xpath = q{ /files /file[@name="Image"] /item/field[ ( @name="Name" and @class="FILENAME" ) or @name="Size" ] }; for my $node ( $dom->findnodes($xpath) )
Re: LibXML: Can't get value
by Lotus1 (Vicar) on Mar 16, 2017 at 20:37 UTC

    The getAttribute method just takes the name of the attribute for its parameter, not an xpath statement from what I could tell. The way poj did it is likely better but this is a quick fix to your program.

    # NOW WORKING for my $fileline ( $dom->findnodes('/files/file[@name="Image"]/item') +) { my ($namenode) = $fileline->findnodes('field[@name="Name"]'); my ($sizenode) = $fileline->findnodes('field[@name="Size"]'); say 'Name : ', $namenode->getAttribute('value'); say 'Size : ', $sizenode->getAttribute('value'); }

      Thank you! Issue solved perfectly.

      In fact, thanks to all for again helping me in such a useful way!

      --
      The great mistake is to anticipate the outcome of the engagement; Let nature take its course, and your tools will strike at the right moment.