简体   繁体   English

如何使用groovy脚本循环遍历XML子节点

[英]How to loop over XML child nodes using groovy script

I have an XML response as below: 我有一个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>

I am trying this to iterate childnodes details and address to validate the response with the request properties. 我正在尝试迭代子节点详细信息和地址以使用请求属性验证响应。 But I could assert email but couldn't go into details (name and area) and address (code and country). 但我可以断言电子邮件,但无法详细说明(姓名和地区)和地址(代码和国家/地区)。 Below is the code I am using 以下是我正在使用的代码

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

Please help me in iterating the nodes details(name and area) and address (code and country) for assertion 请帮助我迭代断言的节点详细信息(名称和区域)和地址(代码和国家/地区)

First of all, it seems that your xml is slightly broken with missing closing tags. 首先,似乎你的xml因缺少结束标记而略微破碎。 I took the liberty of fixing that in the example below. 我冒昧地在下面的例子中解决了这个问题。

Conceptually, when you are navigating through the xml with expressions like xml.Envelope.Body.response you are navigating through xml nodes. 从概念上讲,当您使用xml.Envelope.Body.response表达式浏览xml时,您将浏览xml节点。 Note the distinction here between xml nodes (ie elements) and the actual data or text within the nodes. 请注意xml节点(即元素)与节点内的实际数据或文本之间的区别。

The xml nodes returned from XmlSlurper are represented as descendants of the groovy GPathResult class. 从XmlSlurper返回的xml节点表示为groovy GPathResult类的后代。 These descendants include NodeChild, NodeChildren, NoChildren, and Attribute, all of which can be returned by an xml.Envelope.Body.Response type of query depending on how the query and the xml looks. 这些后代包括NodeChild,NodeChildren,NoChildren和Attribute,所有这些都可以通过xml.Envelope.Body.Response类型的查询返回,具体取决于查询和xml的外观。 To retrieve the actual text data within a node you need to call node.text() . 要检索节点内的实际文本数据,需要调用node.text()

With the xml fixed and the above in mind, the following code: 修复了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"

runs and all the assertions succeed. 运行并且所有断言都成功。

The contactNodes variable is a groovy NodeChildren object and can for all intents and purposes be treated as a List of nodes (ie you can call methods like .each {} , .every {} , .any {} , ... on it). contactNodes变量是一个groovy NodeChildren对象,可以将所有意图和目的都视为节点列表(即你可以调用.each {} .every {} .any {} ,...等方法) 。

edit in response to comment : To iterate only over contact nodes with specific properties, you can do: 编辑以响应评论 :要仅对具有特定属性的联系节点进行迭代,您可以执行以下操作:

xml.Body.response.customer.contact.findAll { contactNode ->
    contactNode.type.text() == 'firstclass' 
}.each { firstClassContactNode -> 
    assert firstClassContactNode.email.text() == "kevin@....com"
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM