Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

XML::Simple : element vs. attribute in XMLout

by rovf (Priest)
on May 26, 2010 at 12:43 UTC ( #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>

Comment on XML::Simple : element vs. attribute in XMLout
Select or Download Code
Replies are listed 'Best First'.
Re: XML::Simple : element vs. attribute in XMLout
by ikegami (Pope) 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 (Deacon) 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
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? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (14)
As of 2015-07-30 16:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (273 votes), past polls