2011-10-19 60 views
0

我不明白爲什麼XmlSlurper顯然不能處理結果。Groovy HTTPBuilder SOAP響應沒有被正確解析

import groovyx.net.http.* 
import static groovyx.net.http.ContentType.* 
import static groovyx.net.http.Method.* 


def String WSDL_URL = ... 
def http = new HTTPBuilder(WSDL_URL , ContentType.XML) 
String soapEnvelope = 
      """<?xml version="1.0" encoding="utf-8"?> 
     <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
         xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> 
      <soap12:Body> 
      <GetTerritories xmlns="..."> 
       <State>AZ</State> 
       <ZipCode>85203</ZipCode> 
      </GetTerritories> 
      </soap12:Body> 
     </soap12:Envelope>""" 
     http.request(POST, XML) { 
      headers."Content-Type" = "application/soap+xml; charset=utf-8" 
      headers."Accept" = "application/soap+xml; charset=utf-8" 
      body = soapEnvelope 

      response.success = { resp, xml ->  
       println "XML was ${xml}" 
       println "Territories were ${xml.Territories}" 
       println "State were ${xml.Territories.State}" 
       println "City was ${xml.Territories.Territory.City}" 
       println "County was ${xml.Territories.Territory.County}" 
      } 

      response.failure = { resp, xml -> 
       xml 
      } 
     } 

導致

XML was <Territories><State>AZ</State><ZipCode>85203</ZipCode><Territory><City>Mesa</City><County>Maricopa</County>...</Territory></Territories> 
Territories were 
State were 
City was 
County was 

UPDATE:感謝John Wagenleitner的洞察力,我做了一個小挖多。

當我再補充一點斷言,我看到一個問題:

assert "Territories" == xml.name() 
        | | | 
        | | Envelope 
        | <Territories><State>AZ</State><ZipCode>85203</ZipCode</Territories> 
        false 

請求參數改變從POST, XMLPOST, TEXT被揭示:

XML was <?xml version="1.0" encoding="utf-8"?> 
<soap:Envelope 
     xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
     <soap:Body> 
     <GetTerritoriesResponse xmlns="..."> 
      <GetTerritoriesResult>&lt;Territories&gt;&lt;State&gt;AZ&lt;/State&gt;&lt;ZipCode&gt;85203&lt;/ZipCode&gt;&lt;Territory&gt;&lt;City&gt;Mesa&lt;/City&gt;&lt;County&gt;Maricopa&lt;/County&gt;...&lt;/Territory&gt;&lt;/Territories&gt; 
      </GetTerritoriesResult> 
     </GetTerritoriesResponse> 
    </soap:Body> 
</soap:Envelope> 

...

所以看起來就像XmlSlurper一樣,當變量被打印出來時,會扔掉SOAP內容並評估最內層的節點(),而不會實際導航到該節點。這是預期的行爲?

我一直無法找到一個更完整和現代的SOAP調用和使用httpBuilder解析,所以我認爲XML將是正確的內容類型。但看起來我不得不接受TEXT並自己解析身體,這看起來很蹩腳。用httpBuilder處理SOAP響應是否有更好的方法?

回答

1

我建議打印響應的原始文本:

println "XML was ${resp.data.text}" 

假設印刷XML行是你所期望的(雖然奇怪,因爲沒有信封或身體節點),那麼你應該能夠從您對xml的引用中刪除區域。使用XmlSlurper進行分析時,根節點是GPathResult。

assert "Territories" == xml.name() 
println "State were ${xml.State.text()}" 
println "City were ${xml.Territory.City.text()}" 
println "County were ${xml.Territory.County.text()}" 

此外,只是想指出SOAP 1.2媒體類型是「application/soap + xml」。

UPDATE:

所以它看起來像的XmlSlurper,正在打印的變量 出來,被扔掉的SOAP的東西,並評估最裏面的節點 (),而沒有實際導航到節點。這是預期的 行爲?

是的,GPathResult的toString()方法只是打印所有文本節點而不是實際的元素或屬性。隨着HTTPBuilder您可以使用打印出來的原始響應文本:

println resp.data.text 

我一直無法使用httpBuilder找到AA更加完善,先進的SOAP調用和 解析,所以我認爲XML將正確的內容 類型。但看起來我不得不接受TEXT並自己解析身體,這看起來很蹩腳。用httpBuilder處理SOAP 響應有沒有更好的方法?

ContentType.XML是好的,問題是如何與SOAP響應所形成的Web服務的回報。 Web服務正在發回的領土結果在GetTerritoriesResult元素的編碼字符串,而不是實際的XML響應該HTTPBuilder中自動識別你的一部分(這是不是與方式有問題HTTPBuilder正在處理它)。由於您真正需要的數據是使用該編碼的字符串,因此您需要自己解析文本節點的GetTerritoriesResult的

response.success = { resp, xml ->  
    println "XML was ${resp.data.text}" 
    def territories = new XmlSlurper().parseText(
     xml.Body.GetTerritoriesResponse.GetTerritoriesResult.text() 
    ) 
    println "State were ${territories.State}" 
    println "City was ${territories.Territory.City}" 
    println "County was ${territories.Territory.County}" 
} 
+0

謝謝,這個評論是相當有幫助的。從我讀過的Scott Davis的Groovy Recipes中,我認爲text()是用於XmlParser,而不是XmlSlurper。儘管如此,打印出來的$ {xml}和$ {xml.name()}之間的不匹配仍然受到阻礙。你知道它爲什麼這樣做嗎? –

+0

打印出xml GPathResult時,它不顯示標籤,只顯示文本內容,所以這就是爲什麼你看到了你看到的結果。 –

+0

如果您在GPathResult上調用text(),它將返回一個包含該元素文本內容的String。在執行println時,通常不是必須的,因爲GPathResult上的toString()方法也會打印出元素的文本內容。 –