Groovy replace node values ​​in xml using xpath

I want to replace node values ​​in xml in groovy. I have 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 to replace node values?

+3


source to share


1 answer


You can try XmlSlurper

, or maybe this is an easy way. You can define your map using node name as key and text as value, iterate over it by changing node in Xml. You can use code similar to 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 full path to more than just the node name in order to change its value (to be more reliable), you can define you XPath

using notation .

instead of notation /

and avoid the root node name (in your case Envelope

), because in the parsed the xml object already exists. Therefore, by changing your XPath, you can have something like:

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

      

Putting it all together in 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 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 am using this snippet:

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

      

See this snippet from this and comment which is a workaround to solve the .

way based on using variables (good workaround IMO :)

)

Hope it helps,

0


source







All Articles