CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
iterating through an array using XML::Simple

 



skysurf
New User

Oct 22, 2012, 6:46 PM

Post #1 of 9 (1009 views)
iterating through an array using XML::Simple Can't Post

Hello,

I am new to Perl and trying to write a Perl program to read in an XML file and generate C code (a pointer array of 246 variables) based on the XML file contents. I was having trouble using a numeric variable for a 'for' loop in the array for XML::Simple and wondering if someone can provide insight on what I am doing wrong. The code looks like this,

use XML::Simple;

use Data::Dumper;

$xml = new XML::Simple (KeyAttr=>[]);

#read XML files

$conf_data = $xml->XMLin("tempConfigDataFile.xml");



open CFILE, ">ACM_FM.c";


print_global_defs();

sub print_global_defs

{

my @FC_Names = @{ $conf_data->{'SW-SYSTEMS'}->{'SW-SYSTEM'}->{'CONF-SPEC'}->{'CONF-ITEMS'}->{'CONF-ITEM'} };

my $FC_Count = @FC_Names;

for(my $i = 0; $i < $FC_Count; $i++) {

print CFILE "&", @FC_Names['$i']->{'CONF-ITEMS'}->{'CONF-ITEM'}->{'CONF-ITEMS'}->{'CONF-ITEM'}->[0]->{VT}, "}\n";

}

}

The problem is that inside the 'for' loop, the variable $i in @FC_Names['$i] always gets evaluated to 0 and it always returns the same element (first one) from the XML file. Thus the c file gets printed out with the same element (the first one) repetatively instead of all the elements consecutively.

Can anyone tell me how to correctly reference the numeric variable 'i' inside the array FC_Names so that the correct value of i is used as an index insde the array such that the correct element of the XML file is referenced?

I would appreciate any help.

Thanks!




Laurent_R
Enthusiast / Moderator

Oct 23, 2012, 2:06 AM

Post #2 of 9 (1005 views)
Re: [skysurf] iterating through an array using XML::Simple [In reply to] Can't Post

Don't use quotes marks around $i in your array subscript. That's probably what is wrong.


rovf
Veteran

Oct 23, 2012, 5:31 AM

Post #3 of 9 (999 views)
Re: [Laurent_R] iterating through an array using XML::Simple [In reply to] Can't Post


Quote
Don't use quotes marks around $i in your array subscript.


This too, but there are more problems with this (and the OP would have found out that something is wrong if he had enabled strict and warnings).

Still, I wonder, why this code did not die; maybe there is some obscure feature in Perl which I don't know yet? Consider the code snippet of the posting:


Code
@FC_Names['$i']->


You were of course correct in mentioning, that the array index must be a number, not a string. However, the OP claimed that element 0 was always selected, and this piece of code certainly does not supply a zero.

Further, wie see that the OP uses an array slice, not an array element. How is it possible to apply the arrow operator, if the left argument is a slice (i.e. a list) instead of a scalar? Obviously it does something (instead of just terminating with an error message)....


(This post was edited by rovf on Oct 23, 2012, 5:32 AM)


skysurf
New User

Oct 23, 2012, 7:28 AM

Post #4 of 9 (994 views)
Re: [rovf] iterating through an array using XML::Simple [In reply to] Can't Post

Thanks for the feedback.

However when I remove the quote around the $i inside the array, I receive an error for that line: "Not a Hash reference".

Would appreciate some more help.


Laurent_R
Enthusiast / Moderator

Oct 23, 2012, 10:55 AM

Post #5 of 9 (991 views)
Re: [skysurf] iterating through an array using XML::Simple [In reply to] Can't Post

A short test under de Perl debugger:



Code
  DB<8> @c = qw /foo bar baz/ 

DB<9> x @c
0 'foo'
1 'bar'
2 'baz'
DB<10> $i = 0

DB<11> print $c['$i']
foo
DB<12> $i = 1

DB<13> print $c['$i']
foo
DB<14> $i = 2

DB<15> print $c['$i']
foo
DB<16> print $c[$i]
baz


As you can see, when I use '$i' as index of the array, I get only the first element of the array, irrespective of the value of $i, as if '$i' was evaluated to 0 in this context (which happens when you evaluate a string in a numeric context). You really need to remove the single quote marks.

With double quote marks, it would work:




Code
  DB<17> print $c["$i"] 
baz


I think that your use of an array slice is also probably an error. You should probably prefix your array name with $ instead of @ (on the line where you are using the $i subscript).


(This post was edited by Laurent_R on Oct 24, 2012, 2:21 AM)


rovf
Veteran

Oct 24, 2012, 1:34 AM

Post #6 of 9 (986 views)
Re: [Laurent_R] iterating through an array using XML::Simple [In reply to] Can't Post

Yes, I see that it *does* behave in that way; and of course if we enforce warnings, we get Argument "...." isn't numeric in array element. What I am interested to know is however, according to which language rule evaluates $array['string'] to the first element of an array? Intuitively, I would have expected to either throw an exception, or maybe that undef would be returned.


Laurent_R
Enthusiast / Moderator

Oct 24, 2012, 2:39 AM

Post #7 of 9 (983 views)
Re: [rovf] iterating through an array using XML::Simple [In reply to] Can't Post

As I said, when evaluated in a numeric context, a non-numeric string yields 0.

Try for example:


Code
  DB<7> print int ('foo') 
0
DB<8> print sin('bar')
0
DB<9>print cos ("boom")
1
DB<10> print log('baz')
Can't take log of 0 at (eval 14)[/usr/lib/perl5/5.10/perl5db.pl:638] line 2.

DB<11> print "foo" + 1
1
DB<12>


But if the string starts with one or several number(s), this will return the value of the initial number(s):



Code
  DB<13> print int "7foo" 
7
DB<14> print int "foo7"
0
DB<15> print log '7bar'
1.94591014905531
DB<16>


Since 0 is the subscript of the first element of an array, that's what you get if you evaluate $array['string'].

But I agree that it would be bad practice to rely on this and that warnings should be enforced.


rovf
Veteran

Oct 24, 2012, 3:45 AM

Post #8 of 9 (977 views)
Re: [Laurent_R] iterating through an array using XML::Simple [In reply to] Can't Post


Quote
As I said, when evaluated in a numeric context, a non-numeric string yields 0.


Ah, sorry, I skipped that part!!!! Thanks for explaining.

Do you, by chance, also have an explanation, why having an array slice as left argument to the arrow operator, doesn't fail? After all, the OP didn't have $FC_Names['string']->, but @FC_Names['string']->.... From perldoc perlop:


If the right side is ... "{...}" ...,
then the left side must be .... a hard or symbolic reference to ... a hash ....


In our case, the left side is an array slice, i.e. a list. I don't know whether the -> operator forces its left argument to scalar context, but even if it does, it would return the number of arguments in the slice (i.e. 1), not a reference.


Laurent_R
Enthusiast / Moderator

Oct 24, 2012, 4:13 AM

Post #9 of 9 (975 views)
Re: [rovf] iterating through an array using XML::Simple [In reply to] Can't Post

I have no idea, but it definitely looks wrong to me, because it does not make sense to dereference an array slice.

However, it seems that the compiler accepts it if the slice has only one element:



Code
DB<3> $array[0]{bar} = "foo" 

DB<4> x @array
0 HASH(0x200d1c10)
'bar' => 'foo'
DB<5> print @array[0]->{bar}
foo


Even more strangely, if I add a second element to the array of hashes and take a real array slice:


Code
  DB<8> $array[1]{bar} = "baz"; 

DB<9> print @array[0..1]->{bar}
baz


So it seems that, in this case, it takes the last element of the array slice.


(This post was edited by Laurent_R on Oct 24, 2012, 8:25 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives