I have a Delphi XE app that consumes a web service written in Cold Fusion (I have no control over the service’s output format). I used the WSDL Importer in Delphi to create my unit for the calls to the web service. I am running into situations where I get an exception in Delphi that says “Element “data” does not contain a single text node”.
The relevant portion of the XML coming back from the web service when I get the exception is this:
<data soapenc:arrayType="xsd:anyType[][1]" xsi:type="soapenc:Array">
<data soapenc:arrayType="xsd:anyType[2]" xsi:type="soapenc:Array">
<data xsi:type="soapenc:string">6490</data>
<data xsi:type="soapenc:string">Other Expense</data>
</data>
</data>
If the XML from the web service contains more than one <data> child, no exception occurs.
<data soapenc:arrayType="xsd:anyType[][3]" xsi:type="soapenc:Array">
<data soapenc:arrayType="xsd:anyType[2]" xsi:type="soapenc:Array">
<data xsi:type="soapenc:string">2600</data>
<data xsi:type="soapenc:string">Deferred Revenue</data>
</data>
<data soapenc:arrayType="xsd:anyType[2]" xsi:type="soapenc:Array">
<data xsi:type="soapenc:string">4120</data>
<data xsi:type="soapenc:string">Non-Credit Income</data>
</data>
<data soapenc:arrayType="xsd:anyType[2]" xsi:type="soapenc:Array">
<data xsi:type="soapenc:string">6490</data>
<data xsi:type="soapenc:string">Other Expense</data>
</data>
</data>
What causes this exception and is there a way around it without being able to change the web service itself?
I don’t know what is causing the error, but yes, there is a way around it. You can use the RIO_AfterExecute() handler to modify the SOAPResponse, to alter the XML to “make it fit”. It’s an ugly, “bigger hammer” approach, but it ultimately lets you fiddle with the data to get around all sorts of problems.
Looking at your two examples, I’d try using stringreplace to replace ‘xsd:anyType[][1]’ with ‘xsd:anyType[][3]’. If that doesn’t work, try injecting another set of data with empty values, to make it seem like there’s not just one.
You’ll need a RIO object, and then you hook it up to a handler like this:
In my case, “self” refers to a class that I’ve written around my SOAP stuff.
Be sure to set your position back to 0 when you’re done fiddling with the request.
Here is some untested code: