delphisoapsoap-clientdelphi-11-alexandria

How to prevent generation of xml 'nil' as is 'xsi:nil="true"' elements in a soap webservice Delphi client?


Since Delphi Alexandria 11.2, I have a problem with my Delphi SOAP clients.

If, in my client side application, my field obj.entryDate is set to nil (because there is no such date), then the Delphi SOAP libraries create the following in the request:

WSDL part of the SOAP request is:

<xs:complexType name="baseArchivDokumentDTO">
    <xs:sequence>
      <xs:element name="entryDate" type="xs:dateTime" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

With the SOAP client that is generated for that WSDL, Delphi generates the following in requests:

<arg0>
  <test>1</test>
  <entryDate xsi:nil="true"/>
</arg0>

If the element is optional (and this is, what minOccurs="0" means above), the Java WebService does not accept the request:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Client</faultcode>
         <faultstring>Unmarshalling Error:</faultstring>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

The normal behaviour should be to omit that element:

<arg0>
  <test>1</test>
</arg0>

There was no problem before Delphi Alexandria, I think.

How can I get back the old (normal) behavior in Delphi Alexandria?


Solution

  • My fallback solution would be to comment the following two methods (CreateNilNode and TSOAPDomConv.CreateNULLNode) in the Delphi unit Soap.OPToSOAPDomConv:

    function CreateNilNode(ParentNode: IXMLNode; const Name: InvString; const Namespace: InvString): IXMLNode;
    begin
    //  Result := ParentNode.AddChild(Name, Namespace);
    //  Result.SetAttributeNS(SSoapNil, XMLSchemaInstNameSpace, STrue);
    end;
    
    function TSOAPDomConv.CreateNULLNode(RootNode, ParentNode: IXMLNode; const Name: InvString; UseParentNode: Boolean): IXMLNode;
    //var
    //  Pre: InvString;
    begin
    //  if not UseParentNode then
    //    Result := ParentNode.AddChild(Name, '')
    //  else
    //    Result := ParentNode;
    //  Pre := FindPrefixForURI(RootNode, Result, XMLSchemaInstNameSpace, True);
    //  Result.SetAttributeNS(MakeNodeName(Pre, SSoapNIL), XMLSchemaInstNameSpace, STrue);
    end;
    

    This would prevent the node and the attribute 'xsi:nil="true"', but I do not like this ugly hack (change delphi source unit), because I got to support this on my own.