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

I've read through here, and trying to use some of the exampled, which work perfectly, sems straightforward. So what am I doing wrong? For this XML
<APPLIANCE_LIST_OUTPUT> <RESPONSE> <DATETIME>2014-06-27T13:38:55Z</DATETIME> <APPLIANCE_LIST> <APPLIANCE> <ID>76297</ID> <NAME>st0153</NAME> <SOFTWARE_VERSION></SOFTWARE_VERSION> <RUNNING_SCAN_COUNT>0</RUNNING_SCAN_COUNT> <STATUS>Online</STATUS> </APPLIANCE> <APPLIANCE> <ID>53489</ID> <NAME>THD-Mexico</NAME> <SOFTWARE_VERSION>2.6</SOFTWARE_VERSION> <RUNNING_SCAN_COUNT>0</RUNNING_SCAN_COUNT> <STATUS>Online</STATUS> </APPLIANCE> <APPLIANCE> <ID>76079</ID> <NAME>QAPLRScanner</NAME> <SOFTWARE_VERSION></SOFTWARE_VERSION> <RUNNING_SCAN_COUNT>0</RUNNING_SCAN_COUNT> <STATUS>Online</STATUS> </APPLIANCE> </APPLIANCE_LIST> </RESPONSE> </APPLIANCE_LIST_OUTPUT>
Why doesn't this work to output the STATUS node per line?
use XML::LibXML qw(); my $xml = XML::LibXML->load_xml(location => 'output.xml'); for ($xml->findnodes('//appliance_list_output[@status]')) { print $_->getAttribute('status') . "\n"; #print $_->getElementsbyTagName('status') . "\n"; print $_ . "\n"; }
Ive' tried various ways to do this, but no matter what irt doesn't seem to enter the "for" loop. BUt if I change the Xpath, it complains, so it seems to READ the XML and have it parsed correctly, but won't examine it? Stumped, thanks in advance...

Replies are listed 'Best First'.
Re: LibXML question
by AppleFritter (Vicar) on Jun 27, 2014 at 19:59 UTC

    Two things.

    First of all, XML is case-sensitive. appliance_list_output is not the same as APPLIANCE_LIST_OUTPUT, and the same goes for status and STATUS.

    Second (after reading up on XPath), you're not getting results because you're only querying for the status attributes of APPLIANCE_LIST_OUTPUT nodes, as opposed to STATUS nodes descended from them. Try the following:

    #!/usr/bin/perl use feature qw/say/; use XML::LibXML qw(); my $xml = XML::LibXML->load_xml(location => 'output.xml'); for ($xml->findnodes('//APPLIANCE_LIST_OUTPUT/descendant::STATUS/text( +)')) { say; }

    Here's the output:

    Online Online Online

    I've also used text() to select the text content of the status nodes, BTW. Leaving that out, you'd get "<STATUS>Online</STATUS>" for each node, rather than just "Online".

    Does this do what you want?

    BTW, here's a useful XPath tutorial site.

      Once you use the abbreviation // for /descendant::, you can use it in both places:
      //APPLIANCE_LIST_OUTPUT//STATUS/text()
      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ