Grails RestClient 访问 POST 响应 XML

Grails RestClient accessing POST response XML

我正在使用 Groovy 的 RESTClient() 执行 POST,其中一些 XML 作为 URL 的有效载荷。我期望得到的回复是

<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope
    xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:getNetworkSessionsForUsernameResponse
            xmlns:ns2="http://webservice.foo.bar.net/">
            <return>
                <ip>1.1.1.1</ip>
                <platform>112</platform>
                <pop>ABC</pop>
                <site>LIP</site>
                <state>STATUS</state>
                <userId>ID1234</userId>
            </return>
        </ns2:getNetworkSessionsForUsernameResponse>
    </S:Body>
</S:Envelope>

我已经蜷缩到 URL 并且知道响应是正确的,所以返回的数据不是问题。我的问题是 RESTClient().post().getData() returns 的格式。如果我这样做

def restClient = new RESTClient("www.someRestService.com", 'text/xml')

String soapRequest = """XML Payload..."""

def restClientResponse = restClient.post(body: soapRequest).getData()

log.info("RESPONSE: " + restClientResponse)
log.info("BODY: " + restClientResponse.Body.getNetworkSessionsForUsernameResponse.return.userId)
log.info("BODY T: " + restClientResponse.Body.getNetworkSessionsForUsernameResponse.return.userId.text())
log.info("NETWORK: " + restClientResponse.getNetworkSessionsForUsernameResponse.return.userId)
log.info("NETWORK T: " + restClientResponse.getNetworkSessionsForUsernameResponse.return.userId.text())
log.info("RETURN: " + restClientResponse.return.userId)
log.info("RETURN T: " + restClientResponse.return.userId.text())
log.info("USERID: " + restClientResponse.userId)
log.info("USERID T: " + restClientResponse.userId.text())
log.info("CHILDREN SIZE: " + restClientResponse.children().size())
log.info("CLASS: " + restClientResponse.getClass().getName())

记录的是:

RESPONSE: 1.1.1.1112ABCLIPSTATUSID1234
BODY:
BODY T:
NETWORK:
NETWORK T:
RETURN:
RETURN T:
USERID:
USERID T:
CHILDREN SIZE: 1
CLASS: groovy.util.slurpersupport.NodeChild

所以 getData() 似乎只是返回所有文本节点而不是解析的 XML 对象,我确定我在某处读到 getData() 解析 XML 使用 XMLSlurper()。我阅读了 this 文章以及其他许多文章,这些文章看起来与我的问题完全一样,但给出的答案正是我正在做的,不是吗?我是否以完全错误的方式访问 restClientResponse

RESTClient 在内部与 XmlSlurper 执行的内部 XML 可能是 non namespace aware:

所以,

def restClientResponse = new XmlSlurper(false, false).parseText('''<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope
    xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:getNetworkSessionsForUsernameResponse
            xmlns:ns2="http://webservice.foo.bar.net/">
            <return>
                <ip>1.1.1.1</ip>
                <platform>112</platform>
                <pop>ABC</pop>
                <site>LIP</site>
                <state>STATUS</state>
                <userId>ID1234</userId>
            </return>
        </ns2:getNetworkSessionsForUsernameResponse>
    </S:Body>
</S:Envelope>''')

println restClientResponse
def userId
userId = restClientResponse.Body.getNetworkSessionsForUsernameResponse.return.userId
println "${userId.size()}: [${userId.text()}]"
userId = restClientResponse.'S:Body'.'ns2:getNetworkSessionsForUsernameResponse'.return.userId
println "${userId.size()}: [${userId.text()}]"

以上结果:

1.1.1.1112ABCLIPSTATUSID1234
0: []
1: [ID1234]

(更改为 命名空间感知 XmlSlurper 结果恰恰相反)。

简答

我是个白痴!

中等答案

我正在处理的设计文档概述了预期从 REST 调用返回的 XML 是我包含在问题中的 XML,但实际上 XML 标签在真实响应中略有不同。 <ns2:getNetworkSessionsForUsernameResponse/> 实际上是 <ns2:getNetworkSessionsForIPResponse/>;尽管我卷曲了 REST 客户端并比较了响应,但我对哪里出了问题感到沮丧。如果您遇到类似问题,请仔细检查,然后再次检查您实际使用的 XML。

我在 github 上浏览了 RESTClient 源代码,然后才弄清楚我做错了什么;参考@jalobaba 回答 XMLSlurper() without any constructor args is used when parsing XML, so 'a non-validating and non-namespace-aware XmlSlurper' is created when an XML response is parsed