使用Groovy中的命名空间正确地迭代XML

时间:2012-07-23 21:02:06

标签: groovy namespaces xml-parsing soapui xmlslurper

我有以下xml代码:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <cms:RelatedConfigurationItemList xmlns:cms="some namespace">
         <ConfigurationItem>
            <name>data</name>
            <id>data</id>
            <type>data</type>
            <relationship>IS CHILD OF</relationship>
            <ConfigurationItemList>
               <ConfigurationItem>
                  <name>data</name>
                  <id>data</id>
                  <type>data</type>
                  <relationship>IS CHILD OF</relationship>
                  <ConfigurationItemList/>
               </ConfigurationItem>
               <ConfigurationItem>
                  <name>data</name>
                  <id>data</id>
                  <type>data</type>
                  <relationship>IS CHILD OF</relationship>
                  <ConfigurationItemList/>
               </ConfigurationItem>
            </ConfigurationItemList>
         </ConfigurationItem>
     <ConfigurationItem>
            <name>other data</name>
            <id>other data</id>
            <type>other data</type>
            <relationship>IS CHILD OF</relationship>
            <ConfigurationItemList>
               <ConfigurationItem>
                  <name>other data</name>
                  <id>other data</id>
                  <type>other data</type>
                  <relationship>IS CHILD OF</relationship>
                  <ConfigurationItemList/>
               </ConfigurationItem>
               <ConfigurationItem>
                  <name>other data</name>
                  <id>other data</id>
                  <type>other data</type>
                  <relationship>IS CHILD OF</relationship>
                  <ConfigurationItemList/>
               </ConfigurationItem>
            </ConfigurationItemList>
         </ConfigurationItem>
      </cms:RelatedConfigurationItemList>
   </soapenv:Body>
</soapenv:Envelope>

我想使用以下伪代码在Groovy中验证:

def request = testRunner.testCase.getTestStepByName( "relationship_request" )
def resp = new File('H://test_xml.xml')
def cms_ns = new groovy.xml.Namespace("namespace for cms",'cms')
def soap_ns = new groovy.xml.Namespace("http://schemas.xmlsoap.org/soap/envelope/",'soapenv')
def root = new XmlSlurper().parse(resp)


def config_item = root[soap_ns.Envelope][soap_ns.Body][cms_ns.RelatedConfigurationItemList][ConfigurationItem]

config_item.each{
    it.name.each{
        it == corresponding value in db?
        else
        die
    }
}

但我似乎无法获得语法,逻辑正确尝试验证数据库响应定义的值(如名称)。如果config_item声明是正确的,那么我可能对Groovy闭包知之甚少。此外,我不确定XML slurper或解析器是否更合适,并且无法确定差异究竟是什么。希望这是对问题的充分描述。

3 个答案:

答案 0 :(得分:2)

XmlSlurper按需工作,内存密集程度较低。当您需要访问xml的许多节点时,通常使用XmlParser。或者,如果您只想读取xml的一个或两个节点,则使用Slurper。

This example应该可以帮助您了解XMLParser的工作原理。

在您的情况下,配置项声明和命名空间使用在语法上是正确的,但它可能是使用XmlParser的理想选择,因为您可能正在验证xml的许多或所有组件。您可能会对使用闭包访问元素感到困惑。这是没有命名空间的示例,可以帮助您理解。

   xml = '''<Envelope>
   <Body>
      <RelatedConfigurationItemList>
         <ConfigurationItem>
            <name>Top level name1</name>
            <id>Top level id1</id>
            <type>Top level type1</type>
            <relationship>IS CHILD OF</relationship>
            <ConfigurationItemList>
               <ConfigurationItem>
                  <name>data1</name>
                  <id>data1</id>
                  <type>data1</type>
                  <relationship>IS CHILD OF</relationship>
                  <ConfigurationItemList/>
               </ConfigurationItem>
               <ConfigurationItem>
                  <name>data2</name>
                  <id>data2</id>
                  <type>data2</type>
                  <relationship>IS CHILD OF</relationship>
                  <ConfigurationItemList/>
               </ConfigurationItem>
            </ConfigurationItemList>
         </ConfigurationItem>
     <ConfigurationItem>
            <name>Top level name2</name>
            <id>Top level id2</id>
            <type>Top level type2</type>
            <relationship>IS CHILD OF</relationship>
            <ConfigurationItemList>
               <ConfigurationItem>
                  <name>other data</name>
                  <id>other data</id>
                  <type>other data</type>
                  <relationship>IS CHILD OF</relationship>
                  <ConfigurationItemList/>
               </ConfigurationItem>
               <ConfigurationItem>
                  <name>other data</name>
                  <id>other data</id>
                  <type>other data</type>
                  <relationship>IS CHILD OF</relationship>
                  <ConfigurationItemList/>
               </ConfigurationItem>
            </ConfigurationItemList>
         </ConfigurationItem>
      </RelatedConfigurationItemList>
   </Body>
</Envelope>'''



def Envelope = new XmlParser().parseText(xml)

//For accessing top level top level Configuration Item
Envelope.Body.RelatedConfigurationItemList.ConfigurationItem.each{
 //Put your check conditions here.. == or any other
 assert it.name.text().contains("Top level name")
 assert it.id.text().contains("Top level id")
 assert it.type.text().contains("Top level type")
 //Inner children configuration items
 it.ConfigurationItemList.ConfigurationItem.each{
     assert it.name.text().contains("data")
     assert it.id.text().contains("data")
     assert it.type.text().contains("data")
 }       
}

答案 1 :(得分:1)

你几乎拥有它......

如果您使用XmlParser(由Vamsi建议)而不是XmlSlurper,则会获得:

def cms_ns = new groovy.xml.Namespace("some namespace",'cms')
def soap_ns = new groovy.xml.Namespace("http://schemas.xmlsoap.org/soap/envelope/",'soapenv')
def root = new XmlParser().parse(resp)

def config_item = root[soap_ns.Body][cms_ns.RelatedConfigurationItemList].ConfigurationItem

您无需使用Envelope标记进行区分,因为它们是根节点,因此它已被视为已加载。

答案 2 :(得分:0)

XmlSlurper很好。请尝试以下方法:

def configItem = root.'**'.findAll{
   it.name()=='ConfigurationItem'
}

configItem.each{
   // check data here
}

这应该以递归方式检查所有配置项,假设这是您要完成的任务。