Want true instantiated objects from XML

U

/usr/ceo

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
 
Z

Zed Pobre

/usr/ceo said:
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?
 
S

sln

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-
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
 
U

/usr/ceo

/usr/ceo said:
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
 
U

/usr/ceo

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



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
 
U

/usr/ceo

The above is all very impressive. What do you want to do?
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
 

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
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top