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

SOAP::SOM array of arrays

Expand Messages
  • Thom Eden
    Folks, I am having an issue parsing a SOAP::SOM envelope. Basically, I have an array of arrays, e.g. q r x y The
    Message 1 of 6 , Oct 3, 2003
    • 0 Attachment
      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
      ... have an array of arrays, e.g. ... element. How do you do this?
      Message 2 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 3 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 4 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 5 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 6 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.