使用Web服务时是什么导致此错误?

Sam*_*m M 5 delphi web-services delphi-xe

我有一个使用以Cold Fusion编写的Web服务的Delphi XE应用程序(我无法控制该服务的输出格式)。我在Delphi中使用WSDL Importer创建了用于调用Web服务的单元。我在Delphi中遇到一个异常,说“元素“数据”不包含单个文本节点”。

当我得到异常时,从Web服务返回的XML的相关部分是这样的:

<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>
Run Code Online (Sandbox Code Playgroud)

如果来自Web服务的XML包含多个<data>子级,则不会发生异常。

<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>
Run Code Online (Sandbox Code Playgroud)

是什么导致此异常,并且有解决该异常的方法而又不能更改Web服务本身?

Chr*_*ton 4

我不知道是什么导致了这个错误,但是是的,有一种解决方法。您可以使用 RIO_AfterExecute() 处理程序来修改 SOAPResponse,以更改 XML 以“使其适合”。这是一种丑陋的“更大的锤子”方法,但它最终可以让你摆弄数据来解决各种问题。
看看您的两个示例,我尝试使用 stringreplace 将 'xsd:anyType[][1]' 替换为 'xsd:anyType[][3]'。如果这不起作用,请尝试注入另一组带有空值的数据,以使其看起来不只有一个。

您需要一个 RIO 对象,然后将其连接到处理程序,如下所示:

MyRIO.OnAfterExecute := self.RIO_AfterExecute;
Run Code Online (Sandbox Code Playgroud)

就我而言,“self”指的是我围绕 SOAP 内容编写的类。

当你处理完请求后,请务必将你的位置设置回 0。

这是一些未经测试的代码:

procedure MyWrapper.RIO_AfterExecute(const MethodName: string; SOAPResponse: TStream);
var 
  SL : TStringList;   
begin
  // do stuff with the SOAPResponse here. 
  // It's 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;
Run Code Online (Sandbox Code Playgroud)