http://www.perlmonks.org?node_id=495200

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

The other day I ran into a situation where I wanted to add an xml node to an existing xml structure. Initially, I chose to insert the node using XML::Simple. The key was that I needed to ensure that I didn't change the XML structure of the original, other than the addition of a single node. However I quickly realized that the XML structure of the output was not the same as the input to XMLin.

Here is my sample:

use strict; use warnings; use XML::Simple; my $filename = "sample_file.xml"; my $xs = XML::Simple->new(keeproot=>1, forcearray=>1); my $xmlString; { $/++; $xmlString = <DATA>; } my $data_hr = $xs->XMLin($xmlString); my $resultXMLString = $xs->XMLout($data_hr); print "$resultXMLString\n"; ## ## RESULT: ## ##<a> ## <FOOFOOFOOFOO> ## <m>foofoo 44444</m> ## <pm>barbarbar222</pm> ## <mfg someid="2345">xyzzy</mfg> ## <r>nn23v</r> ## <s>555</s> ## </FOOFOOFOOFOO> ##</a> ## ## ## __DATA__ <a id="FOOFOOFOOFOO"> <s>555</s> <m>foofoo 44444</m> <pm>barbarbar222</pm> <r>nn23v</r> <mfg someid='2345'>xyzzy</mfg> </a>

Notice that the a node has an attribute on input, however it does not have one on the result. On the other hand, the attribute of node mfg is symmetrical.

With a deadline looming, I ended up using XML::LibXML to read the xml into DOM and then add the node.

This leads to my philosophical question:

Is this where XML::Simple breaks down and I should opt to use XML::LibXML instead? The documentation for XML::Simple alludes to this by saying that

If your needs are not so simple, this may not be the mod­ ule for you. In that case, you might want to read the section on "WHERE TO FROM HERE?".

I guess what I wanted to do was pretty simple....

Also, after reviewing this situation (for this posting) I have further discovered that the behaviour I see is only related to the root node. If the root node has an attribute, it is not translated back to an attribute for the root node.

For example, the following code works as I expect, however the node I want to modify isn't the top node:

use strict; use warnings; use XML::Simple; my $filename = "sample_file.xml"; my $xs = XML::Simple->new(keeproot=>1, forcearray=>1); my $xmlString; { $/++; $xmlString = <DATA>; } my $data_hr = $xs->XMLin($xmlString); my $resultXMLString = $xs->XMLout($data_hr); print "$resultXMLString\n"; ## ## RESULT: ## ##<someotherroot> ## <a name="FOOFOOFOOFOO"> ## <m>foofoo 44444</m> ## <mfg someid="2345">xyzzy</mfg> ## <pm>barbarbar222</pm> ## <r>nn23v</r> ## <s>555</s> ## </a> ##</someotherroot> ## ## ## __DATA__ <someotherroot> <a id="FOOFOOFOOFOO"> <s>555</s> <m>foofoo 44444</m> <pm>barbarbar222</pm> <r>nn23v</r> <mfg someid='2345'>xyzzy</mfg> </a> </someotherroot>

Hazah! I'm Employed! (But not necessarily happily employed.)

Replies are listed 'Best First'.
Re: XML::Simple Oddities and/or Philosophy
by runrig (Abbot) on Sep 26, 2005 at 20:08 UTC
    The problem is the way attributes of "id" (and "name and "key" ) are handled. Try using "KeyAttr=>[]" to ignore the default.

      Duhooo!

      I tried several combinations of adding things to keyattr, however I didn't consider blanking it out.

      From the documentation:

      The default value for 'keyattr' is [ 'name', 'key', 'id' ]. Setting this option to an empty list will dis­ able the array folding feature.

      Thank you very much for your feedback.

      Hazah! I'm Employed!

Re: XML::Simple Oddities and/or Philosophy
by izut (Chaplain) on Sep 26, 2005 at 20:13 UTC
    This works:
    #!/usr/bin/env perl use strict; use warnings; use XML::Simple; my $xs = XMLin(\*DATA, ForceArray => 1, KeyAttr => { item => 'id', },) +; XMLout($xs, OutputFile => 'out.xml'); __DATA__ <someotherroot> <a id="FOOFOOFOOFOO"> <s>555</s> <m>foofoo 44444</m> <pm>barbarbar222</pm> <r>nn23v</r> <mfg someid='2345'>xyzzy</mfg> </a> </someotherroot>
    You were missing the KeyAttr option in XMLin.


    Igor S. Lopes - izut
    surrender to perl. your code, your rules.
Re: XML::Simple Oddities and/or Philosophy
by planetscape (Chancellor) on Sep 27, 2005 at 06:09 UTC
Re: XML::Simple Oddities and/or Philosophy
by leriksen (Curate) on Sep 27, 2005 at 07:03 UTC
    In my opinion, XML::Simple is not the tool to use for this kind of work, especially as the complexity of your XML documents increases

    XML::Simple is a great tool for

    • reading XML into a perl data structure
    • writing a perl data structure out to XML where the actual layout doesnt matter, only the well-formedness

    By that second point I mean, you aren't contrained by someone elses DTD or XSD - there layout is important e.g. the <name> element must come before the <address> element if the XSD says so, but because XML::Simple is outputting a hash with 'name' and 'address' keys, you cant control that (well, you can, but you have to tie the hash to a package that will sort the keys for you)

    In my opinion, if your going to be writing elements/nodes to an XML document, and you dont want to perturb any other parts of the document, your better off using an XML module that supports XPath navigation to locate your insert point, and using its API to insert the required nodes.

    This is more robust than tweaking XML::Simple's many options to keep the source and result documents the same.

    Another option is XSLT, but that's a whole other technology to master...

    ...reality must take precedence over public relations, for nature cannot be fooled. - R P Feynmann

      leriksen thank you for your comments. That's what I was looking for out of my post. Some indication of how others decide when to choose one tool over another.

      Thanks!

      Hazah! I'm Employed!

Re: XML::Simple Oddities and/or Philosophy
by grantm (Parson) on Sep 28, 2005 at 00:26 UTC