typescriptsoapnestjswsdlnode-soap

How to Dynamically Set xsi:type Attribute in SOAP Response Using Node-SOAP in a NestJS Project


Part of my WSDL is defined as

<s:complexType name="AbstractOperation" abstract="true">
    <s:sequence>
        <s:element minOccurs="1" maxOccurs="1" name="progressive" type="s:int" />
    </s:sequence>
</s:complexType>

<s:complexType name="ConcreteOperation1">
    <s:complexContent mixed="false">
        <s:extension base="tns:AbstractOperation">
            <s:sequence>
                <s:element minOccurs="0" maxOccurs="1" name="identifier" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>

<s:complexType name="ConcreteOperation2">
    <s:complexContent mixed="false">
        <s:extension base="tns:AbstractOperation">
            <s:sequence>
                <s:element minOccurs="0" maxOccurs="1" name="code" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>

I want to return something like:

<tns:Operations>
    <tns:AbstractOperation xsi:type="tns:ConcreteOperation1">
        <tns:progressive>1</tns:progressive>
        <tns:identifier>FP301DW</tns:identifier>
    </tns:AbstractOperation>
    <tns:AbstractOperation xsi:type="tns:ConcreteOperation2">
        <tns:progressive>2</tns:progressive>
        <tns:code>AF2F3S</tns:code>
    </tns:AbstractOperation>
</tns:Operations>

In my NestJS project, I am using the soap library to start a SOAP server. In the controller, after retrieving data from a Prisma ORM instance, I am returning it like this:

     return {
        Operations: {
          AbstractOperation: prismaMappedOperationArray,
        },
      }

But I get:

<tns:Operations>
    <tns:AbstractOperation>
        <tns:progressive>1</tns:progressive>
        <tns:identifier>FP301DW</tns:identifier>
    </tns:AbstractOperation>
    <tns:AbstractOperation>
        <tns:progressive>2</tns:progressive>
        <tns:code>AF2F3S</tns:code>
    </tns:AbstractOperation>
</tns:Operations>

How can I dynamically specify the xsi:type attribute when arranging the response, based on the instance of the prismaMappedOperationArray objects (which can be of either the ConcreteOperation1 or ConcreteOperation2 class)?


Solution

  • Ok I answered myself after some radom testing session, soap library documentation do not mention it but if you wanna add marshallable attributes to your Typescript object you have to add an attributes key like:

    return {
      Operations: {
        AbstractOperation: prismaMappedOperationArray,
    
        attributes: { 'xmlns:xsi': 'tns:ConcreteOperation1' },
       },
    }
    

    And this will return:

    <tns:Operations>
        <tns:AbstractOperation xsi:type="tns:ConcreteOperation1">
            <tns:progressive>1</tns:progressive>
            <tns:identifier>FP301DW</tns:identifier>
        </tns:AbstractOperation>
        <tns:AbstractOperation xsi:type="tns:ConcreteOperation1">
            <tns:progressive>2</tns:progressive>
            <tns:identifier>FP301DW</tns:identifier>
        </tns:AbstractOperation>
    </tns:Operations>