Add namespace to the SOAP Body and Header

Hi,

I'm trying to add a namespace to the SOAP Body and Header.
I send the request:

<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <env:Body>
    <n1:Air_MultiAvailability xmlns:n1="http://my.url.com/SAR_07">

But I would like to send:

<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header xmlns="http://webservices.amadeus.com/definitions
"></soap:Header>
  <env:Body xmlns="http://my.url.com/SAR_07">
    <Air_MultiAvailability>

I have tested the last one and it works.
So I need several things:

_add namespaces to the Header and Body tags,
_plus the Header tag is empty, it does not contain any element (I have seen
lots of example that add element to the header but not just an empty
header):

<soap:Header xmlns="http://webservices.amadeus.com/definitions
"></soap:Header>

Thanks for any help.

···

--
David ALPHEN

Hi,

David Alphen wrote:

So I need several things:

_add namespaces to the Header and Body tags,
_plus the Header tag is empty, it does not contain any element (I have seen
lots of example that add element to the header but not just an empty
header):

<soap:Header xmlns="http://webservices.amadeus.com/definitions
"></soap:Header>

Following code samples require soap4r-1.5.6 RC2. You need to get 1.5.6
RC2 from http://dev.ctor.org/soap4r/wiki#a2007-06-05:1.5.6-RC2

1. empty SOAP Header

soap4r-1.5.5 cannot send empty SOAPHeader. With 1.5.6, you can do that
like this;

  require 'soap/rpc/driver'
  require 'soap/header/handler'

  class EmptyHeaderHandler < SOAP::Header::Handler
    def on_outbound(header)
      # dump SOAPHeader even if it has no item
      header.force_encode = true
      header.extraattr['xmlns'] = 'urn:foo'
      # no item needed
      nil
    end
  end

  driver = SOAP::RPC::Driver.new('http://localhost:7171/soapendpoint&#39;\)
  driver.wiredump_dev = STDOUT
  driver.headerhandler << EmptyHeaderHandler.new(XSD::QName::EMPTY)
  driver.add_method('nop').call

2. free namespace definition control

At first, XML processors must handle both A and B as the same.

  A. <env:Body>
       <n1:Air_MultiAvailability xmlns:n1="http://my.url.com/SAR_07"/>
     </env:Body>
  B. <env:Body xmlns="http://my.url.com/SAR_07&quot;&gt;
       <Air_MultiAvailability/>
     </env:Body>

But I can understand that there's a case we cannot change other party's
SOAP implementation. For the case of this, you need to construct XML by
yourself like this;

  driver = SOAP::RPC::Driver.new('http://localhost:7171/soapendpoint&#39;\)
  header = SOAP::SOAPHeader.new
  header.extraattr['xmlns'] = 'urn:foo'
  header.force_encode = true
  require 'rexml/document'
  body = SOAP::SOAPBody.new(
    REXML::Document.new('<Air_MultiAvailability/>'))
  body.extraattr['xmlns'] = 'urn:foo'
  driver.invoke(header, body)

Of course you'd better to ask the other party to fix the implementation.

Regards,
// NaHi

Hello,

Thank you,

I've updated to 1.5.6 RC2 and it works now, here is my code:

/* Start code */

require 'soap/header/handler'
require 'http-access2'
require 'soap/wsdlDriver'

wsdl = "myWsdl.wsdl"

factory = SOAP::WSDLDriverFactory.new(wsdl)
driver = factory.create_rpc_driver

# save the SOAP message
driver.wiredump_file_base = File.join(File.dirname (__FILE__), "tmp")
driver.wiredump_dev = STDERR if $DEBUG

class EmptyHeaderHandler < SOAP::Header::Handler

  def on_outbound(header)
    # dump SOAPHeader even if it has no item
    header.force_encode = true
    header.extraattr['xmlns'] = 'urn:foo'
    # no item needed
    nil
  end

end

driver.headerhandler << EmptyHeaderHandler.new(XSD::QName::EMPTY)

parameters = { #... my parameters }

req = driver.Air_MultiAvailability(parameters)

/* End of code */

Well, I have an other question I'll ask in a new topic about wsdl2ruby.

···

++

On 6/5/07, NAKAMURA, Hiroshi <nakahiro@sarion.co.jp> wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

David Alphen wrote:
> So I need several things:
>
> _add namespaces to the Header and Body tags,
> _plus the Header tag is empty, it does not contain any element (I have
seen
> lots of example that add element to the header but not just an empty
> header):
>
> <soap:Header xmlns="http://webservices.amadeus.com/definitions
> "></soap:Header>

Following code samples require soap4r-1.5.6 RC2. You need to get 1.5.6
RC2 from http://dev.ctor.org/soap4r/wiki#a2007-06-05:1.5.6-RC2

1. empty SOAP Header

soap4r-1.5.5 cannot send empty SOAPHeader. With 1.5.6, you can do that
like this;

  require 'soap/rpc/driver'
  require 'soap/header/handler'

  class EmptyHeaderHandler < SOAP::Header::Handler
    def on_outbound(header)
      # dump SOAPHeader even if it has no item
      header.force_encode = true
      header.extraattr['xmlns'] = 'urn:foo'
      # no item needed
      nil
    end
  end

  driver = SOAP::RPC::Driver.new('http://localhost:7171/soapendpoint&#39;&lt;http://localhost:7171/soapendpoint'&gt;
)
  driver.wiredump_dev = STDOUT
  driver.headerhandler << EmptyHeaderHandler.new(XSD::QName::EMPTY)
  driver.add_method('nop').call

2. free namespace definition control

At first, XML processors must handle both A and B as the same.

  A. <env:Body>
       <n1:Air_MultiAvailability xmlns:n1="http://my.url.com/SAR_07"/>
     </env:Body>
  B. <env:Body xmlns=" http://my.url.com/SAR_07&quot;&gt;
       <Air_MultiAvailability/>
     </env:Body>

But I can understand that there's a case we cannot change other party's
SOAP implementation. For the case of this, you need to construct XML by
yourself like this;

  driver = SOAP::RPC::Driver.new('http://localhost:7171/soapendpoint&#39;&lt;http://localhost:7171/soapendpoint'&gt;
)
  header = SOAP::SOAPHeader.new
  header.extraattr['xmlns'] = 'urn:foo'
  header.force_encode = true
  require 'rexml/document'
  body = SOAP::SOAPBody.new(
    REXML::Document.new('<Air_MultiAvailability/>'))
  body.extraattr['xmlns'] = 'urn:foo'
  driver.invoke(header, body)

Of course you'd better to ask the other party to fix the implementation.

Regards,
// NaHi

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Cygwin)

iQEVAwUBRmTnUh9L2jg5EEGlAQKpgAf9F4o7yMwFp0OGRp9clEupC/ex5Fphejyv
uatlBb2nH/4ZoBl4ufZQdhrYNYics2E9TZ+TmdZujCfV/v8kgxAPys1OWYh2enQB
va6ayndvcD+bTDG7fRdoQQmOW+ZYDePRm814pCcuqZEYwOxTjYEilHTBY+cw/sdU
w5qIKc8B5lh6OXcbUF3ezWY/XGChrNK6flGKRzuRt8zrDFgIsyf2F75QkH8DXxrR
4yS1lTQ4AHWrpqBrH2EnWjJmILCCw8ZqBzaXC4XfYOizmBxrsyhx9tULQkClD2tR
ai5iky6cx9nUuPcu2oaiZryDQ02dt7gx8W1fwfrnwzyk3BFS+6ps+w==
=ree6
-----END PGP SIGNATURE-----

--
David ALPHEN