Groovy用xpath替换xml中的节点值 [英] Groovy replace node values in xml with xpath

查看:229
本文介绍了Groovy用xpath替换xml中的节点值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用groovy替换xml中的节点值。
我有一个hashmap中的xpath值,例如:

  def param = [:] 
param [/ Envelope / Body / GetWeather / CityName] =Berlin
param [/ Envelope / Body / GetWeather / CountryName] =Germany

XML文件:

 <?xml version = 1.0encoding =UTF-8?>< soapenv:Envelope xmlns:soapenv =http://schemas.xmlsoap.org/soap/envelope/> 
< soapenv:Header />
< soapenv:Body>
< web:GetWeather xmlns:web =http://www.webserviceX.NET>
< web:CityName>测试< / web:CityName>
< web:CountryName>测试< / web:CountryName>
< / web:GetWeather>
< / soapenv:Body>
< / soapenv:Envelope>

如何替换节点值?

解决方案

您可以尝试使用 XmlSlurper ,反而可能是一种简单的方法。您可以使用节点名称作为关键字定义地图,并将文本作为值迭代,以更改Xml中的节点。您可以使用类似下面的代码:

  import groovy.util.XmlSlurper 
import groovy.xml.XmlUtil

def xmlString ='''< soapenv:Envelope xmlns:soapenv =http://schemas.xmlsoap.org/soap/envelope/>
< soapenv:Header />
< soapenv:Body>
< web:GetWeather xmlns:web =http://www.webserviceX.NET>
< web:CityName>测试< / web:CityName>
< web:CountryName>测试< / web:CountryName>
< / web:GetWeather>
< / soapenv:Body>
< / soapenv:Envelope>'''

def param = [:]
param [CityName] =Berlin
param [ ] =德国

//解析xml
def xml = new XmlSlurper()。parseText(xmlString)

//对于每个键,值在地图
param.each {key,value - >
//如果其名称匹配
xml。'**',则更改节点值findAll {if(it.name()== key)it.replaceBody value}
}

println XmlUtil.serialize(xml)

另一种可能的解决方案<相反,如果你想使用完整的路径,不仅节点名称改变它的值(更健壮),你可以定义你 XPath 使用符号而不是 / 表示法并避免根节点名称你的情况 Envelope ),因为在已解析的xml对象中它已经存在了。所以改变你的XPath你可以有这样的东西:

  def param = [:] 
//因为信封是根节点没有必要
param [Body.GetWeather.CityName] =Berlin
param [Body.GetWeather.CountryName] =Germany
  



$ b

import groovy.util.XmlSlurper
import groovy.xml.XmlUtil
$ b $ def xmlString ='''< soapenv:Envelope xmlns:soapenv =http://schemas.xmlsoap.org/皂/信封/>
< soapenv:Header />
< soapenv:Body>
< web:GetWeather xmlns:web =http://www.webserviceX.NET>
< web:CityName>测试< / web:CityName>
< web:CountryName>测试< / web:CountryName>
< / web:GetWeather>
< / soapenv:Body>
< / soapenv:Envelope>'''

def param = [:]
//因为信封是根节点,所以不需要
param [ Body.GetWeather.CityName] =Berlin
param [Body.GetWeather.CountryName] =Germany

def xml = new XmlSlurper()。parseText(xmlString)

param.each {key,value - >
def node = xml
key.split(\\\。)。each {
node = node。$ {it}
}
node.replaceBody value


println XmlUtil.serialize(xml)

请注意,在第二种解决方案中,我使用以下片段:

  def node = xml 
key.split \\。)。each {
node = node。$ {it}
}

这段代码来自回答 comment 这是解决使用变量的路径的解决方法一个好的解决方法国际海事组织:)



希望这有助于,


I want to replace the node values in a xml in groovy. I have the values in xpath in a hashmap like:

 def param = [:]       
 param["/Envelope/Body/GetWeather/CityName"] = "Berlin"
 param["/Envelope/Body/GetWeather/CountryName"] = "Germany"

XML File:

 <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header/>
  <soapenv:Body>
      <web:GetWeather xmlns:web="http://www.webserviceX.NET">
          <web:CityName>Test</web:CityName>
          <web:CountryName>Test</web:CountryName>
      </web:GetWeather>
  </soapenv:Body>
</soapenv:Envelope>

How can I replace the node values?

解决方案

You can try using XmlSlurper instead probably it's an easy way. You can define your map using the node name as a key and the text as a value iterate over it changing the node in the Xml. You can use something similar the code below:

import groovy.util.XmlSlurper
import groovy.xml.XmlUtil

def xmlString = '''<soapenv:Envelope   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header/>
  <soapenv:Body>
      <web:GetWeather xmlns:web="http://www.webserviceX.NET">
          <web:CityName>Test</web:CityName>
          <web:CountryName>Test</web:CountryName>
      </web:GetWeather>
  </soapenv:Body>
</soapenv:Envelope>'''

def param = [:]       
param["CityName"] = "Berlin"
param["CountryName"] = "Germany"

// parse the xml
def xml = new XmlSlurper().parseText(xmlString)

// for each key,value in the map
param.each { key,value ->
    // change the node value if the its name matches
    xml.'**'.findAll { if(it.name() == key) it.replaceBody value }
}

println XmlUtil.serialize(xml)

Another possible solution

Instead if you want to use the complete path not only the node name to change its value (to be more robust) you can define you XPath using . notation instead of / notation and avoid root node name (in your case Envelope) because in the parsed xml object it's already there. So changing your XPath you can have something like:

def param = [:]       
// since envelope is the root node it's not necessary
param["Body.GetWeather.CityName"] = "Berlin"
param["Body.GetWeather.CountryName"] = "Germany"

All together in the code:

import groovy.util.XmlSlurper
import groovy.xml.XmlUtil

def xmlString = '''<soapenv:Envelope   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header/>
  <soapenv:Body>
      <web:GetWeather xmlns:web="http://www.webserviceX.NET">
          <web:CityName>Test</web:CityName>
          <web:CountryName>Test</web:CountryName>
      </web:GetWeather>
  </soapenv:Body>
</soapenv:Envelope>'''

def param = [:]       
// since envelope is the root node it's not necessary
param["Body.GetWeather.CityName"] = "Berlin"
param["Body.GetWeather.CountryName"] = "Germany"

def xml = new XmlSlurper().parseText(xmlString)

param.each { key,value ->
    def node = xml
    key.split("\\.").each {
      node = node."${it}"
    }
    node.replaceBody value
}

println XmlUtil.serialize(xml)

Note that in the second solution I use this snippet:

    def node = xml
    key.split("\\.").each {
      node = node."${it}"
    }

This snippet it's from this answer and comment which is a workaround to solve . path based using variables (a good workaround IMO :))

Hope this helps,

这篇关于Groovy用xpath替换xml中的节点值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆