What causes this error when using a web service?

I have a Delphi XE application that consumes a web service written in Cold Fusion (I have no control over the output format of the service). I used the WSDL Importer in Delphi to create my device for calling to a web service. I am facing situations where I get an exception in Delphi, which says that the "Element" data does not contain one node text.

The corresponding XML part that returns from the web service when an exception is received is:

<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, an exception does not occur.

 <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?

+4
source share
3 answers

I donโ€™t know what causes the error, but yes, there is a way around this. You can use the RIO_AfterExecute () handler to modify the SOAPResponse, to modify the XML to "make it suitable." This is an ugly Big Hammer approach, but it ultimately allows you to tinker with data to get around all kinds of problems.
Looking at your two examples, I would try to use stringreplace to replace "xsd: anyType [] [1]" with "xsd: anyType [] [3]". If this does not work, try entering a different dataset with empty values โ€‹โ€‹so that it looks like more than one.

You will need an RIO object, and then you attach it to the handler as follows:

 MyRIO.OnAfterExecute := self.RIO_AfterExecute; 

In my case, โ€œIโ€ refers to the class that I wrote around my SOAP material.

Be sure to set your position to 0 when you finish the query.

Here is some untested code:

 procedure MyWrapper.RIO_AfterExecute(const MethodName: string; SOAPResponse: TStream); var SL : TStringList; begin // do stuff with the SOAPResponse here. // It a stream, so I like to load it into a stringlist // ex: SL := TStringList.Create; try SOAPResponse.Position := 0; SL.LoadFromSTream(SOAPREsponse); // fiddle with stringreplace here, to doctor up the SL.text. SOAPResponse.Position := 0; SOAPResponse.size := length(SL.Text); SL.SaveToStream(SOAPResponse); finally SL.free; end; end; 
+4
source

Just for reference, I ran into the same problem today, and after hours of searching, I found the problem. The fact is that the WSDL importer does not correctly map certain types to a string, which causes TXMLDocument to be instructed to read text code while it is not there! Therefore, any type defined as a string (or an array of strings) may be incorrect ...

In OP: check the definition of type soapenc: Array in the imported block.

+2
source

There should be a mistake in your Delphi XML reader code. The fact that it works is sometimes companionable. XML navigation differs depending on the component you are using.

I believe this will help you.

Libraries and Tutorials for XML in Delphi

Where is the tutorial on using XML with Delphi?

If you post Delphi XML processing code, we can study it in more detail.

+1
source

Source: https://habr.com/ru/post/1368862/


All Articles