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

Hi all, yes, I am in need of some Perl Wisdom :)
I have a script which parses an XML file to Excell. All goes fine, but I'm quite stuck on the referencing.
My current xml looks like this:
<root> <SUB CLASSNAME="SUB1"> <Element1 Type="Type1">Type 1 value</Element1> <Element2 Type="Type2">Type 2 value</Element2> </SUB> </root>
But I don't know ( I know, it's simple but I don't get it) how to parse an xml looking like this...
<SUB CLASSNAME="SUB1"> <INNERSUB CLASSNAME="INNERSUB1"> <Element1 Type="Type1">Content</element1> <Element2 Type="Type2">Content</element2> </INNERSUB> </SUB>
How do I reach Type and Content now ?? (My working script is linked at the bottom with full xml) This is a piece of my code:
my $xs1 = XML::Simple->new(); my $doc = $xs1->XMLin($file, keyattr=>['CLASSNAME'], ForceContent=>1, +ForceArray=>1); use Data::Dumper; local $Data::Dumper::Indent=1; for my $sub ( sort keys %{ $doc->{SUB} } ){ $rowCount = $tellerR; $worksheet->Cells($rowCount, $colCount)->{Value} = $sub; for my $elem ( sort keys %{ $doc->{SUB}{$sub} } ){ for my $element ( @{ $doc->{SUB}{$sub}{$elem} } ){ $worksheet->Cells($rowCount, $colCount)->{Value} = $$element{Type}; $worksheet->Cells($rowCount, $colCount)->{Value} = $$element{content}; } }
The complete working script is at: Script file
and an example xml as well : The XML
And even as a ZIP/RAR at : Rar Package
Feel free to dowload and reuse. But please help me out

Replies are listed 'Best First'.
Re: Newbie XML Simple reference
by ig (Vicar) on Nov 03, 2008 at 18:58 UTC

    The following script

    #!/usr/bin/perl -- use strict; use warnings; use XML::Simple; use Data::Dumper; my $file = "test.xml"; my $xs1 = XML::Simple->new(); my $doc = $xs1->XMLin($file, keyattr=>['CLASSNAME'], ForceContent=>1, +ForceArray=>1); print Dumper($doc); foreach my $element (keys %{$doc->{INNERSUB}->{INNERSUB1}}) { print "$element\n"; print "\tType:\t$doc->{INNERSUB}->{INNERSUB1}->{$element}[0]-> +{Type}\n"; print "\tContent:\t$doc->{INNERSUB}->{INNERSUB1}->{$element}[0 +]->{content}\n"; } exit(0);

    With test.xml containing:

    <SUB CLASSNAME="SUB1"> <INNERSUB CLASSNAME="INNERSUB1"> <Element1 Type="Type1">Content</element1> <Element2 Type="Type2">Content</element2> </INNERSUB> </SUB>

    Produces

    $VAR1 = { 'INNERSUB' => { 'INNERSUB1' => { 'Element2' => [ { 'Type' => 'Type +2', 'content' => 'C +ontent' } ], 'Element1' => [ { 'Type' => 'Type +1', 'content' => 'C +ontent' } ] } }, 'CLASSNAME' => 'SUB1' }; Element2 Type: Type2 Content: Content Element1 Type: Type1 Content: Content

    Update: If the syntax for accessing nested data structures is not familiar, you might have a look at perlreftut.

Re: Newbie XML Simple reference
by toolic (Bishop) on Nov 03, 2008 at 19:16 UTC
    XML::Twig is nice too:
    use strict; use warnings; use XML::Twig; my $xfile = <<EOF; <SUB CLASSNAME="SUB1"> <INNERSUB CLASSNAME="INNERSUB1"> <Element1 Type="Type1">Content</Element1> <Element2 Type="Type2">Content</Element2> </INNERSUB> </SUB> EOF my $t= new XML::Twig(); $t->parse($xfile); my $sub = $t->root(); for my $elm ($sub->first_child('INNERSUB')->children()) { print $elm->name(), "\n"; print $elm->att('Type'), "\n"; print $elm->text(), "\n\n"; } __END__ Element1 Type1 Content Element2 Type2 Content

    Note: I had to modify your "element" end tags to be "Element", for legal XML.

Re: Newbie XML Simple reference
by grantm (Parson) on Nov 03, 2008 at 21:57 UTC
    It sounds like your problem is due to not understanding Perl references rather than XML::Simple. This node might help you to get up to speed on both.
      Thanks for the link. The next hours I will look into my script again. But first I'll check out your node link.
      I checked the link(s) but now I am more worried I will not be able to make my script. Perl is, imo, quite complicated if you never saw referencing like that. How can I get a list of attributes within an element ?
      Like for this xml
      <node class="1" name="name1" type="type1" ... >
      What outputs this:
      You have 3 attributes:
      class
      name
      type
      ?
      Without using the node in code... So in a loop, and not like {node} , that is not how to program
      Keep in mind that I use the XML::Simple.
      Thanks so much for the help !!!
        Do your part, set it up.
Re: Newbie XML Simple reference
by Anonymous Monk on Nov 04, 2008 at 11:18 UTC
      Maybe that is because I am struggling with the referencing !
      Sorry Guys, I am a Perl noob. My problem is that I cannot spend time studying this language. My boss wont let me
      I need an output like this:

      This is the output i am looking for,
      "You have 2 tags: node and node
      In node you have attribute type and name with values k and n"
      for this xml
      XML
      ----
      <XML> <element> <node type="k" name="n"/> <node type="i" name="q"/> </element> </XML>
      Dummy Code
      #!/usr/bin/perl -- use strict; use warnings; use XML::Simple; my $xs1 = XML::Simple->new(); my $doc = $xs1->XMLin($file, keyattr=>['????'], ForceContent=>1, Force +Array=>1); use Data::Dumper; local $Data::Dumper::Indent=1; print Dumper($doc); for my $sub ( sort keys %{ $doc->{????} } ){ for my $elem ( sort keys %{ $doc->{????}->{$sub} } ){ } }