未正确分析Groovy HTTPBuilder SOAP响应

未正确分析Groovy HTTPBuilder SOAP响应,soap,groovy,httpbuilder,Soap,Groovy,Httpbuilder,我不明白为什么XmlSlurper显然没有处理结果 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 =

我不明白为什么XmlSlurper显然没有处理结果

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
            }
        } 

因此,当输出变量时,XmlSlurper似乎正在丢弃SOAP内容并计算最内部的节点(),而不是实际导航到该节点。这是预期的行为吗


我无法使用httpBuilder找到更完整、更现代的SOAP调用和解析,因此我认为XML将是正确的内容类型。但看起来我只需要接受文本并自己解析主体,这看起来很蹩脚。使用httpBuilder处理SOAP响应有更好的方法吗?

我建议打印响应的原始文本:

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()}"
另外,我只想指出SOAP1.2媒体类型是“application/SOAP+xml”

更新:

因此,当打印变量时,它看起来像XmlSlurper out就是扔掉SOAP内容并计算最里面的节点 (),而不是实际导航到该节点。这是预期的吗 行为

是的,GPathResult的toString()方法只打印所有文本节点,而不是实际的元素或属性。使用HTTPBuilder,您可以通过以下方式打印原始响应文本:

println resp.data.text
我一直无法找到一个更完整、更现代的SOAP调用和 使用httpBuilder解析,所以我认为XML是正确的内容 类型。但看起来我只需要接受文本并解析 我自己的身体,看起来很瘸。有更好的处理肥皂的方法吗 httpBuilder的响应

ContentType.XML
很好,问题在于web服务返回的SOAP响应是如何形成的。web服务将区域结果作为GetTerritoriesResult元素中的编码字符串发送回,而不是作为HTTPBuilder自动解析的实际XML响应的一部分(这不是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}"
}

谢谢,这个评论很有帮助。从我读到的Scott Davis的Groovy食谱中,我认为text()是用于XmlParser的,而不是用于XmlSlurper的。但是${xml}和${xml.name()。你知道它为什么这样做吗?打印xml GPathResult时,它不显示标记,只显示文本内容,所以这就是你看到结果的原因。如果对GPathResult调用text(),它将返回一个包含该元素文本内容的字符串。在执行println之类的操作时,通常没有严格必要这样做,因为GPathResult上的toString()方法也会打印出元素的文本内容。
assert "Territories" == xml.name()
println "State were ${xml.State.text()}"
println "City were ${xml.Territory.City.text()}"
println "County were ${xml.Territory.County.text()}"
println resp.data.text
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}"
}