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

2998Trouble with 'unresolved prefix', WSDL & namespaces

Expand Messages
  • gnawed
    Sep 15, 2003
    • 0 Attachment
      I'm having some namespace issues when using a WSDL file.

      I have a ComplexType which is simply an array of strings:

      Types:
      <xsd:complexType name="ArrayOfStrings">
      <xsd:complexContent>
      <xsd:restriction base="SOAP-ENC:Array">
      <xsd:sequence>
      <xsd:element maxOccurs="unbounded" minOccurs="0"
      name="slot" type="xsd:string"/>
      </xsd:sequence>
      <xsd:attribute ref="SOAP-ENC:arrayType"
      wsdl:arrayType="xsd:string[]"/>
      </xsd:restriction>
      </xsd:complexContent>
      </xsd:complexType>

      Messages:
      <message name="ArrayRequest">
      <part name="inArray" type="tns:ArrayOfStrings" />
      </message>
      <message name="ArrayResponse">
      <part name="outArray" type="tns:ArrayOfStrings" />
      </message>



      Which gets used in a simple test method which accepts this array and
      passes it back:

      Server:
      package NTF::API::Test;

      use base qw(SOAP::Server::Parameters);
      use SOAP::Lite;
      use strict;

      sub getArray {
      my $self = shift;
      my @args = SOAP::Server::Parameters::byName([qw(inArray)], @_);

      my $array = [];
      foreach my $item (@{$args[0]}) {
      push @$array, SOAP::Data->name('slot' => $item)->type
      ('string');
      }
      my $struct = SOAP::Data->name('outArray')->value($array)->type
      ('tns:ArrayOfStrings');

      return $struct;
      }



      If I call this method like this (BTW, I'm using Apache::SOAP):

      use strict;
      use Data::Dumper;
      use SOAP::Lite +trace=>"debug";

      my $s = SOAP::Lite->service
      ("http://someurl.com/Test.wsdl");

      my $q = $s->getArray(
      SOAP::Data->name( 'inArray' )
      ->value( [
      SOAP::Data->name(slot=>'item1')->type
      ('string'),
      SOAP::Data->name(slot=>'item2')->type
      ('string'),
      ]
      )->type('tns:ArrayOfStrings')->attr
      ({'xmlns:tns'=>'urn:/NTF/API/Test'})
      );
      print "Received: ", Dumper($q);



      I get this error about 'unresolved prefix'

      getArray():
      Unresolved prefix 'tns' for attribute value 'tns:ArrayOfStrings'
      <?xml version="1.0" encoding="UTF-8"?>
      <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/1999/XMLSchema-
      instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:xsd="http://www.w3.org/1999/XMLSchema" SOAP-
      ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <SOAP-ENV:Body>
      <namesp1:getArrayResponse xmlns:namesp1="urn:/NTF/API/Test">
      <outArray xsi:type="tns:ArrayOfStrings" SOAP-
      ENC:arrayType="xsd:string[2]">
      <slot xsi:type="xsd:string">item1</slot>
      <slot xsi:type="xsd:string">item2</slot>
      </outArray>
      </namesp1:getArrayResponse>
      </SOAP-ENV:Body>
      </SOAP-ENV:Envelope>



      I read in one of the postings here, that if I add a xmlns to the WSDL
      file it will fix the problem:

      <message name="ArrayRequest">
      <part name="inArray" type="tns:ArrayOfStrings"
      xmlns:tns="urn:/NTF/API/Test" />
      </message>
      <message name="ArrayResponse">
      <part name="outArray" type="tns:ArrayOfStrings"
      xmlns:tns="urn:/NTF/API/Test" />
      </message>



      but the result was unchanged.

      The only way I could fix this was to add an attribute to the return
      value (as I already have in the request, above):

      my $struct = SOAP::Data->name('outArray')->value($array)->type
      ('tns:ArrayOfStrings')->attr({"xmlns:tns"=>"urn:/NTF/API/Test"});



      Then I get this:
      getArray():
      Received: $VAR1 = bless( [
      'item1',
      'item2'
      ], 'ArrayOfStrings' );



      Is there a way to tell SOAP::Lite to use the WSDL file to determine
      the correct types and namespaces? This applies both to the client
      and the server. Can I even call service() on a server? If so, what
      does it affect?

      Since SOAP::Lite already knows the names, types & namespaces required
      for the getArray() call from the WSDL file, couldn't a call like this:
      $q = $s->getArray( { inArray => [ {slot => 'item1'}, {slot
      => 'item2'} ] } );
      produce the correct XML with proper structure, types and namespaces.

      Same for the server:
      return { outArray => [ {slot => 'item1'}, {slot =>'item2'} ] };