Skip to content

how to edit the response fields in node-soap

I have the following WSDL definition:

<definitions targetNamespace="http://app.com/app" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:app="http://app.com/app" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   
   <message name="SoapQuery">
      <part name="TransType" type="xsd:string" />
   </message>

   <message name="SoapQueryResult">
      <part name="ResponseCode" type="xsd:string"/>
      <part name="ResultDesc" type="xsd:string" />
   </message>

   <portType name="SoapQuery_PortType">
      <operation name="SoapQuery">
         <input message="SoapQuery" />
         <output message="SoapQueryResult" />
      </operation>
   </portType>

   <binding name="SoapQuery_Binding" type="SoapQuery_PortType">
      <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
      <operation name="SoapQuery" style="document">
         <soap:operation soapAction="SoapQuery" />
         <soap:input>
            <soap:body namespace="app" use="literal" />
         </soap:input>

         <soap:output>
            <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal" />
         </soap:output>
      </operation>
   </binding>

   <service name="SoapQueryService">
      <documentation>WSDL File for SoapQueryService</documentation>
      <port binding="SoapQuery_Binding" name="SoapQuery_Port">
         <soap:address location="http://localhost:8002/api/request" />
      </port>
   </service>
</definitions>

and the following handler definition:

var SoapQueryService = {
  SoapQueryService: {
    SoapQuery_Port: {
      // This is how to define an asynchronous function.
      SoapQuery: function (args, callback) {
        // do some work
        callback({
          'ResultCode': 0,
          'ResultDesc': "sdfds",
        });
      }
    }
  }
};

Currently, when receiving the following request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <app:SoapQuery xmlns:app="http://app.com/app">
            <TransType>11124</TransType>
        </app:SoapQuery>
    </soapenv:Body>
</soapenv:Envelope>

it returns:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:app="http://app.com/app">
  <soap:Body>
    <app:SoapQueryResponse>
      <app:ResultCode>0</app:ResultCode>
      <app:ResultDesc>sdfds</app:ResultDesc>
    </app:SoapQueryResponse>
  </soap:Body>
</soap:Envelope>

But I want the response to look like:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:app="http://app.com/app">
  <soap:Body>
    <app:SoapQueryResult> <!-- not - SoapQueryResponse -->
      <ResultCode>0</ResultCode>  <!-- notice there is no `app:` -->
      <ResultDesc>sdfds</ResultDesc> <!-- notice there is no `app:` -->
    </app:SoapQueryResult>
  </soap:Body>
</soap:Envelope>

I have tried different approaches but none to seem to have effect on the response type. I feel like I am missing something in the WSDL or the handler..

Answer

Omit the RPC tag in your WSDL definition and change it from

<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

to

<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />

because you’re using RPC as style it’s adding app: to the output message and the parts, ignoring your outputName and replacing it with SoapQueryResponse as well. Removing the RPC tag will give you this output

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:app="http://app.com/app">
  <soap:Body>
    <SoapQueryResult> <!-- notice there is no `app:` -->
      <ResultCode>0</ResultCode>  
      <ResultDesc>sdfds</ResultDesc>
    </SoapQueryResult>
  </soap:Body>
</soap:Envelope>

By default node-soap will remove all targetNamespace prefix from the message and message parts if is not stylized RPC. I have created a pull request here which will allow users to add optional targetNamespace on the output message to be prefixed on the output only not the parts. So with the suggested pull request, you’d add targetNamespace to your message

 <message name="SoapQueryResult" targetNamespace="app">
      <part name="ResponseCode" type="xsd:string"/>
      <part name="ResultDesc" type="xsd:string" />
 </message>

and you’ll get your desired output

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:app="http://app.com/app">
  <soap:Body>
    <app:SoapQueryResult>
      <ResultCode>0</ResultCode>
      <ResultDesc>sdfds</ResultDesc>
    </app:SoapQueryResult>
  </soap:Body>
</soap:Envelope>