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

I've been trying to figure out how to determine if a key (Voltage) exists in my xml file and finally settled on...

test.xml - <Settings ModelNumber="1" SerialNumber="13"> - <Channels> <Channel Name="FSC" Voltage="12" Threshold="15" /> <Channel Name="SSC" Voltage="10" Threshold="20" /> </Channels> - <Pods> </Pods> </Settings> use XML::Simple; $inst_set= XMLin($file); foreach my $Channel(@{$inst_set->{Channels}->{Channel}}){ if($Channel->{Voltage}){$settings_file=$file} #if the Voltage exis +ts, it must be the settings file } }

This works, i just KNOW this is not an elegant solution, and therefore probably not the most reliable, so looking for some feedback. Having made this work, now need to change the Voltage value in the original xml. Has anyone got recommendation on best module to use to modify the original file? Thanks Chris

Replies are listed 'Best First'.
Re: confirming key in xml?
by Anonymous Monk on Apr 06, 2015 at 21:30 UTC

    The thing about XML::Simple is that it is sometimes just too simple (more e.g. here).

    XML::LibXML + XPath solution:

    use XML::LibXML; my $dom = XML::LibXML->load_xml(location=>'test.xml'); my @nodes = $dom->findnodes('/Settings/Channels/Channel[@Voltage]'); print @nodes ? "Found it!\n" : "Didn't Find it!\n";

      This worked...of course...and probably marks my transition from XML::Simple to XML::LibXML. Thanks Monks, for your support and enthusiasm! C

        I should add tho, that it took about 6 hours to install XML::LibXML on my machine! Thanks activestate, for showing my your shortcomings before i asked my boss to drop a bundle on a corporate package!

Re: confirming key in xml?
by pme (Monsignor) on Apr 06, 2015 at 21:35 UTC
    Hi ccherri,

    You can use XML::Simple to do modifications too:

    use XML::Simple; my $inst_set = XMLin( 'test.xml', KeepRoot => 1 ); foreach my $Channel (@{$inst_set->{Settings}->{Channels}->{Channel}}) +{ if ( $Channel->{Voltage} ) { print "Old voltage: $Channel->{Voltage} -- "; $Channel->{Voltage} *= 2.0; print "New voltage: $Channel->{Voltage}\n"; } } my $xml = XMLout( $inst_set, KeepRoot => 1 ); print $xml;
    Update:'KeepRoot' was added in according to AM's comments below.

      XML::Simple is incredibly brittle when it comes to writing and especially round-tripping XML. For a perfect example of this read this thread. Sorry, but I have to strongly recommend against XML::Simple in this case. Recommendations for other XML modules given e.g. here.

      ... In fact, this code is actually a good example of some of the issues one has to deal with when using XML::Simple to write XML... did you notice that it changed the name of the root node from Settings to opt? Sure, there are options to fix that, but the previously linked thread is a wonderful example of the corners one can paint oneself into.

        Thanks for pointing out the missing 'KeepRoot'.
      "You can use XML::Simple..."

      Some quirks with XML::Simple have been mentioned by some illuminated bros - but there is XML::LibXML::Simple

      Regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

Re: confirming key in xml?
by Lotus1 (Vicar) on Apr 07, 2015 at 19:37 UTC

    Others have been down the same path. This node shows how to do what you want.

    You'll have better luck searching for examples if you use the correct terms. In your example 'Voltage' is an attribute of the element 'Channel'.

Re: confirming key in xml?
by locked_user sundialsvc4 (Abbot) on Apr 06, 2015 at 23:26 UTC

    After spending too-long telling myself that “XPath expressions can’t be ‘the right way’ to query an XML structure,” I have done a complete about-face.   XPath is declarative way to ask for what you need to find, and it works.   So, avoid writing code that is dependent upon the structure of the XML document, for the same reasons that you should avoid (hand-)writing recursive-descent parsers.   (No, no, no hard-and-fast rules here, but the time you save will be your own.)

    In the process, I have also settled on XML::LibXML.   This module is an interface to libxml2, which is the de facto binary library for managing “XML everything.”   One of the main reasons why I like to use it, now, is that there’s a very good chance that I am using the same library, to do my part of the job, that my erstwhile data-exchange partner used, or will use, to do his.