http://www.perlmonks.org?node_id=831802

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

Dear Monks, I am working on a old code which uses XMLSimple to parse XML data.
I have a data set in which i need to relate the tags by occurance like Phone tag if followed by preceding Name tag then it is related to it.
I can't do this with XMLSimple as the data structure it returns creates the keys of Name tag and Phone tag thereby grouping the data related to them.
Please see this example
use XML::Simple; use Data::Dumper; my $data=qq(<Data><Name><Lname>xyz</Lname><Fname>abcd</Fname></Name><P +hone><Mobile>123456789</Mobile><Home>55656556</Home></Phone><Phone><M +obile>123456789</Mobile><Home>55656556</Home></Phone><Name><Lname>UTV +</Lname><Fname>EFGH</Fname></Name><Phone><Mobile>123456789</Mobile><H +ome>55656556</Home></Phone></Data>); my $ref=XMLin($data); print Dumper($ref); which shows output $VAR1 = { 'Phone' => [ { 'Home' => '55656556', 'Mobile' => '123456789' }, { 'Home' => '55656556', 'Mobile' => '123456789' }, { 'Home' => '55656556', 'Mobile' => '123456789' } ], 'Name' => [ { 'Lname' => 'xyz', 'Fname' => 'abcd' }, { 'Lname' => 'UTV', 'Fname' => 'EFGH' } ] };
From this i can't make out which phone number is associated with which name, Please help.

Out of sheer desperation may be i can use this

#on above $data i can split up the above string with each #Name tag followed by Phone tags associated with this my @namephn=map{m/<Name>.*?<\/Phone>/g } $data; print join "\n",@namephn; #---------- Output ------------- <Name><Lname>xyz</Lname><Fname>abcd</Fname></Name><Phone><Mobile>12345 +6789</Mobile><Home>55656556</Home></Phone> <Name><Lname>UTV</Lname><Fname>EFGH</Fname></Name><Phone><Mobile>12345 +6789</Mobile><Home>55656556</Home></Phone>

But how do i make that lazy ? operator match more than one phone tag till the next Name tag :-(

Replies are listed 'Best First'.
Re: Relating data parsed with XMLSimple
by Jenda (Abbot) on Mar 30, 2010 at 11:42 UTC

    The XML is not very well designed ... depending on the order of tags in a data oriented XML is a bad idea. Anyway ... do you like this output better?:

    use strict; use XML::Rules; use Data::Dumper; my $data=q( <Data> <Name><Lname>xyz</Lname><Fname>abcd</Fname></Name> <Phone><Mobile>123456789</Mobile><Home>55656556</Home></Phone> <Phone><Mobile>123456789</Mobile><Home>55656556</Home></Phone> <Name><Lname>UTV</Lname><Fname>EFGH</Fname></Name> <Phone><Mobile>123456789</Mobile><Home>55656556</Home></Phone> </Data>); my $parser = XML::Rules->new( stripspaces => 7, rules => { _default => 'content', Name => 'as array no content', Phone => sub { #return; my ($tag,$attr,$context,$parents) = @_; if (! $parents->[-1]{Name}) { warn "<Phone> before <Name>!\n"; } else { push @{$parents->[-1]{Name}[-1]{Phones}}, $attr; } return }, Data => sub {$_[1]->{Name}}, } ); my $ref = $parser->parse($data); print Dumper($ref);

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

      Yes sir this output definately looks better but will have to install this module and check if this is possible to include in the existing code.

      Thank you very much

Re: Relating data parsed with XMLSimple
by Anonymous Monk on Mar 30, 2010 at 10:17 UTC
    Your XML does not associate names with numbers, not at all

      It is supposed to be like this in XML

      Name    Mark

      Phone    1234

      Phone     7895

      Name     Glenn

      Phone     6789

      Then the two tags followed immediately after first Name tag are related to it e.g. Mark's numbers are 1234,7895 and Glenn's will be 6789. The xml i receive is from a third party web service.

        The xml i receive is from a third party web service.

        File a bug report immediately, as their format is stupid.

Re: Relating data parsed with XMLSimple
by rovf (Priest) on Mar 30, 2010 at 11:09 UTC
    Your way of defining the XML structure seems to be questionable to me. As it was already pointed out, you don't have a name-number association in your code. Maybe you can trick XML::Simple into returning something you will like better, by passing the option

    forcearray => [ 'Data' ]
    to XMLin(), but if you have the chance to influence the design of this piece of XML, I suggest that you redesign it.

    -- 
    Ronald Fischer <ynnor@mm.st>

      This typ of data is received by Web service call with SOAP Lite.

      However i cannot even change the module to parse XML as this is old code which was already working and need to fix it.

      From CPAN i found that may be XML::Twig can be used to sort this out.

        I do not think there is any mix of options that would convince XML::Simple to preserve the "relation" between Names and Phones.

        Jenda
        Enoch was right!
        Enjoy the last years of Rome.