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

Re: [soaplite] Root element with child data?

Expand Messages
  • Gavin Alexander
    Hi, From what I can see, its got do with the way that the SOAP::Serializer handles the root element as a method . If you check out the SOAP::Lite source, you
    Message 1 of 3 , Dec 29, 2004
    • 0 Attachment
      Hi,

      From what I can see, its got do with the way that the
      SOAP::Serializer handles the root element as a
      "method".
      If you check out the SOAP::Lite source, you can see
      that the SOAP::Data::set_value method will always
      overide the root elements' values with null data,
      (unless its explicitly supplied in the ->call() method
      as parameters, in which case it generates a new
      symbol, such as 'gensym-xx', etc)

      There are a couple of things you can try.
      Redefine the SOAP::Data::set_value method to look
      something like this.

      sub SOAP::Data::set_value
      {
      $self = UNIVERSAL::isa($_[0] => 'SOAP::Data') ?
      shift->new : SOAP::Data->new;
      $self->{_value} = [@_] if ! @{$self->{_value}} and
      @_;
      $self;
      }

      and use it like this:
      my $request = SOAP::Data
      ->name('Query'=>'Foo')
      ->attr({'xmlns' => 'http://example.com'});
      $soap->call($request);

      Another work-around would be to add your own
      serializer overiding the envelope method. By default
      SOAP::Lite calls envelope with a 'method' type. If
      you change this to 'freeform' the parameters don't get
      treated as a seperate 'method', 'body' elements

      Something like this should work.

      package My::Serializer;

      use strict;
      use base 'SOAP::Serializer';
      use vars qw/@freeforms/;
      BEGIN { @freeforms = qw/Query/; }

      sub envelope
      {
      my $self = shift;
      my $type = shift;
      my $root = shift;
      UNIVERSAL::isa($root => 'SOAP::Data') and grep
      /^$root->name$/, @freeforms ?
      return $self->SUPER::envelope('freeform', $root,
      @_):
      return $self->SUPER::envelope($type, $root, @_);
      }

      1;

      and
      SOAP::Lite->proxy(...)->serializer(My::Serializer->new)
      should work fine.

      I'm not a 100% sure if these will break anything. Can
      someone please verify this?
      Also this might have been fixed in the the latest
      version of S::L, but I haven't checked.

      Can anyone else out there suggest a less intrusive
      way to do this using SOAP::Lite?

      Cheers.

      --gavin

      --- bluesterror <yahoo@...> wrote:

      ---------------------------------

      Hi,

      I am using document-literal messaging in my web
      service. Quoting from
      the WS-I basic profile 1.0, "a document-literal
      binding MUST be
      represented on the wire as a MESSAGE with a soap:Body
      whose child
      element is an instance of the global element
      declaration referenced by
      the corresponding wsdl:message part."

      In other words, rather than the name of the service,
      the toplevel
      element of an XML document is used. In my case, the
      service takes as
      parameter a string and returns an XML document
      fragment, so the
      request message ideally would look something like:

      <soap:Body>
      <Query xmlns="http://example.com">FOO</Query>
      </soap:Body>

      However I cannot make SOAP::Lite generate such a
      fragment. The
      following code:

      my $method = SOAP::Data
      ->name('Query' => 'Foo')
      ->attr({'xmlns' => 'http://example.com'});

      my $som = $soap->call($method);

      sends a request like:

      <soap:Body>
      <Query xmlns="http://example.com" xsi:nil="true" />
      </soap:Body>

      It seems SOAP::Lite disregards the value of the root
      XML node unless
      it is also a SOAP::Data element. Using $method=>'FOO'
      as the
      parameter to call() results in FOO being the child of
      some gensym
      element. What is the proper way to do this?

      Aside: My understanding is that a "wrapped" style
      includes the
      operation name as well, but I'd rather not resort to
      that in keeping
      with the BP. The other workaround is to make the
      document fragment
      have a param child element but that would needlessly
      complicate my
      server-side implementation.





      Yahoo! Groups SponsorADVERTISEMENT


      ---------------------------------
      Yahoo! Groups Links

      To visit your group on the web, go to:
      http://groups.yahoo.com/group/soaplite/

      To unsubscribe from this group, send an email to:
      soaplite-unsubscribe@yahoogroups.com

      Your use of Yahoo! Groups is subject to the Yahoo!
      Terms of Service.


      Find local movie times and trailers on Yahoo! Movies.
      http://au.movies.yahoo.com
    • bluesterror
      Thanks, this bit did the trick! FWIW I am using SOAP::Lite 0.65-beta2.1. -Bob
      Message 2 of 3 , Dec 29, 2004
      • 0 Attachment
        Thanks, this bit did the trick!

        FWIW I am using SOAP::Lite 0.65-beta2.1.

        -Bob

        --- In soaplite@yahoogroups.com, Gavin Alexander <gc_alexander@y...>
        wrote:
        > There are a couple of things you can try.
        > Redefine the SOAP::Data::set_value method to look
        > something like this.
        >
        > sub SOAP::Data::set_value
        > {
        > $self = UNIVERSAL::isa($_[0] => 'SOAP::Data') ?
        > shift->new : SOAP::Data->new;
        > $self->{_value} = [@_] if ! @{$self->{_value}} and
        > @_;
        > $self;
        > }
        >
        > and use it like this:
        > my $request = SOAP::Data
        > ->name('Query'=>'Foo')
        > ->attr({'xmlns' => 'http://example.com'});
        > $soap->call($request);
      Your message has been successfully submitted and would be delivered to recipients shortly.