Want true instantiated objects from XML

Discussion in 'Perl Misc' started by /usr/ceo, Oct 12, 2008.

  1. /usr/ceo

    /usr/ceo Guest

    I've had a need for this at points in the past, but was always able to
    code around it (and still could even now), but I'd really like to be
    able to do this, and I can't find anything out there that does this
    exactly as I want. (Which tends to make me believe what I want
    wouldn't be as immediately useful as maybe I would think it to be,
    but...?!)

    Given an object defined as this:

    package Person;

    use strict;
    use warnings qw( all );

    sub new {
    my $proto = shift;
    my $class = ref $proto || $proto;
    my %attrs = @_;
    my $self = {};

    # Nevermind the error checking for attributes right now.

    $self->{__name} = $attrs{name};
    $self->{__age} = $attrs{age};

    bless $class, $self;

    return $self;
    }

    # RW attributes.

    sub name { $s = shift; $s->{__name} = shift if @_; return $s-
    >{__name} }

    sub age { $s = shift; $s->{__age} = shift if @_; return $s->{__age} }

    # Methods.

    sub sayName { print "My name is: " . shift->{__name} . "\n" }
    sub sayAge { print "I am " . shift->{__age} . " years old.\n" }

    1;

    I want to be able to read the following XML and create instances of
    Person from each instance in the XML:

    <xml>
    <People>
    <Person name="John Doe" age="22" />
    <Person name="Jane Doe" age="23" />
    <Person name="Maxx Doogan" age="10" />
    </People>
    </xml>

    So I get an array of Person objects which I can then write:

    my @people; # Hold the array of Person object created from the XML
    above.

    for my $person (@people) {
    $person->sayName();
    $person->sayAge();
    }

    I've looked through SOAP::Lite (and SOAP::Serialize and
    SOAP::Deserialize). I'm a fairly frequent user of XML::Simple, but
    Simple doesn't do the above (AFAIK). SURELY *something* like this is
    "out there" (read "CPAN") but I can't seem to find it; only things
    close to it (like SOAP::SOM objects that require an xpath of sorts and
    my methods are still not available through an instantiated method of
    just the data [object attributes] in XML.)

    Thanks!
    /usr/ceo
    /usr/ceo, Oct 12, 2008
    #1
    1. Advertising

  2. /usr/ceo

    Zed Pobre Guest

    /usr/ceo <> wrote:
    > I've looked through SOAP::Lite (and SOAP::Serialize and
    > SOAP::Deserialize). I'm a fairly frequent user of XML::Simple, but
    > Simple doesn't do the above (AFAIK). SURELY *something* like this is
    > "out there" (read "CPAN") but I can't seem to find it; only things
    > close to it (like SOAP::SOM objects that require an xpath of sorts and
    > my methods are still not available through an instantiated method of
    > just the data [object attributes] in XML.)


    I would do it with XML::Twig, myself, though there are other options.

    #!/usr/bin/perl
    use strict; use warnings
    use Person;
    use XML::Twig;

    my $twig = XML::Twig->new();
    $twig->parse(\*DATA);

    my ($name, $age);
    my $person;
    my @personslist;
    my @xmlpersons = $twig->root->descendants('Persons');

    foreach my $element (@xmlpersons)
    {
    $name = $element->att('name');
    $age = $element->att('age');
    $person = Person->new('name' => $name, 'age' => $age);
    push(@personslist,$person);
    }

    __DATA__
    <xml>
    <People>
    <Person name="John Doe" age="22" />
    <Person name="Jane Doe" age="23" />
    <Person name="Maxx Doogan" age="10" />
    </People>
    </xml>

    ##########

    You're looking for something like that?

    --
    Zed Pobre <> a.k.a. Zed Pobre <>
    PGP key and fingerprint available on finger; encrypted mail welcomed.
    Zed Pobre, Oct 13, 2008
    #2
    1. Advertising

  3. /usr/ceo

    Guest

    On Sun, 12 Oct 2008 14:01:14 -0700 (PDT), "/usr/ceo" <> wrote:

    >I've had a need for this at points in the past, but was always able to
    >code around it (and still could even now), but I'd really like to be
    >able to do this, and I can't find anything out there that does this
    >exactly as I want. (Which tends to make me believe what I want
    >wouldn't be as immediately useful as maybe I would think it to be,
    >but...?!)
    >
    >Given an object defined as this:
    >
    >package Person;
    >
    >use strict;
    >use warnings qw( all );
    >
    >sub new {
    > my $proto = shift;
    > my $class = ref $proto || $proto;
    > my %attrs = @_;
    > my $self = {};
    >
    > # Nevermind the error checking for attributes right now.
    >
    > $self->{__name} = $attrs{name};
    > $self->{__age} = $attrs{age};
    >
    > bless $class, $self;
    >
    > return $self;
    >}
    >
    ># RW attributes.
    >
    >sub name { $s = shift; $s->{__name} = shift if @_; return $s-
    >>{__name} }

    >sub age { $s = shift; $s->{__age} = shift if @_; return $s->{__age} }
    >
    ># Methods.
    >
    >sub sayName { print "My name is: " . shift->{__name} . "\n" }
    >sub sayAge { print "I am " . shift->{__age} . " years old.\n" }
    >
    >1;
    >

    The above is all very impressive. What do you want to do?

    >I want to be able to read the following XML and create instances of
    >Person from each instance in the XML:
    >
    ><xml>
    ><People>
    > <Person name="John Doe" age="22" />
    > <Person name="Jane Doe" age="23" />
    > <Person name="Maxx Doogan" age="10" />
    ></People>
    ></xml>
    >


    So XML parsing is holding you up?

    >So I get an array of Person objects which I can then write:
    >
    >my @people; # Hold the array of Person object created from the XML
    >above.
    >
    >for my $person (@people) {
    > $person->sayName();
    > $person->sayAge();
    >}
    >
    >I've looked through SOAP::Lite (and SOAP::Serialize and
    >SOAP::Deserialize). I'm a fairly frequent user of XML::Simple, but
    >Simple doesn't do the above (AFAIK). SURELY *something* like this is
    >"out there" (read "CPAN") but I can't seem to find it; only things
    >close to it (like SOAP::SOM objects that require an xpath of sorts and
    >my methods are still not available through an instantiated method of
    >just the data [object attributes] in XML.)
    >
    >Thanks!
    >/usr/ceo



    rxparse version 2

    sln
    , Oct 13, 2008
    #3
  4. /usr/ceo

    /usr/ceo Guest

    On Oct 12, 6:17 pm, Zed Pobre <> wrote:
    > /usr/ceo <> wrote:
    > > I've looked through SOAP::Lite (and SOAP::Serialize and
    > > SOAP::Deserialize).  I'm a fairly frequent user of XML::Simple, but
    > > Simple doesn't do the above (AFAIK).  SURELY *something* like this is
    > > "out there" (read "CPAN") but I can't seem to find it; only things
    > > close to it (like SOAP::SOM objects that require an xpath of sorts and
    > > my methods are still not available through an instantiated method of
    > > just the data [object attributes] in XML.)

    >
    > I would do it with XML::Twig, myself, though there are other options.
    >
    > #!/usr/bin/perl
    > use strict; use warnings
    > use Person;
    > use XML::Twig;
    >
    > my $twig = XML::Twig->new();
    > $twig->parse(\*DATA);
    >
    > my ($name, $age);
    > my $person;
    > my @personslist;
    > my @xmlpersons = $twig->root->descendants('Persons');
    >
    > foreach my $element (@xmlpersons)
    > {
    >     $name = $element->att('name');
    >     $age = $element->att('age');
    >     $person = Person->new('name' => $name, 'age' => $age);
    >     push(@personslist,$person);
    >
    > }
    >
    > __DATA__
    > <xml>
    > <People>
    >     <Person name="John Doe" age="22" />
    >     <Person name="Jane Doe" age="23" />
    >     <Person name="Maxx Doogan" age="10" />
    > </People>
    > </xml>
    >
    > ##########
    >
    > You're looking for something like that?


    Well that's definitely pretty nice. It's about halfway between what I
    want and what I thought I was going to have to do, which was close to
    what you wrote -- I just hadn't looked at XML::Twig. This is close
    enough to what I want without providing a schema upfront (which is why
    I think it would be a little difficult to write something smart enough
    to marshall to and from XML since XML is for all intents and purposes,
    free-format.)

    I think the XML::Twig hit will be helpful and I'll probably do that.

    Thanks!
    /usr/ceo
    /usr/ceo, Oct 13, 2008
    #4
  5. /usr/ceo

    /usr/ceo Guest

    On Oct 12, 6:46 pm, wrote:
    > On Sun, 12 Oct 2008 14:01:14 -0700 (PDT), "/usr/ceo" <> wrote:
    > >I've had a need for this at points in the past, but was always able to
    > >code around it (and still could even now), but I'd really like to be
    > >able to do this, and I can't find anything out there that does this
    > >exactly as I want.  (Which tends to make me believe what I want
    > >wouldn't be as immediately useful as maybe I would think it to be,
    > >but...?!)

    >
    > >Given an object defined as this:

    >
    > >package Person;

    >
    > >use strict;
    > >use warnings qw( all );

    >
    > >sub new {
    > >   my $proto = shift;
    > >   my $class = ref $proto || $proto;
    > >   my %attrs = @_;
    > >   my $self = {};

    >
    > >   # Nevermind the error checking for attributes right now.

    >
    > >   $self->{__name} = $attrs{name};
    > >   $self->{__age} = $attrs{age};

    >
    > >   bless $class, $self;

    >
    > >   return $self;
    > >}

    >
    > ># RW attributes.

    >
    > >sub name { $s = shift; $s->{__name} = shift if @_; return $s-
    > >>{__name} }

    > >sub age { $s = shift; $s->{__age} = shift if @_; return $s->{__age} }

    >
    > ># Methods.

    >
    > >sub sayName { print "My name is: " . shift->{__name} . "\n" }
    > >sub sayAge { print "I am " . shift->{__age} . " years old.\n" }

    >
    > >1;

    >
    > The above is all very impressive. What do you want to do?
    >
    > >I want to be able to read the following XML and create instances of
    > >Person from each instance in the XML:

    >
    > ><xml>
    > ><People>
    > >   <Person name="John Doe" age="22" />
    > >   <Person name="Jane Doe" age="23" />
    > >   <Person name="Maxx Doogan" age="10" />
    > ></People>
    > ></xml>

    >
    > So XML parsing is holding you up?


    No, I can parse most of the XML I need with XML::Simple. The point
    is, I don't really want the hashed structure that XML::Simple
    provides, even though I can munge the parsing with ForceGroup and
    other options. So no, the parsing isn't the issue. I want more of an
    XML "freeze / unfreeze" or serialize / deserialize (marshalling)
    solution. (Marshalling and s/d aren't always the same I realize...)

    >
    >
    > >So I get an array of Person objects which I can then write:

    >
    > >my @people; # Hold the array of Person object created from the XML
    > >above.

    >
    > >for my $person (@people) {
    > >   $person->sayName();
    > >   $person->sayAge();
    > >}

    >
    > >I've looked through SOAP::Lite (and SOAP::Serialize and
    > >SOAP::Deserialize).  I'm a fairly frequent user of XML::Simple, but
    > >Simple doesn't do the above (AFAIK).  SURELY *something* like this is
    > >"out there" (read "CPAN") but I can't seem to find it; only things
    > >close to it (like SOAP::SOM objects that require an xpath of sorts and
    > >my methods are still not available through an instantiated method of
    > >just the data [object attributes] in XML.)

    >
    > >Thanks!
    > >/usr/ceo

    >
    > rxparse version 2


    I'll check that out as well, but the solution Zed offered was closer
    to what I was looking for. Close enough.

    Thanks!
    /usr/ceo
    /usr/ceo, Oct 13, 2008
    #5
  6. /usr/ceo

    /usr/ceo Guest

    On Oct 13, 1:57 am, "/usr/ceo" <> wrote:
    > On Oct 12, 6:46 pm, wrote:
    >
    >
    >
    > > On Sun, 12 Oct 2008 14:01:14 -0700 (PDT), "/usr/ceo" <> wrote:
    > > >I've had a need for this at points in the past, but was always able to
    > > >code around it (and still could even now), but I'd really like to be
    > > >able to do this, and I can't find anything out there that does this
    > > >exactly as I want.  (Which tends to make me believe what I want
    > > >wouldn't be as immediately useful as maybe I would think it to be,
    > > >but...?!)

    >
    > > >Given an object defined as this:

    >
    > > >package Person;

    >
    > > >use strict;
    > > >use warnings qw( all );

    >
    > > >sub new {
    > > >   my $proto = shift;
    > > >   my $class = ref $proto || $proto;
    > > >   my %attrs = @_;
    > > >   my $self = {};

    >
    > > >   # Nevermind the error checking for attributes right now.

    >
    > > >   $self->{__name} = $attrs{name};
    > > >   $self->{__age} = $attrs{age};

    >
    > > >   bless $class, $self;

    >
    > > >   return $self;
    > > >}

    >
    > > ># RW attributes.

    >
    > > >sub name { $s = shift; $s->{__name} = shift if @_; return $s-
    > > >>{__name} }
    > > >sub age { $s = shift; $s->{__age} = shift if @_; return $s->{__age} }

    >
    > > ># Methods.

    >
    > > >sub sayName { print "My name is: " . shift->{__name} . "\n" }
    > > >sub sayAge { print "I am " . shift->{__age} . " years old.\n" }

    >
    > > >1;

    >
    > > The above is all very impressive. What do you want to do?

    >
    > > >I want to be able to read the following XML and create instances of
    > > >Person from each instance in the XML:

    >
    > > ><xml>
    > > ><People>
    > > >   <Person name="John Doe" age="22" />
    > > >   <Person name="Jane Doe" age="23" />
    > > >   <Person name="Maxx Doogan" age="10" />
    > > ></People>
    > > ></xml>

    >
    > > So XML parsing is holding you up?

    >
    > No, I can parse most of the XML I need with XML::Simple.  The point
    > is, I don't really want the hashed structure that XML::Simple
    > provides, even though I can munge the parsing with ForceGroup and
    > other options.  So no, the parsing isn't the issue.  I want more of an
    > XML "freeze / unfreeze" or serialize / deserialize (marshalling)
    > solution.  (Marshalling and s/d aren't always the same I realize...)
    >
    >
    >
    >
    >
    > > >So I get an array of Person objects which I can then write:

    >
    > > >my @people; # Hold the array of Person object created from the XML
    > > >above.

    >
    > > >for my $person (@people) {
    > > >   $person->sayName();
    > > >   $person->sayAge();
    > > >}

    >
    > > >I've looked through SOAP::Lite (and SOAP::Serialize and
    > > >SOAP::Deserialize).  I'm a fairly frequent user of XML::Simple, but
    > > >Simple doesn't do the above (AFAIK).  SURELY *something* like this is
    > > >"out there" (read "CPAN") but I can't seem to find it; only things
    > > >close to it (like SOAP::SOM objects that require an xpath of sorts and
    > > >my methods are still not available through an instantiated method of
    > > >just the data [object attributes] in XML.)

    >
    > > >Thanks!
    > > >/usr/ceo

    >
    > > rxparse version 2

    >
    > I'll check that out as well, but the solution Zed offered was closer
    > to what I was looking for.  Close enough.
    >
    > Thanks!
    > /usr/ceo


    For those of you following along at home, there were some minor errors
    with the code I typed in off the top of my head for my example.
    blessing into $class is wrong. Using "strict" the $s variable in my
    accessors needed to be "my"'d. I hate it when I read a book or try to
    pull something from Usenet and it doesn't work due to unchecked errors
    on the part of the author! :) :-(

    Here is the final XML::Twig solution, taking Zed's XML::Twig solution,
    adding in the Person package (just inline in this case) and correcting
    for a few errors (and making a few ticky-tack "the way I do things"
    changes to Zed's example which was fine as it was):

    #!/usr/bin/perl

    use strict;
    use warnings qw( all );

    package Person;

    use strict;
    use warnings qw( all );

    sub new {
    my $proto = shift;
    my $class = ref $proto || $proto;
    my %attrs = @_;
    my $self = {};

    # Nevermind the error checking for attributes right now.

    $self->{__name} = $attrs{name};
    $self->{__age} = $attrs{age};

    bless $self, $class;
    return $self;
    }

    # RW attributes.

    sub name { my $s = shift; $s->{__name} = shift if @_; return $s-
    >{__name} }

    sub age { my $s = shift; $s->{__age} = shift if @_; return $s-
    >{__age} }


    # Methods.

    sub sayName { print "My name is: " . shift->{__name} . "\n" }
    sub sayAge { print "I am " . shift->{__age} . " years old.\n" }

    package main;

    use XML::Twig;

    my $twig = XML::Twig->new();
    $twig->parse( \*DATA );

    my @people;
    my @xmlpersons = $twig->root->descendants( 'Person' );

    for my $element (@xmlpersons) {
    my $name = $element->att( 'name' );
    my $age = $element->att( 'age' );
    my $person = Person->new( name => $name, age => $age );
    push @people, $person;
    }

    for my $person (@people) {
    print "-" x 10 . "\n";
    $person->sayName();
    $person->sayAge();
    }

    __DATA__
    <xml>
    <People>
    <Person name="John Doe" age="22" />
    <Person name="Jane Doe" age="23" />
    <Person name="Maxx Doogan" age="10" />
    </People>
    </xml>

    Grüss!
    /usr/ceo
    /usr/ceo, Oct 13, 2008
    #6
    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. gooch
    Replies:
    7
    Views:
    1,141
    Ryan Stewart
    Jan 10, 2005
  2. Siemel Naran

    Does true ^ true return false?

    Siemel Naran, Jun 17, 2004, in forum: C++
    Replies:
    19
    Views:
    660
    Chris Theis
    Jun 18, 2004
  3. bdb112
    Replies:
    45
    Views:
    1,334
    jazbees
    Apr 29, 2009
  4. Brent Dillingham
    Replies:
    7
    Views:
    144
    Erik Hollensbe
    Aug 24, 2008
  5. Ilias Lazaridis
    Replies:
    4
    Views:
    503
    Ilias Lazaridis
    Jun 25, 2011
Loading...

Share This Page