Loading ...
Sorry, an error occurred while loading the content.

Re: SOAP::SOM array of arrays

Expand Messages
  • teden
    Duncan, Thanks, you pushed me through my Mental Block... Here is how I ended up doing it: #!/opt/perl5.6/bin/perl # Pragmas use strict; use warnings; # Perl
    Message 1 of 6 , Oct 9, 2003
    • 0 Attachment
      Duncan,

      Thanks, you pushed me through my Mental Block...

      Here is how I ended up doing it:

      #!/opt/perl5.6/bin/perl

      # Pragmas
      use strict;
      use warnings;

      # Perl Module imports
      use SOAP::Lite;

      my $xml = <<EOF;
      <person>
      <address>
      <addressType>Business</addressType>
      <addressLineList>
      <addressLine>100 Main St.</addressLine>
      <addressLine>Suite 32</addressLine>
      </addressLineList>
      </address>
      <address>
      <addressType>Home</addressType>
      <addressLineList>
      <addressLine>100 Jones Dr.</addressLine>
      <addressLine>Apt 1-Y</addressLine>
      </addressLineList>
      </address>
      </person>
      EOF

      my $som = SOAP::Deserializer->deserialize($xml);
      print "<person>", "\n";
      # Iterate through all child elements of <root>
      for (my $i = 1; my $a = $som->dataof("//person/[$i]"); $i++) {
      print " <", $a->name, ">", "\n";
      for (my $j = 1; my $b = $som->dataof("//person/[$i]/[$j]");
      $j++) {
      print " <", $b->name, ">";
      if ($b->name eq 'addressLineList') {
      print "\n";
      for (my $k = 1; my $c = $som->dataof
      ("//person/[$i]/[$j]/[$k]"); $k++) {
      print " <", $c->name, ">", $c-
      >value, "</", $c->name, ">", "\n";
      }
      } else {
      print $b->value, "</", $b->name, ">", "\n";
      next;
      }
      print " </", $b->name, ">", "\n";
      }
      print " </", $a->name, ">", "\n";
      }
      print "</person>", "\n";

      exit 0;


      Your pointer definitely pushed me in the right direction!

      I will echo the sentiment that it would be great if SOAP::SOM->match,
      dataof and valueof took a more robust set of XPath statements. I was
      prepared to do

      $som->match('//person/address[$i]/addressLineList/addressLine')

      so I can loop through those records, all the while knowing I was on
      the $i-th "address" record...

      Thom Eden
      --- In soaplite@yahoogroups.com, "Duncan Cameron"
      <duncan_cameron2002@y...> wrote:
      > At 13:21:00 on 2003-10-08 teden <the@d...> wrote:
      >
      > >Ok,
      > >
      > >I am beginning to get it. My code below is doing exactly what I
      asked
      > >it to - get the som tree for all A elements, then get the som tree
      > >for all B elements. What I want are all the B elements for a given
      A
      > >element. It seems I cannot do what it is I want to do. SOAP::SOM->
      > >match, dataof and valueof trim the SOM tree to a subset specified
      in
      > >the path given as an argument. When processing the inner array, it
      > >seems I cannot match it to its parent element, a key requirement.
      > >When the documentation says that the SOAP::SOM
      > >methods "match", "dataof", and "valeuof" take a simple XPATH type
      > >syntax, I expected to be able to specify something like
      > >
      > > '//A[1]/B[1]'
      > >
      > >to get the first B element nested within the first A element.
      Alas, I
      > >cannot. Can this be a formal request for an enhancement? In the
      > >meantime, I either need to look at creating a custom deserializer,
      > >or - heaven forbid - another language.
      > >
      > One way is to iterate through the children at each level, like this:
      >
      > my $xml = <<'END';
      > <root>
      > <A>
      > <B>q</B>
      > <B>r</B>
      > </A>
      > <C>c stuff </C>
      > <A>
      > <B>x</B>
      > <C>c stuff </C>
      > <B>y</B>
      > </A>
      > </root>
      > END
      >
      > my $som = SOAP::Deserializer->deserialize($xml);
      > # Iterate through all child elements of <root>
      > for ($i = 1; my $a = $som->dataof("/root/[$i]"); $i++) {
      > next unless $a->name eq 'A';
      > # Iterate through all child elements of the current <A> element
      > for ($j = 1; my $b = $som->dataof("/root/[$i]/[$j]"); $j++) {
      > next unless $b->name eq 'B';
      > print $b->value, "\n";
      > }
      > }
      >
      > prints
      >
      > q
      > r
      > x
      > y
      >
      > Regards
      > Duncan
    • Duncan Cameron
      ... Not pretty but it does what you need. ... If this approach gets too much, you can extract the SOAP envelope using - outputxml(1) and then use an XPath
      Message 2 of 6 , Oct 10, 2003
      • 0 Attachment
        At 14:57:00 on 2003-10-09 teden <the@...> wrote:

        >Duncan,
        >
        >Thanks, you pushed me through my Mental Block...
        >
        >Here is how I ended up doing it:
        >
        >#!/opt/perl5.6/bin/perl
        >
        ># Pragmas
        >use strict;
        >use warnings;
        >
        ># Perl Module imports
        >use SOAP::Lite;
        >
        >my $xml = <<EOF;
        ><person>
        > <address>
        > <addressType>Business</addressType>
        > <addressLineList>
        > <addressLine>100 Main St.</addressLine>
        > <addressLine>Suite 32</addressLine>
        > </addressLineList>
        > </address>
        > <address>
        > <addressType>Home</addressType>
        > <addressLineList>
        > <addressLine>100 Jones Dr.</addressLine>
        > <addressLine>Apt 1-Y</addressLine>
        > </addressLineList>
        > </address>
        ></person>
        >EOF
        >
        >my $som = SOAP::Deserializer->deserialize($xml);
        >print "<person>", "\n";
        ># Iterate through all child elements of <root>
        >for (my $i = 1; my $a = $som->dataof("//person/[$i]"); $i++) {
        > print " <", $a->name, ">", "\n";
        > for (my $j = 1; my $b = $som->dataof("//person/[$i]/[$j]");
        >$j++) {
        > print " <", $b->name, ">";
        > if ($b->name eq 'addressLineList') {
        > print "\n";
        > for (my $k = 1; my $c = $som->dataof
        >("//person/[$i]/[$j]/[$k]"); $k++) {
        > print " <", $c->name, ">", $c-
        >>value, "</", $c->name, ">", "\n";
        > }
        > } else {
        > print $b->value, "</", $b->name, ">", "\n";
        > next;
        > }
        > print " </", $b->name, ">", "\n";
        > }
        > print " </", $a->name, ">", "\n";
        >}
        >print "</person>", "\n";
        >
        >exit 0;
        >
        >
        Not pretty but it does what you need.

        >Your pointer definitely pushed me in the right direction!
        >
        >I will echo the sentiment that it would be great if SOAP::SOM->match,
        >dataof and valueof took a more robust set of XPath statements. I was
        >prepared to do
        >
        > $som->match('//person/address[$i]/addressLineList/addressLine')
        >
        >so I can loop through those records, all the while knowing I was on
        >the $i-th "address" record...
        >
        If this approach gets too much, you can extract the SOAP envelope using

        ->outputxml(1)

        and then use an XPath processor, such as XML::XPath or XML::LibXML,
        to find the nodes that you want.

        Regards
        Duncan
      Your message has been successfully submitted and would be delivered to recipients shortly.