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

Re: [soaplite] Re: SOAP::SOM array of arrays

Expand Messages
  • Duncan Cameron
    ... One way is to iterate through the children at each level, like this: my $xml = q r c stuff x c
    Message 1 of 6 , Oct 8, 2003
    • 0 Attachment
      At 13:21:00 on 2003-10-08 teden <the@...> 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
    • 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 2 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 3 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.