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

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

I have been trying to use XML Smart module to create some XML files and I’m having some problems getting element to nest properly. I’m new to this module I would appreciate if you could help me specify correct code that I need to use to create this simple XML structure:

<Shelf_Info> <switch Name="Puebla01"> <shelfType>7480</shelfType> <commentText>ATM Core switch</commentText> </switch> <switch Name="Puebla02"> <shelfType>7440</shelfType> <commentText>ATM access switch</commentText> </switch> </Shelf_Info>

So far I managed to create elements for one occurrence of switch data in the above example but I don’t know how to get it to build the structure for second, third,….occurrence. This is what I have:

my $XML = XML::Smart->new() ; $XML->{Shelf_Info} ; $XML->{Shelf_Info}{switch}{Name} = "$pp"; $XML->{Shelf_Info}{switch}{shelfType} = '15000'; $XML->{Shelf_Info}{switch}{shelfType}->set_node(1); $XML->{Shelf_Info}{switch}{commentText} = "$comment"; $XML->{Shelf_Info}{switch}{commentText}->set_node(2); $XML->save('test.xml') ;

So, how do I get it to create the second lot (switch Name="Puebla02”) without overriding the first one?

Regards Kon

Replies are listed 'Best First'.
Re: Creating nested elements in XML::Smart
by bitingduck (Chaplain) on Dec 12, 2012 at 08:02 UTC

    This seems to work:

    use strict; use warnings; use XML::Smart; my @pp=qw(Puebla01 Puebla02); my @shelf=qw(7480 7440); my @comment=("ATM Core switch","ATM access switch"); my $XML = XML::Smart->new() ; my $count=0; foreach (@pp){ $XML->{Shelf_Info}{switch}[$count]{Name} = "$_"; $XML->{Shelf_Info}{switch}[$count]{shelfType} = $shelf[$count]; $XML->{Shelf_Info}{switch}[$count]{shelfType}->set_node(1); $XML->{Shelf_Info}{switch}[$count]{commentText} = "$comment[$count +]"; $XML->{Shelf_Info}{switch}[$count]{commentText}->set_node(2); $count++; } $XML->save('test.xml') ;

    It seems to want array refs to iterate over nodes.

Re: Creating nested elements in XML::Smart
by Jenda (Abbot) on Dec 12, 2012 at 14:34 UTC
    use XML::Rules; my $parser = XML::Rules->new(rules => {}, ident => ' '); print $parser->toXML( Shelf_Info => { switch => [ {Name => "Puebla01", shelfType => [7480], commentText => ['ATM + Core switch']}, {Name => "Puebla02", shelfType => [7440], commentText => ['ATM + access switch']}, ] });

    Not XML::Smart though. It makes use of the fact that the value of a tag attribute may only be a single string, not a hash or array so it's clear that the shelfType and commentText must be a child tag, not an attribute. Generally XML::Rules attempts to create the simplest possible XML that'd contain the data and attribute is considered simpler than child tag.

    Update: With version 1.16 I just uploaded to CPAN, it'd be even simpler:

    use XML::Rules ToXML => { ident => ' ' }; print ToXML( Shelf_Info => { switch => [ {Name => "Puebla01", shelfType => [7480], commentText => ['ATM + Core switch']}, {Name => "Puebla02", shelfType => [7440], commentText => ['ATM + access switch']}, ] });

    You may now instantiate a parser and import a subroutine that'll call the specified method on that instance to simplify the usage.

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

Re: Creating nested elements in XML::Smart
by choroba (Cardinal) on Dec 14, 2012 at 07:01 UTC
    A solution using XML::XSH2, a wrapper around XML::LibXML.
    #!/usr/bin/perl use warnings; use strict; use XML::XSH2; package XML::XSH2::Map; use constant { TYPE => 0, COMMENT => 1, }; our %Shelves = ( Puebla01 => [7480, 'ATM Core switch'], Puebla02 => [7440, 'ATM access switch'], ); package main; xsh << '__XSH__'; create Shelf_Info ; for my $shelf in { sort keys %Shelves } { my $switch := insert element switch append /Shelf_Info ; cd $switch ; set @Name $shelf ; set shelfType { $Shelves{$shelf}[TYPE] } ; set commentText { $Shelves{$shelf}[COMMENT] } ; } save :f 'test.xml' ; __XSH__
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ