如何使用 groovy 脚本遍历 XML 个子节点
How to loop over XML child nodes using groovy script
我有一个 XML 回复如下:
<ns:Envelope xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/">
<ns:Body>
<ns:response xmlns:svc="http://...serviceNameSpace"
xmlns:ent="http://....entitiesNameSpace">
<ns:customer>
<ns:contact>
<ns:type>firstclass</ns:type>
<ns:email>kevin@....com</ns:email>
<ns:details>
<ns:name>Kevin</ns:name>
<ns:area>Networking</ns:area>
</ns:details>
<ns:address>
<ns:code>39343</ns:code>
<ns:country>US</ns:country>
</ns:address>
</ns:contact>
<ns:contact>
<ns:type>secondclass</ns:type>
<ns:email>john@...com</ns:email>
<ns:details>
<ns:name>John</ns:name>
<ns:area>Development</ns:area>
<ns:address>
<ns:code>23445</ns:code>
<ns:country>US</ns:country>
</ns:contact>
</ns:customer>
</ns:response >
</ns:Body>
我正在尝试迭代子节点的详细信息和地址,以使用请求属性验证响应。但我可以断言电子邮件,但无法详细说明(名称和地区)和地址(代码和国家/地区)。下面是我使用的代码
import groovy.xml.*
def envelope = new XmlSlurper().parseText(messageExchange.responseContentAsXml)
def type = 'secondclass'
def emailAddress= ${properties#emailAddress}
envelope.'**'
.findAll { it.name() == 'contact' }
.findAll { it.type.text().contains(type) }
.each {
assert emailAddress== it.emailAddress.text()
}
请帮我迭代节点详细信息(名称和区域)和地址(代码和国家)以进行断言
首先,您的 xml 似乎有点损坏,缺少结束标记。我冒昧地在下面的例子中修复了这个问题。
从概念上讲,当您使用 xml.Envelope.Body.response
等表达式在 xml 中导航时,您就是在 xml 节点中导航。请注意 xml 节点(即元素)与节点内的实际数据或文本之间的区别。
从 XmlSlurper 返回的 xml 节点表示为 groovy GPathResult class 的后代。这些后代包括 NodeChild、NodeChildren、NoChildren 和 Attribute,所有这些都可以由 xml.Envelope.Body.Response
类型的查询返回,具体取决于查询和 xml 的外观。要检索节点内的实际文本数据,您需要调用 node.text()
。
固定 xml 并牢记以上内容,以下代码:
def str = '''\
<ns:Envelope xmlns:ns="http://schemas.xmlsoap.org/soap/envelope/">
<ns:Body>
<ns:response xmlns:svc="http://...serviceNameSpace" xmlns:ent="http://....entitiesNameSpace">
<ns:customer>
<ns:contact>
<ns:type>firstclass</ns:type>
<ns:email>kevin@....com</ns:email>
<ns:details>
<ns:name>Kevin</ns:name>
<ns:area>Networking</ns:area>
</ns:details>
<ns:address>
<ns:code>39343</ns:code>
<ns:country>US</ns:country>
</ns:address>
</ns:contact>
<ns:contact>
<ns:type>secondclass</ns:type>
<ns:email>john@...com</ns:email>
<ns:details>
<ns:name>John</ns:name>
<ns:area>Development</ns:area>
</ns:details>
<ns:address>
<ns:code>23445</ns:code>
<ns:country>US</ns:country>
</ns:address>
</ns:contact>
</ns:customer>
</ns:response >
</ns:Body>
</ns:Envelope>
'''
def xml = new XmlSlurper(false, true).parseText(str)
def contactNodes = xml.Body.response.customer.contact
assert contactNodes.first().email == 'kevin@....com'
assert contactNodes.first().details.name.text() == "Kevin"
assert contactNodes.first().details.area.text() == "Networking"
assert contactNodes.last().email == 'john@...com'
assert contactNodes.last().details.name.text() == "John"
assert contactNodes.last().details.area.text() == "Development"
运行并且所有断言都成功。
contactNodes
变量是一个groovy NodeChildren object and can for all intents and purposes be treated as a List of nodes (i.e. you can call methods like .each {}
, .every {}
, .any {}
, ...就可以了)。
编辑以回应评论:要仅迭代具有特定属性的接触节点,您可以这样做:
xml.Body.response.customer.contact.findAll { contactNode ->
contactNode.type.text() == 'firstclass'
}.each { firstClassContactNode ->
assert firstClassContactNode.email.text() == "kevin@....com"
}
我有一个 XML 回复如下:
<ns:Envelope xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/">
<ns:Body>
<ns:response xmlns:svc="http://...serviceNameSpace"
xmlns:ent="http://....entitiesNameSpace">
<ns:customer>
<ns:contact>
<ns:type>firstclass</ns:type>
<ns:email>kevin@....com</ns:email>
<ns:details>
<ns:name>Kevin</ns:name>
<ns:area>Networking</ns:area>
</ns:details>
<ns:address>
<ns:code>39343</ns:code>
<ns:country>US</ns:country>
</ns:address>
</ns:contact>
<ns:contact>
<ns:type>secondclass</ns:type>
<ns:email>john@...com</ns:email>
<ns:details>
<ns:name>John</ns:name>
<ns:area>Development</ns:area>
<ns:address>
<ns:code>23445</ns:code>
<ns:country>US</ns:country>
</ns:contact>
</ns:customer>
</ns:response >
</ns:Body>
我正在尝试迭代子节点的详细信息和地址,以使用请求属性验证响应。但我可以断言电子邮件,但无法详细说明(名称和地区)和地址(代码和国家/地区)。下面是我使用的代码
import groovy.xml.*
def envelope = new XmlSlurper().parseText(messageExchange.responseContentAsXml)
def type = 'secondclass'
def emailAddress= ${properties#emailAddress}
envelope.'**'
.findAll { it.name() == 'contact' }
.findAll { it.type.text().contains(type) }
.each {
assert emailAddress== it.emailAddress.text()
}
请帮我迭代节点详细信息(名称和区域)和地址(代码和国家)以进行断言
首先,您的 xml 似乎有点损坏,缺少结束标记。我冒昧地在下面的例子中修复了这个问题。
从概念上讲,当您使用 xml.Envelope.Body.response
等表达式在 xml 中导航时,您就是在 xml 节点中导航。请注意 xml 节点(即元素)与节点内的实际数据或文本之间的区别。
从 XmlSlurper 返回的 xml 节点表示为 groovy GPathResult class 的后代。这些后代包括 NodeChild、NodeChildren、NoChildren 和 Attribute,所有这些都可以由 xml.Envelope.Body.Response
类型的查询返回,具体取决于查询和 xml 的外观。要检索节点内的实际文本数据,您需要调用 node.text()
。
固定 xml 并牢记以上内容,以下代码:
def str = '''\
<ns:Envelope xmlns:ns="http://schemas.xmlsoap.org/soap/envelope/">
<ns:Body>
<ns:response xmlns:svc="http://...serviceNameSpace" xmlns:ent="http://....entitiesNameSpace">
<ns:customer>
<ns:contact>
<ns:type>firstclass</ns:type>
<ns:email>kevin@....com</ns:email>
<ns:details>
<ns:name>Kevin</ns:name>
<ns:area>Networking</ns:area>
</ns:details>
<ns:address>
<ns:code>39343</ns:code>
<ns:country>US</ns:country>
</ns:address>
</ns:contact>
<ns:contact>
<ns:type>secondclass</ns:type>
<ns:email>john@...com</ns:email>
<ns:details>
<ns:name>John</ns:name>
<ns:area>Development</ns:area>
</ns:details>
<ns:address>
<ns:code>23445</ns:code>
<ns:country>US</ns:country>
</ns:address>
</ns:contact>
</ns:customer>
</ns:response >
</ns:Body>
</ns:Envelope>
'''
def xml = new XmlSlurper(false, true).parseText(str)
def contactNodes = xml.Body.response.customer.contact
assert contactNodes.first().email == 'kevin@....com'
assert contactNodes.first().details.name.text() == "Kevin"
assert contactNodes.first().details.area.text() == "Networking"
assert contactNodes.last().email == 'john@...com'
assert contactNodes.last().details.name.text() == "John"
assert contactNodes.last().details.area.text() == "Development"
运行并且所有断言都成功。
contactNodes
变量是一个groovy NodeChildren object and can for all intents and purposes be treated as a List of nodes (i.e. you can call methods like .each {}
, .every {}
, .any {}
, ...就可以了)。
编辑以回应评论:要仅迭代具有特定属性的接触节点,您可以这样做:
xml.Body.response.customer.contact.findAll { contactNode ->
contactNode.type.text() == 'firstclass'
}.each { firstClassContactNode ->
assert firstClassContactNode.email.text() == "kevin@....com"
}