【问题标题】:How to use GPath with variable?如何将 GPath 与变量一起使用?
【发布时间】:2018-02-21 18:42:21
【问题描述】:

假设我手头有以下 XML

<Envelope>
  <Body>
    <analyzeEffectOfReplaceOfferResponse>
      <productOfferings>
        <productOffering>
          <id>some value</id>
        </productOffering>
      </productOfferings>
    </analyzeEffectOfReplaceOfferResponse>
  </Body>
</Envelope>

在检索文件并解析后,我也有 GPathResult 形式的输入 XML:

inputXML = new XmlSlurper().parse(inputFile)

当我试图找到这样的节点时:

inputXML."Body"."analyzeEffectOfReplaceOfferResponse"."productOfferings"."productOffering".depthFirst().findAll {it.value}

我得到了所需的孩子“id”

但是,如果我使用包含此文本的字符串:

"Body"."analyzeEffectOfReplaceOfferResponse"."productOfferings"."productOffering"

并像这样使用它:

inputXML."${xPath}".depthFirst().findAll {it.value}

没用... 我做错了什么?

【问题讨论】:

    标签: variables groovy findall xmlslurper gpath


    【解决方案1】:

    在您当前的尝试中,Groovy 正在使用参数 "Body"."analyzeEffectOfReplaceOfferResponse"."productOfferings"."productOffering"inputXML 对象调用 getProperty 方法。

    由于没有具有该特定名称的 XML 子元素,因此找不到任何内容。

    相反,您的目标是按照以下方式动态链接调用:

    inputXML.getProperty('Body')
            .getProperty('analyzeEffectOfReplaceOfferResponse')
            .getProperty('productOfferings')
            .getProperty('productOffering')
            .depthFirst().findAll {it.value}
    

    您可以通过创建递归创建此链接的​​方法来做到这一点,例如

    def xPath = '"Body"."analyzeEffectOfReplaceOfferResponse"."productOfferings"."productOffering"'
    
    def getProperties(gpathResult, dotProp) {
        def props = dotProp?.split(/\./)
        props.length <= 1 ? gpathResult : getProperties(gpathResult[props.head() - '"' - '"'], (props.tail().join('.')))
    }
    
    getProperties(inputXML, xPath).depthFirst().findAll {it.value}
    

    或者您可以使用成熟的 XPath 库。

    【讨论】:

    • 不过,我很好奇——这最终让我得到了一个字符串集合。如果我想获取 XML 中的实际节点以便更新它们怎么办?
    • 您当前的代码返回代表 productOffering 节点及其父节点的 groovy.util.slurpersupport.NodeChildren 集合。
    • 有趣的方法,但只适用于最简单的gpath 表达式,即它不适用于例如A.B[1].C 或类似的,会吗?
    【解决方案2】:

    可以使用Eval.me:

    def inputXML = new XmlSlurper().parseText( '''<Envelope>
      <Body>
        <analyzeEffectOfReplaceOfferResponse>
          <productOfferings>
            <productOffering>
              <id>some value</id>
            </productOffering>
          </productOfferings>
        </analyzeEffectOfReplaceOfferResponse>
      </Body>
    </Envelope>''')
    
    println inputXML."Body"."analyzeEffectOfReplaceOfferResponse"."productOfferings"."productOffering".depthFirst().findAll {it.value}
    
    //use Eval.me groovy code evaluation
    def gpath = ' XML."Body"."analyzeEffectOfReplaceOfferResponse"."productOfferings"."productOffering" '
    println Eval.me( 'XML', inputXML, gpath ).depthFirst().findAll {it.value}
    
    //or even like this:
    gpath = ' XML."Body"."analyzeEffectOfReplaceOfferResponse"."productOfferings"."productOffering".depthFirst().findAll {it.value} '
    println Eval.me( 'XML', inputXML, gpath )
    

    【讨论】:

    • 但在此示例中,gpath 是一个字符串,您可以从任何存储中获取它...您能否提供更多信息究竟是什么不工作...
    • 我实际上发现了我的问题 - 这是简单的值错误。
    【解决方案3】:

    您是否必须使用字符串,或者您只是在寻找一种方法来存储元素的路径,以便您以后不必再次键入它?

    String xml = '<Envelope><Body><analyzeEffectOfReplaceOfferResponse><productOfferings><productOffering><id>some value</id></productOffering></productOfferings></analyzeEffectOfReplaceOfferResponse></Body></Envelope>'
    def Envelope = new XmlSlurper().parseText(xml)
    Closure takeMyPathFrom = {node -> node."Body"."analyzeEffectOfReplaceOfferResponse"."productOfferings"."productOffering"}
    assert takeMyPathFrom(Envelope) == "some value"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 2021-01-09
      • 2016-03-03
      • 2017-09-10
      相关资源
      最近更新 更多