2011-08-24 86 views
4

我有一个Delphi XE应用程序,它使用Cold Fusion编写的Web服务(我无法控制服务的输出格式)。我在Delphi中使用WSDL Importer来为我的Web服务调用创建我的单元。我遇到的情况是,我在Delphi中遇到了一个说“元​​素”数据“不包含单个文本节点”的异常。消费Web服务时会导致此错误的原因是什么?

来从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服务本身?

+0

请发布delphi xml处理代码 – Sam

+1

这是一些丑陋的XML。没有真正的命名的一切“数据”?有人不知道XML和SOAP是关于什么的!我怀疑是Delphi代码不能处理所有的节点是同一个名字,所以会感到困惑,但是! – mj2008

+0

@ mj2008:我同意XML很丑陋。这是Cold Fusion简化编写Web服务的“特性”之一;开发人员不必考虑XML格式。如果他们用Delphi编写的话,它会更加干净。 –

回答

4

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

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

MyRIO.OnAfterExecute := self.RIO_AfterExecute; 

在我的情况下,“自我”是指,我已经在我的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; 
+0

我希望避免锤子的方法,但我认为这是我唯一的选择。感谢您的建议。 –

1

必须在你的Delphi XML阅读代码中的bug。它有效的事实有时是偶然的。根据您使用的组件,导航通过XML是不同的。

我相信这将帮助你

Libraries and tutorials for XML in Delphi

Where is a tutorial for using XML with Delphi?

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

+0

我没有编写任何代码来解析XML。它全部由WSDL导入器创建的单元处理。我不太了解所有这些工作原理,只是实例化对象,调用适当的方法,并遍历返回的变体数组。 Cold Fusion是Web服务写入的内容,不会像我习惯的那样返回漂亮的对象。它映射到变体阵列。 –

+0

的WSDL进口商创建此功能的Web服务call.'function GetAdjustmentAccountList(常量OperatingUnit:字符串; const的RequestedDate:TXSDateTime):地图; STDCALL;'' 地图=阵列mapItem的;'' = mapItem类(TRemotable) 私人 FKEY:变体; 影响力:变体; 已发布 属性键:变体读取Fkey写入Fkey; 属性值:Variant read Fvalue写入Fvalue; 结束;' –

+0

好吧,够公平的是冷聚变是如何工作的......但也许你仍然可以捕捉到XML从一个变种返回并处理它自己。您可能已经发现WSDL Importer能够导入Cold Fusion生成的WSDL的缺陷。这实际上是另一点,您是否导入了WSDL文件或将WSDL导入器指向了webservice URI?您可能有兴趣考虑为Cold Fusion Web服务编写.Net客户端,并让.Net客户端充当Delphi应用程序的服务。然后你可以控制暴露给Delphi的web服务接口。 – Sam

2

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

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

相关问题