如何将XML节点路径作为参数传递给groovy中的方法?

How to transfer the XML node path as a parameter to a method in groovy?

我编写了以下代码来验证 XML 节点值。 当我们必须遍历单个节点并打印值时,下面的代码工作正常。 但是当我尝试遍历任何子节点和 return 节点值时,我无法检索到正确的值。

//Sample XML (sample_2015-10-12.xml)
<a>
   <b>
      <c1 Action="C">
         <Id>12345</Id>
         <DisplayName>User1</DisplayName>
         <Price>68.0000</Price>
         <d>
            <mv>
               <value>29</value>
            </mv>
         </d>
      </c1>
      <c2 Action="C">
         <Id>12378</Id>
         <DisplayName>User2</DisplayName>
         <Price>70.0000</Price>
         <d>
            <mv>
               <value>30</value>
            </mv>
         </d>
      </c2>   
   </b>
</a>


//Call class example and pass the node path as a parameter
library = testRunner.testCase.testSuite.project.testSuites["XMLValidate"]
module = library.testCases["XMLValidate"].testSteps["validateXML"]
module.run(testRunner, context)
def example = context.example
log.info "example.execute() = " + example.execute("d.mv.value");    


//Traverse the XML node and print the node value
class Example
{
   def log
   def context
   def testRunner
   def xPath

   // Class constructor with same case as Class name
   def Example(logIn,contextIn,testRunnerIn)
   {
      this.log = logIn
      this.context = contextIn
      this.testRunner = testRunnerIn
      this.xPath = xPath
   }
    def execute(xPath)
   {
        log.info xPath
        def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
        def XMLPath = context.expand("F:\Sample_2015-10-12.xml");
        def samplexml = new File(XMLPath).text;
        def root = new XmlParser().parseText( samplexml )
        def strPath = XMLPath.split(Pattern.quote('\'))
        def strFileName = strPath[strPath.size()-1].split('_');


    int cnt = 0
    switch( strFileName[0] ){
        case "Sample":
            def Var = root.b.c
            log.info Var
            Var.any{
                String intNum = it.Id.collect {it.text()}
                log.info it.Id.collect {it.text()}
                if (intNum.replace('[','').replace(']','') == "12378"){
                    log.info cnt
                    true
                }
                else{
                    cnt = cnt + 1
                    return
                }           
            }

            def Var2 = root.b.c[cnt]."${xPath}"
            log.info Var2.collect {it.text()}
    }


  }
}
context.setProperty( "example", new Example( log, context, testRunner) )

请帮忙

您可以将路径分解为每个部分(例如 dmv value) 然后调用 Node.getAt(String) 向下遍历层次结构。这是一个例子。

例子

import groovy.util.XmlParser
import groovy.util.Node

def data = '''
<a>
   <b>
      <c1 Action="C">
         <Id>12345</Id>
         <DisplayName>User1</DisplayName>
         <Price>68.0000</Price>
         <d>
            <mv>
               <value>29</value>
            </mv>
         </d>
      </c1>
      <c2 Action="C">
         <Id>12378</Id>
         <DisplayName>User2</DisplayName>
         <Price>70.0000</Price>
         <d>
            <mv>
               <value>30</value>
            </mv>
         </d>
      </c2>   
   </b>
</a>
'''

def xml = new XmlParser().parseText(data)
def example = new Example(xml)

example.execute('d.mv.value')
example.execute(['d', 'mv', 'value'])

@groovy.transform.TupleConstructor
class Example {
    Node xml

    def execute(String path) {
        execute(path.tokenize('.'))
    }

    def execute(List<String> properties) {
        def base = xml.b.'*' // This means the base path is a.b.[ANY NODE]

        /* 
         * Calls Node.getAt(String) on each Node.
         * Example:
         * xml.b.'*'.getAt('d').getAt('mv').getAt('value')
         * which is the same as: xml.b.'*'.d.mv.value
         */
        properties.inject(base) {node, propertyName ->
            node.getAt(propertyName)
        }        
    }
}

输出是 NodeCollection。如果你只想要这些值,你可以这样做:example.execute('d.mv.value').collect { it.value().head() } which returns: [29, 30]