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

I've been working through this, trying to follow the recommendations and reading recommended information in books etc. I hope this is a vast improvement in both presentation and coding style over my initial posting

My Array Reference keeps wiping itself no matter what I do, so i'm doing something wrong obviously. I suspect i'm incorrectly using the reference in the loop, but... Also, if there is a proper method for me to adjust and repost this, please advise

As always *bow* and thank-you for your previous help

A basic XML example with proper formatting I think

<?xml version="1.0" encoding="UTF-8" ?> <GeocodeResponse> <status>OK</status> <result> <type>postal_code</type> <formatted_address>Edmonton, BC V2M 4M7, Canada</formatted +_address> <address_component> <long_name>V2M 4M7</long_name> <short_name>V2M 4M7</short_name> <type>postal_code</type> </address_component> <geometry> <location> <lat>29.1153940</lat> <lng>-133.8394480</lng> </location> </geometry> </result> </GeocodeResponse>

The code from what I can grasp so far (Someone previously supplied me with basic XML ripping code, however it didn't parse correctly, so I improved this method considerably before reposting it. I'm limited in XML mods, so this is how i'm making sure I can run this on ANY server without permission)

print "<br>Content-type: text/html \n\n"; my @lines = split /\n/, $content; #--content = above XML data my $depth=0; my @myarray; my $currVar; #--Declare/Set foreach my $line (@lines) { if($line =~ m/\?xml version/) { # DO NOTHING as this is useless header info } elsif($line =~ m/\<(.*)\>(.*)\<\/.*\>/) { #--THIS is DATA $currVar=\$myarray; #--Create reference to main array for ($i = 1; $i <= $depth; $i++) { #--Create the variable +reference $currVar=\@currVar[$arrayKey[$i]]; } $currVar[$1]=$2; } elsif($line =~ /^\s{0,4}\<\/(.*)\>/) { #--Array depth decrea +se $depth--; } elsif($line =~ /^\s{0,4}\<(.*)\>$/) { #--Array depth decr +ease $depth++; $arrayKey[$depth]=$1; #--Keep track of the variable names +according to depth } } print "<br>STATUS = ".$myarray[GeocodeResponse][status]." <---THIS + should say OK";

Expected output as array: (I hand typed this, but it should be close) Ok, Anonymous Monk told me this isn't even close to Perl format, so i'm making another version below it that I hope is Perl

$myarray=[GeocodeResponse]=[ status="OK", result=[ type="postal_code", formatted_address="Edmonton, BC V2M 4M7, Canada", address_component=[ long_name="V2M 4M7", short_name="V2M 4M7", type="postal_code" ], geometry=[ location=[ lat=29.1153940, lng=-133.8394480 ], ], ], ]

Hopefully Perl format... based on "Modern Perl", but i'll probably get it wrong too. Need to learn it though, so I don't mind at all being told whats wrong or ridiculed a little ;) Perl variables are apples to oranges compared to LUA

# creates a single array, not an array of arrays my @array_of_arrays = ( 1 .. 10, ( 11 .. 20, ( 21 .. 30 ) ) );
@array_of_arrays = ( status="OK", result=( type="postal_code", formatted_address="Edmonton, BC V2M 4M7, Canada", address_component=( long_name="V2M 4M7", short_name="V2M 4M7", type="postal_code" ), geometry=( location=( lat=29.1153940, lng=-133.839448 ) ) ) )

Replies are listed 'Best First'.
Re: Working through it...
by chromatic (Archbishop) on Sep 10, 2011 at 23:12 UTC

    What output do you get?

                $currVar=\$myarray; #--Create reference to main array

    Do you mean instead $currVar = \@myarray;?

    What do you expect this to do?

    for ($i = 1; $i <= $depth; $i++) { #--Create the variable +reference $currVar=\@currVar[$arrayKey[$i]]; } $currVar[$1]=$2;

    This is incredibly fragile to whitespace changes, which are generally meaningless in XML:

    elsif($line =~ /^\s{0,4}\<\/(.*)\>/) { #--Array depth decrease

    This should give a bareword error if you're using strict, unless there's meaningful code you haven't shown:

    print "<br>STATUS = ".$myarray[GeocodeResponse][status]."

    I think the other response is correct that you want to use a hash, not an array, but I can't make sense of this code. You're honestly much, much better off using a real XML parser. I know you think that's going to be more work, but it's not. It's really not.

    Improve your skills with Modern Perl: the free book.

      I guess its because no-one knows what i'm tring to do because my code is so rudimentary. Previously I was using hashes, then was told to instead use arrays, so I did that with limited success. Almost had it working in fact, then it collapsed. I'll go back to hashes because I DO NEED the named indexes. I'll fully read that next recommended section a couple times re hashes

      Do you mean instead $currVar = \@myarray;?

      Using the @ was causing errors for me

      What do you expect this to do? for ($i = 1; $i <= $depth; $i++) { $currVar=\@currVar[$arrayKey[$i]]; }

      This is supposed to make the reference to the variable according to depth, so I can then enter a value. @arrayKey contains all of the variable names, so the loop just inserts them in order, creating the reference

      if($line =~ /^\s{0,4}\<\/(.*)\>/) {

      The data this code will receive has 0-4 spaces depending on the depth of the value. I'm sure there's a better way to do it, but for now it works

      I know you think that's going to be more work, but it's not. It's really not

      If I only use mods, i'd most certainly succeed. But i'm trying to learn HOW to do this at the same time. I've bashed my head into walls numerous times, but the picture is becoming clearer, more and more reading, more attempts, days of failed code attempts. More recommendations on things to read, subtle improvements each time(Note: my server admin is a cow and only allows some mods. My other server only allows other mods, I need a new server)

      As always, thank-you for your input *bow*

        Using the @ was causing errors for me

        Right. Array elements and hash values can only be scalars. What do you expect $currVar[$arrayKey[$i]] to contain?

        But i'm trying to learn HOW to do this at the same time.

        I've been writing Perl 5 professionally since 1998. I probably could write robust XML parsers in multiple languages, but I never do because it's really not worth the time getting things right. I'm sure I'd learn a few things doing it even with my experience, but that's not worth it either, because parsing XML is tricky.

        You're just learning how to use arrays and hashes in Perl. You've already spent several days getting this far; expect to spend at least that long figuring out robust parsing of the XML you've shown. Your reach exceeds your grasp, which is not a bad thing, but you've chosen a particularly pernicious task to learn.

        I don't mean to discourage you from learning. Certainly you have a lot to admire in sticking with this task—but what you'll learn by using a module in this case is very much more valuable right now at your level of Perl understanding than all the work necessary to make a robust XML parser.

        Improve your skills with Modern Perl: the free book.

Re: Working through it...
by Khen1950fx (Canon) on Sep 11, 2011 at 01:26 UTC
    FYI, your XML formatting is better. You could make it even better by using XML::Tidy. In the bin folder, you'll find xmltidy. Just run:
    xmltidy myxml.xml
    and it's done. For example, I ran your xml though xmltidy:
    <?xml version="1.0" encoding="utf-8"?> <GeocodeResponse> <status>OK</status> <result> <type>postal_code</type> <formatted_address>Edmonton, BC V2M 4M7, Canada</formatted_address +> <address_component> <long_name>V2M 4M7</long_name> <short_name>V2M 4M7</short_name> <type>postal_code</type> </address_component> <geometry> <location> <lat>29.1153940</lat> <lng>-133.8394480</lng> </location> </geometry> </result> </GeocodeResponse>
Re: Working through it...
by Anonymous Monk on Sep 10, 2011 at 22:46 UTC

    Expected array: (I hand typed this, but it should be close)

    You hand typed nonsense (or possibly Lua) :) that is not perl syntax!!!

    In perl, associative arrays are called hash, and named starting with % character and are accessed using { } not [ ]

    Regular arrays, non-associative arrays, are called array, and named starting with @ character and are accessed using [ ] not { }

      Yes, LUA style format so my feeble little brain can grasp the layout and access. I'm reading from "Modern Perl" for the information regarding arrays. I thought that format was correct based on the examples, but the examples didn't deal with depth either, soooo...

      @ and are matching formats in my head

      I'll try and correct the resulting table format now

        I'm reading from "Modern Perl" for the information regarding arrays.

        Arrays use numeric indexes. You probably want hashes, because they use strings as keys. You should also review the Nested Data Structures section.

        Improve your skills with Modern Perl: the free book.