Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

XML::Simple : element vs. attribute in XMLout

by rovf (Priest)
on May 26, 2010 at 12:43 UTC ( [id://841719]=perlquestion: print w/replies, xml ) Need Help??

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

I have a hash representing an XML structure, where a part of it basically looks like this (I've simplified it a bit):

... arr => { elem => [ { mod => 'mstring1', rp => 'rstring1', subarr => { subelem => [ {...}, {...}, ... ] } }, { mod => 'mstring2', rp => 'rstring2', subarr => { subelem => [ {...}, {...}, ... ] } }, } ...
This structure has been processed by XMLin, using the option forcearray => [ qw(arr subarr) ]. Currently, I'm writing out this structure without any options. XMLout produces the following structure on output:
... <arr> <elem mod="mstring1" rp="rstring1"> <subarr> <subelem>...</subelem> <subelem>...</subelem> </subarr> </elem> <elem mod="mstring2" rp="rstring2"> <subarr> <subelem>...</subelem> <subelem>...</subelem> </subarr> </elem> ... </arr> ...
In particular, mod and rp become attributes. Now my question: Is it possible to configure XMLout in a way, so that rp is turned in an attribute, but mod is turned into a element, i.e.
... <arr> <elem rp="rstring1"> <mod>mstring1</mod> <subarr> <subelem>...</subelem> <subelem>...</subelem> </subarr> </elem> <elem rp="rstring2"> <mod>mstring2</mod> <subarr> <subelem>...</subelem> <subelem>...</subelem> </subarr> </elem> ... </arr> ...
Can this be done with XMLout, or is XML::Simple too, eh, simple for this task?

-- 
Ronald Fischer <ynnor@mm.st>

Replies are listed 'Best First'.
Re: XML::Simple : element vs. attribute in XMLout
by ikegami (Patriarch) on May 26, 2010 at 14:18 UTC

    You need to change your tree from

    my $tree = { arr => { elem => [ { mod => 'mstring1', rp => 'rstring1', subarr => { subelem => [ {content=>'...'}, {content=>'...'}, ] } }, { mod => 'mstring2', rp => 'rstring2', subarr => { subelem => [ {content=>'...'}, {content=>'...'}, ] } }, ], } };
    to
    my $tree = { arr => { elem => [ { mod => { content => 'mstring1' }, <------ rp => 'rstring1', subarr => { subelem => [ {content=>'...'}, {content=>'...'}, ] } }, { mod => { content => 'mstring2' }, <------ rp => 'rstring2', subarr => { subelem => [ {content=>'...'}, {content=>'...'}, ] } }, ], } };

    This can be done programmatically.

    You can use ContentKey => ... to specify a name other than "content". I have used _text.

    If you're creating the tree using XMLin, use ForceContent => 1. Here's a round-trip example:

    use strict; use warnings; use Data::Dumper qw( Dumper ); use XML::Simple qw( ); local $XML::Simple::PREFERRED_PARSER = 'XML::Parser'; my $xs = XML::Simple->new( ForceArray => [qw( elem subelem )], ForceContent => 1, #ContentKey => '_text', KeyAttr => {}, KeepRoot => 1, ); my $tree = $xs->XMLin(<<'__EOI__'); <arr> <elem rp="rstring1"> <mod>mstring1</mod> <subarr> <subelem>...</subelem> <subelem>...</subelem> </subarr> </elem> <elem rp="rstring2"> <mod>mstring2</mod> <subarr> <subelem>...</subelem> <subelem>...</subelem> </subarr> </elem> </arr> __EOI__ { local $Data::Dumper::Indent = 1; print(Dumper($tree)); } print $xs->XMLout($tree);

    Update: I had originally phrased the reply as if the OP started from XML. Rearranged contents.
    Update: Added instructions on how to transform the tree programmatically.

      Instead of changing
      mod => 'mstring1',
      to:
      mod => { content => 'mstring1' },
      you could just change it to:
      mod => [ 'mstring1' ],
Re: XML::Simple : element vs. attribute in XMLout
by Krambambuli (Curate) on May 26, 2010 at 13:20 UTC
    It seems that if the structure would have been obtained using XMLin with

    forcearray => [ qw(arr mod subarr) ]
    then the hash would be what XMLOut needs. Wouldn't that fit ?

      This is likely correct. I haven't checked this yet, because I was hoping for a solution which would work with the *present* internal representation, because it would spare me from modifying existing code which already assumes the hash to be constructed in the way it is right now.

      -- 
      Ronald Fischer <ynnor@mm.st>

        You can always transform the tree programmatically before XMLout.

        for my $elem (@{ $tree->{arr}{elem} }) { $elem->{mod}{content} = delete($elem->{mod}); }

        For what it's worth, keep in mind your existing code will break if a mod element acquires an attribute. (Don't you love the fragility of XML::Simple?)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://841719]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (9)
As of 2024-04-23 10:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found