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

Re: SOAP::SOM array of arrays

Expand Messages
  • teden
    ... have an array of arrays, e.g. ... element. How do you do this?
    Message 1 of 6 , Oct 8, 2003
    • 0 Attachment
      --- In soaplite@yahoogroups.com, "Thom Eden" <the@d...> wrote:
      > Folks,
      >
      > I am having an issue parsing a SOAP::SOM envelope. Basically, I
      have an array of arrays, e.g.
      >
      > <A>
      > <B>q</B>
      > <B>r</B>
      > </A>
      > <A>
      > <B>x</B>
      > <B>y</B>
      > </A>
      >
      > The code I am using looks something like this:
      >
      > if ($som->match(SOAP::SOM::envelope)) {
      > foreach my $A_Element($som->dataof('//A')) {
      > print "<A>\n";
      > foreach my $B_Element($som->dataof('//A/B')) {
      > print " <B>".$B_Element->value."</B>\n";
      > }
      > print "</A>\n";
      > }
      > } else {
      > print "! It's not SOAP::SOM !\n\n";
      > }
      >
      > which should print out the above, but instead I get
      >
      > <A>
      > <B>q</B>
      > <B>r</B>
      > <B>x</B>
      > <B>y</B>
      > </A>
      > <A>
      > <B>q</B>
      > <B>r</B>
      > <B>x</B>
      > <B>y</B>
      > </A>
      >
      > I need the inner loop to position itself relative to the parent
      element. How do you do this?
      >
      > Many thanks,
      >
      > Thom Eden
    • teden
      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
      Message 2 of 6 , Oct 8, 2003
      • 0 Attachment
        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.


        Frustrated,

        Thom Eden


        --- In soaplite@yahoogroups.com, "Thom Eden" <the@d...> wrote:
        > Folks,
        >
        > I am having an issue parsing a SOAP::SOM envelope. Basically, I
        have an array of arrays, e.g.
        >
        > <A>
        > <B>q</B>
        > <B>r</B>
        > </A>
        > <A>
        > <B>x</B>
        > <B>y</B>
        > </A>
        >
        > The code I am using looks something like this:
        >
        > if ($som->match(SOAP::SOM::envelope)) {
        > foreach my $A_Element($som->dataof('//A')) {
        > print "<A>\n";
        > foreach my $B_Element($som->dataof('//A/B')) {
        > print " <B>".$B_Element->value."</B>\n";
        > }
        > print "</A>\n";
        > }
        > } else {
        > print "! It's not SOAP::SOM !\n\n";
        > }
        >
        > which should print out the above, but instead I get
        >
        > <A>
        > <B>q</B>
        > <B>r</B>
        > <B>x</B>
        > <B>y</B>
        > </A>
        > <A>
        > <B>q</B>
        > <B>r</B>
        > <B>x</B>
        > <B>y</B>
        > </A>
        >
        > I need the inner loop to position itself relative to the parent
        element. How do you do this?
        >
        > Many thanks,
        >
        > Thom Eden
      • Duncan Cameron
        ... One way is to iterate through the children at each level, like this: my $xml = q r c stuff x c
        Message 3 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 4 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 5 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.