XML:Simple and arrays of hashes

Discussion in 'Perl Misc' started by Richard Lawrence, Feb 24, 2005.

  1. Hi there,

    Consider the following XML in a file called "data.xml":

    <user>
    <name>Frank</name>
    <age>27</age>
    <friends>
    <friend>
    <name>Sue</name>
    <location>London</location>
    </friend>
    <friend>
    <name>Jane</name>
    <location>Paris</location>
    </friend>
    </friends>
    </user>

    If I use the following:

    #!/usr/bin/perl -w
    use strict;
    use XML::Simple;
    my $user = XMLin("data.xml");
    print "Hi, my name is " . $user->{name};
    print " and I am " . $user->{age} . " years old. ";
    print "My friends are ";
    # Begin horrible code
    my ($key, $value, $k, $v);
    while(($key, $value) = each %{$user->{friends}})
    {
    while(($k, $v) = each %{$value})
    {
    print "$k (who lives in " . $v->{location} . ") and ";
    }
    }
    # End horrible code
    print "thats it!\n";

    then I get the intended:

    Hi, my name is Frank and I am 27 years old. My friends are Sue (who
    lives in London) and Jane (who lives in Paris) and thats it!

    which is great.

    However as you have probably noticed from the code, the whole $key,
    $value, $k, $v and nested while's looks really horrible to me and I'm
    sure there is a far better way to do this.

    Can anyone advise on the best way to re-write this section whilst still
    maintaining readability?

    Many thanks in advance,

    Richard.
     
    Richard Lawrence, Feb 24, 2005
    #1
    1. Advertising

  2. Richard  Lawrence

    Anno Siegel Guest

    Richard Lawrence <> wrote in comp.lang.perl.misc:
    > Hi there,
    >
    > Consider the following XML in a file called "data.xml":
    >
    > <user>
    > <name>Frank</name>
    > <age>27</age>
    > <friends>
    > <friend>
    > <name>Sue</name>
    > <location>London</location>
    > </friend>
    > <friend>
    > <name>Jane</name>
    > <location>Paris</location>
    > </friend>
    > </friends>
    > </user>
    >
    > If I use the following:
    >
    > #!/usr/bin/perl -w
    > use strict;
    > use XML::Simple;
    > my $user = XMLin("data.xml");
    > print "Hi, my name is " . $user->{name};
    > print " and I am " . $user->{age} . " years old. ";
    > print "My friends are ";
    > # Begin horrible code
    > my ($key, $value, $k, $v);
    > while(($key, $value) = each %{$user->{friends}})
    > {
    > while(($k, $v) = each %{$value})
    > {
    > print "$k (who lives in " . $v->{location} . ") and ";
    > }
    > }
    > # End horrible code
    > print "thats it!\n";
    >
    > then I get the intended:
    >
    > Hi, my name is Frank and I am 27 years old. My friends are Sue (who
    > lives in London) and Jane (who lives in Paris) and thats it!
    >
    > which is great.
    >
    > However as you have probably noticed from the code, the whole $key,
    > $value, $k, $v and nested while's looks really horrible to me and I'm
    > sure there is a far better way to do this.


    First off, I don't think your xml structure represents very well the
    structure of the data. There is a superfluous level in your structure.
    But I'm not touching that.

    You're looping over keys that function as names of subfields. They
    should be addressed through fixed strings, like you do with "name" and
    "age". You know what they are, use your knowledge.

    Further, don't declare variables ahead of time, declare them when they
    are first used. And use reasonable variable names. $k and $v when
    $key and $value are already there is indeed horrible.

    So, replace you "horrible code" with something like this:

    my $friends = $user->{ friends}->{ friend}; # see the extra level?
    for my $name ( keys %$friends ) {
    my $location = $friends->{ $name}->{ location};
    print "$name (who lives in $location) and ";
    }


    The rest of your code isn't beyond critique either, but I'll let that
    go.

    Anno
     
    Anno Siegel, Feb 24, 2005
    #2
    1. Advertising

  3. Anno Siegel wrote:
    > First off, I don't think your xml structure represents very well the
    > structure of the data. There is a superfluous level in your

    structure.
    > But I'm not touching that.


    Thanks for this. I did wonder about the extra field myself but wasn't
    sure whether it was better form to place groups of data (eg. the
    friends) in a field of their own or not. I chose to do so and it seems
    like that probably wasn't the best - easy to fix though :)

    > The rest of your code isn't beyond critique either, but I'll let that
    > go.


    If you had the time then I would appreciated it if you did critique it.
    Otherwise I'll only continue making the same mistakes over and over
    again until someone else points them out.

    Having said that, I'm assuming its my usage of . to include the
    variables because I have no idea how to write:

    print "My name is $user->{name}\n";

    and actually get it to print correctly? Unfortunately my abilities to
    find something on Google or perldoc on how to handle this has failed me
    :(

    Thanks for your comments,

    Richard.
     
    Richard Lawrence, Feb 24, 2005
    #3
  4. Richard  Lawrence

    Anno Siegel Guest

    Richard Lawrence <> wrote in comp.lang.perl.misc:
    > Anno Siegel wrote:


    > > The rest of your code isn't beyond critique either, but I'll let that
    > > go.

    >
    > If you had the time then I would appreciated it if you did critique it.
    > Otherwise I'll only continue making the same mistakes over and over
    > again until someone else points them out.
    >
    > Having said that, I'm assuming its my usage of . to include the


    There's that, yes.

    > variables because I have no idea how to write:
    >
    > print "My name is $user->{name}\n";


    Exactly like that.

    Further, "use warnings" is preferable over "perl -w". With "use warnings"
    you can switch off individual warnings later.

    A third point concerns the piecewise printing of a larger chunk of
    output. I'd use a variable to collect it and print it in one go.
    Apart from efficiency consideration, the approach is more flexible
    if you want to re-arrange things or modify the final string.

    Anno
     
    Anno Siegel, Feb 25, 2005
    #4
  5. Anno Siegel wrote:
    > Further, "use warnings" is preferable over "perl -w". With "use

    warnings"
    > you can switch off individual warnings later.


    Thanks for this one!

    > A third point concerns the piecewise printing of a larger chunk of
    > output. I'd use a variable to collect it and print it in one go.
    > Apart from efficiency consideration, the approach is more flexible
    > if you want to re-arrange things or modify the final string.


    Agreed.

    To be honest, my whole use of poor variable names and multiple prints
    was to get a 10 line bit of code quickly working to understand the
    fundimentals on how to extract information from an XML file. Thankfully
    none of this would be used in a proper application.

    As for $user->{name}, I remembered that I'd been trying to use
    $user->{"name"} and of course this won't work if I simply plop that
    into a print. Something to remember.

    Many thanks for your advice, I have learnt some useful things :)

    Richard.
     
    Richard Lawrence, Feb 25, 2005
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ben Holness

    Hashes of Hashes via subs

    Ben Holness, Oct 5, 2003, in forum: Perl
    Replies:
    8
    Views:
    591
    Ben Holness
    Oct 8, 2003
  2. Steven Arnold

    using hashes as keys in hashes

    Steven Arnold, Nov 23, 2005, in forum: Ruby
    Replies:
    3
    Views:
    183
    Mauricio Fernández
    Nov 23, 2005
  3. kazaam
    Replies:
    12
    Views:
    295
    Matthias Wächter
    Sep 13, 2007
  4. Tim O'Donovan

    Hash of hashes, of hashes, of arrays of hashes

    Tim O'Donovan, Oct 27, 2005, in forum: Perl Misc
    Replies:
    5
    Views:
    235
  5. Replies:
    3
    Views:
    233
Loading...

Share This Page