kettle中有兩種方式請求webservice服務,一個是Web服務查詢,但是這個有缺陷,無法處理複雜的需求,遇到這種情況就需要用Http post來處理了。
網上也有很多關於Http post請求webservice服務的,但是無一例外的都對請求響應後的結果沒有做出處理的教程,呼叫結果最終目的是為了拿到資料,有時候返回的是一個xml格式的集合,就需要用【XML檔案輸入】來解析每一個節點。而SOAP標準的響應結果不能直接用【XML檔案輸入】進行解析,下面就針對這種情況該如何處理做個簡單的介紹。
轉換指令碼預覽:
主要包括獲取變數、設定引數(SOAP請求入參)、發起請求(Http post)、獲取body(過濾soap響應結果)、解析xml等;
第一步:獲取變數
這裡定義入參的值,模擬作業情況下上一步驟傳過來的引數,這裡直接設定預設值,在下一個步驟中使用。
我這裡定義了三個引數,分別為orgCode、deptCode、staffName。
第二步:設定引數
這裡主要是安裝SOAP介面引數格式定義入參,他有一定標準的格式,其中藍色框是介面的真正入參,動態變化的是紅色框,也就是上一步傳進來的引數,通過佔位符的方式賦值。
這裡用到了E4X,E4X 是新增了對 XML 支援的 JavaScript 正式標準,通過 E4X,可以通過宣告變數的方法來宣告 XML 物件變數;
第三步:發起請求
需要填入介面地址,選擇字元編碼為UTF-8,上一步驟傳過來的入參,及響應結果變數名稱,另外根據介面情況可能還需要設定頭部資訊之類的,在Fields頁面設定,我的介面不需要,這裡就不做展示。
第四步:獲取body
下面是我的webService介面通過SoapUI工具測試的響應的結果示例:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:getDataResponse xmlns:ns2="http://webservice.ks.com">
<ns2:return>
<result>
<staff>
<identityNo>身份證號碼0</identityNo>
<employeNo>工牌號0</employeNo>
<spellCode>拼音碼0</spellCode>
<deptName>所屬部門名稱0</deptName>
<sexCode>性別程式碼0</sexCode>
<staffNo>員工內部號0</staffNo>
<sexName>性別名稱0</sexName>
<staffName>員工姓名0</staffName>
<account>賬戶0</account>
<staffBirthdate>出生日期0</staffBirthdate>
<deptCode>所屬部門程式碼0</deptCode>
</staff>
<!-- 以下忽略部分staff-->
</result>
<code>100</code>
<success>true</success>
<message>查詢成功</message>
</ns2:return>
</ns2:getDataResponse>
</soap:Body>
</soap:Envelope>
我的目的是獲取到節點result下的所有staff節點的內容,所以需要用到【XML檔案輸入】來解析這些節點。但是如果直接把響應結果進行解析,不管選擇那個節點,執行時會報錯:Can not apply XPath!
所以需要通過JavaScript指令碼解析響應結果,只獲取Body下的返回值內容:
其中轉義符轉換可以忽略,因為我的webservice介面通過http post請求返回的結果將<>符號進行轉義,所以需要轉成符號才可以進行下一步。
kettle中JavaScript指令碼沒有replaceAll()函式,所以如果要替換所有就需要用到正規表示式去找到要替換的內容。
首先是將Http post請求響應的字串結果建立一個出XML物件,然後獲取soap的名稱空間及響應結果的名稱空間,根據這些資訊拿到響應結果的body部分,最後轉成格式化的字串輸出。
最終responseXML為:
<ns2:getDataResponse xmlns:ns2="http://webservice.ks.com">
<ns2:return>
<result>
<staff>
<identityNo>身份證號碼0</identityNo>
<employeNo>工牌號0</employeNo>
<spellCode>拼音碼0</spellCode>
<deptName>所屬部門名稱0</deptName>
<sexCode>性別程式碼0</sexCode>
<staffNo>員工內部號0</staffNo>
<sexName>性別名稱0</sexName>
<staffName>員工姓名0</staffName>
<account>賬戶0</account>
<staffBirthdate>出生日期0</staffBirthdate>
<deptCode>所屬部門程式碼0</deptCode>
</staff>
<!-- 以下忽略部分staff-->
</result>
<code>100</code>
<success>true</success>
<message>查詢成功</message>
</ns2:return>
</ns2:getDataResponse>
再用【XML檔案輸入】來解析responseXML就成功了
後來,我驚訝的發現,獲取body這個步驟這麼複雜,目的不就是隻取getDataResponse嗎,那我是不是可以通過replace()函式把前後部分去掉呢?
於是我的獲取body步驟變成了:
然後列印輸出到excel也是可以的: