2011-08-24 113 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類型的定義。

相關問題