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

时间:2011-08-24 21:28:11

标签: web-services delphi delphi-xe

我有一个Delphi XE应用程序,它使用Cold Fusion编写的Web服务(我无法控制服务的输出格式)。我使用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>

如果来自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>

导致此异常的原因是什么导致无法更改Web服务本身?

3 个答案:

答案 0 :(得分:4)

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

你需要一个RIO对象,然后你把它连接到这样的处理程序:

MyRIO.OnAfterExecute := self.RIO_AfterExecute;

就我而言,“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;

答案 1 :(得分:2)

仅供参考,我今天遇到了同样的问题,经过几个小时的搜索,我发现了问题。事实是,WSDL导入器错误地将某些类型映射到字符串,这导致TXMLDocument被指示在没有文本节点的情况下读取文本节点! 所以定义为字符串(或字符串数​​组)的任何类型都可能是错误的......

到OP:检查导入单元中soapenc:Array类型的定义。

答案 2 :(得分:1)

必须是您的Delphi xml阅读代码中的错误。它有效的事实有时是偶然的。根据您正在使用的组件,浏览XML会有所不同。

我相信这些会对你有所帮助

Libraries and tutorials for XML in Delphi

Where is a tutorial for using XML with Delphi?

如果发布Delphi XML处理代码,我们可以进一步深入研究。