Using XML::Simple to fill a list

M

Mark

Hi,

As a newbie, I'm trying to use XML::Simple and I'm not very
successful... So please help :)

Consider the following XML Schema:
<class name="SIMPLE">
<export>
<object class="Collection" name="cFIRST">
<Integer name="f1" constant="true">1</Integer>
<Integer name="f2" constant="true">2</Integer>
</object>
<object class="Collection" name="cSECOND">
<Integer name="aaa" constant="true">0</Integer>
<Integer name="bbb" constant="true">1</Integer>
</object>
<String name="myString" length="10"></String>
<Integer name="myInt">1</Integer>
</export>
</class>


I want to fill a list with all the elements under tag <export> as
following (as strings):
"cFIRST.f1"
"cFIRST.f2"
"cSECOND.aaa"
"cSECOND.bbb"
"myString"
"myInt"

I've written the following code but my list is always empty...

use XML::Simple;
use strict;
use warnings;

my $xml_in = $ARGV[0];
my $content = eval { XMLin($xml_in) };

print("I found an error in your XML: $@") if $@;

my @list = ();
my $nb;

foreach my $obj (keys %{$content->{class}->{export}->{object}}) {
my @obj = keys %{$content->{class}->{export}->{$obj}->{Integer}};
$nb = @obj;

print "For $obj there are $nb items\n" ;

foreach my $item (@obj) {
push (@list, "$obj.$item" )
};
}
$nb = @list;
printf "\nThere are $nb items in the list\n";
foreach my $i (@list) {
printf "$i\n";
}

I guess my problem is here : "->{$obj}->", but I still can't find how
to resolve it.

Thanks in advance for any help.
Any advice for optimization is also welcome.

Mark
 
R

Robert Gamble

Mark said:
Hi,

As a newbie, I'm trying to use XML::Simple and I'm not very
successful... So please help :)

Consider the following XML Schema:
<class name="SIMPLE">
<export>
<object class="Collection" name="cFIRST">
<Integer name="f1" constant="true">1</Integer>
<Integer name="f2" constant="true">2</Integer>
</object>
<object class="Collection" name="cSECOND">
<Integer name="aaa" constant="true">0</Integer>
<Integer name="bbb" constant="true">1</Integer>
</object>
<String name="myString" length="10"></String>
<Integer name="myInt">1</Integer>
</export>
</class>


I want to fill a list with all the elements under tag <export> as
following (as strings):
"cFIRST.f1"
"cFIRST.f2"
"cSECOND.aaa"
"cSECOND.bbb"
"myString"
"myInt"

I've written the following code but my list is always empty...

use XML::Simple;
use strict;
use warnings;

my $xml_in = $ARGV[0];
my $content = eval { XMLin($xml_in) };

print("I found an error in your XML: $@") if $@;

my @list = ();
my $nb;

foreach my $obj (keys %{$content->{class}->{export}->{object}}) {
my @obj = keys %{$content->{class}->{export}->{$obj}->{Integer}};
$nb = @obj;

print "For $obj there are $nb items\n" ;

foreach my $item (@obj) {
push (@list, "$obj.$item" )
};
}
$nb = @list;
printf "\nThere are $nb items in the list\n";
foreach my $i (@list) {
printf "$i\n";
}

I guess my problem is here : "->{$obj}->", but I still can't find how
to resolve it.

Thanks in advance for any help.

Use Data::Dumper to display the actual structure of the object returned
by XMLin:

use XML::Simple;
use strict;
use warnings;
use Data::Dumper;

my $xml_in = $ARGV[0];
my $content = eval { XMLin($xml_in) };
print Dumper($content);

You can then see that the data structure is not quite what you were
expecting. You need to change the following to achieve the desired
results:

....
foreach my $obj (keys %{$content->{export}->{object}}) {
my @obj = keys %{$content->{export}->{object}->{$obj}->{Integer}};
....

This will print:

For cFIRST there are 2 items
For cSECOND there are 2 items

There are 4 items in the list
cFIRST.f1
cFIRST.f2
cSECOND.bbb
cSECOND.aaa

Use a similiar method to access "myString" and "myInt" if needed. You
might also want to review the options to XML::Simple dealing with how
XMLin creates the resulting data structure.

Rob Gamble
 
M

Mark

Hi,

Thanks for your help Robert,

However I've got an error for String (as for Integer)

PERL(test3.pl): Can't use string ("myString") as a HASH ref while
"strict refs"
in use at test3.pl line 43.
Can't use string ("myString") as a HASH ref while "strict refs" in use
at test3.
pl line 43.

for the following code:
#####################
#Strings
{
foreach my $obj (keys
%{$content->{class}->{export}->{String}->{name}})
{
print " $obj ; $content->{class}->{export}->{String}->{$obj}\n";
#$hash{"$obj"} = 0;
};
}
#####################

It fails on the call to keys function:
keys %{$content->{class}->{export}->{String}->{name}}

But,

If I remove the "->{name}" from this line I have the following output:
length ; 10
name ; myString

Wich is better but still not what I want... because I need only
"myString" :-(

That means that from the following XML, I want only the "name" as an
item:
<String name="myString" length="10"></String>

Should I try any option while calling XMLIn like KeyAttr or anything
else? For the moment my tests are unsuccessful... I'm feeling lost ...
no answer via google or FAQ that I read

TIA for your help,

Mark
 
M

Mark

OK. Now I found a "work around" but I got a strange behavior if I have
more than one String, it works. Otherwise (for one) I receive the list
of "properties" of the String object (length and name)

Here is my code:
{
my $all_strings = $content->{class}->{export}->{String};
foreach my $string (keys%{$all_strings}) {
print "- $string\n";
}
}

And I still do not understand what's going on...
 
R

Robert Gamble

Mark said:
OK. Now I found a "work around" but I got a strange behavior if I have
more than one String, it works. Otherwise (for one) I receive the list
of "properties" of the String object (length and name)

Here is my code:
{
my $all_strings = $content->{class}->{export}->{String};
foreach my $string (keys%{$all_strings}) {
print "- $string\n";
}
}

And I still do not understand what's going on...

What you need to do is use Data::Dumper to print out the structures
that XMLin creates for each scenerio and see how they differ when you
have more than one element of the same type. Then review the
XML::Simple documentation for options that control this behavior to
your liking.

Robert Gamble
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,171
Messages
2,570,935
Members
47,472
Latest member
KarissaBor

Latest Threads

Top