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

Hi, I'm using XML::Simple for parsing some configuration files. All works fine except that XML::Simple tends to "simplify" the structure of the XML file, so that if I do a XMLin(), then a XMLout(), I usually don't get the same format back, although the contents are equivalent. For example:
<config ip="127.0.0.1" port="12345"> <timeout>1000</timeout> </config>
tends to give me (I did try setting a few options):
<config ip="127.0.0.1" port="12345" timeout="1000"/>
When I need to share the configuration structure with another application, this can become a problem.

So is there a simple way to set the options (or some other means) with XML::Simple that can make sure the in-out round trip gives exactly the same structure?

Thanks

Replies are listed 'Best First'.
Re: Keeping XML structure with XML::Simple
by hbo (Monk) on Jul 21, 2004 at 04:44 UTC
    From perldoc XML::Simple
    ForceArray => 1 (in) (IMPORTANT!) This option should be set to ’1’ to force nested elements to be represented as arrays even when there is only one. Eg, with ForceArray enabled, this XML: <opt> <name>value</name> </opt> would parse to this: { ’name’ => [ ’value ] } instead of this (the default): { ’name’ => ’value } This option is especially useful if the data structure is likely to be written back out as XML and the default behaviour of rolling single nested elements up into attributes is not desirable.
    Setting that option will make it easier to not mangle your XML. But XML::Simple shows its limitations when you try use it to write your XML. It's really best when used as it was originally intended, as a config reader.
Re: Keeping XML structure with XML::Simple
by pg (Canon) on Jul 21, 2004 at 07:11 UTC

    I am not really that concerned, as long as the DOM tree still keeps logically equivalent, although you can argure that a child is not a property, but well...

    The first thing came up in my mind was this testing, which I felt interesting, mostly triggered by your post:

    use XML::Simple; use strict; use warnings; my $xml = XMLin('<config ip="127.0.0.1" port="12345"><timeout>1000</ti +meout><timeout>2000</timeout></config>'); print XMLout($xml);

    The output was:

    <opt ip="127.0.0.1" port="12345"> <timeout>1000</timeout> <timeout>2000</timeout> </opt>

    I am satisfied.

      Are you happy that 'config' was replaced by 'opt'? If that is not the desired behaviour, instead write,
      my $xml = XMLin(..., KeepRoot => 1); print XMLout($xml, KeepRoot => 1);
      which would correctly output:
      <config ip="127.0.0.1" port="12345">
        <timeout>1000</timeout>
        <timeout>2000</timeout>
      </config>
      
      The KeepRoot option tells XML::Simple that your structure already has a root node.
        Just want to point out that the <timeout> element did not get fold up into attributes in your example is because there are more than one of them, by default if there is only one <timeout>, it will be folded up into an attribute.
Re: Keeping XML structure with XML::Simple
by graff (Chancellor) on Jul 21, 2004 at 06:01 UTC
    Hmmm... so XML::Simple could be used to get recommendations on how to improve the style/design of an XML stream. I like that.