Sharing is caring - how to modify xml files using ReadyApi
Modifying xml files or simply working with xml strings might look difficult for a begginer so for those who need it I will try to break the whole thing into pieces so that it is easier to understand.
Refering to nodes and attributes
Let's say this piece of xml is stored in the file 'mijnFruits.xml' somewhere on your computer:
<fruits> <apples> <apple color="red"/> <apple color="green"/> </apples> <oranges> <clementine> <mandarine> </oranges> <bananas/> <jabu-ticaba/> </fruits>
If you would want to use a groovy script to identify a certain element, you'll first have to define a variable in which to parse the content:
def xml = new XmlSlurper().parse("D:\\someFolder\\mijnFruits.xml")
In order to refer to the 'clementine' node for instance, you would use:
xml.oranges.clementine // For instance, the following will replace the node 'clementine' with 'tangerine' // xml.oranges.clementine.replaceNode { // tangerine '' // }
Please note that while refering to any node, the root node (i.e. "fruits") is replaced by the variable in which the file is parsed (in our case 'xml'). That is why in our example we used 'xml.oranges.clementine' and not 'fruits.oranges.clementine'
In order to refer to a node that has a certain attribute ( for instance <apple color="red"/> ), the syntax is as follows:
// This will return a list will all the nodes 'xml.apples.apple' that have an attribute 'color' and the value 'red' xml.apples.apple.findAll{it.@color == "red"} // Hence, it is possible to check if such a node exists. For instance: //if (xml.apples.apple.findAll{it.@color == "red"}.size() == 0) // log.info("Such a node doesn't exist.") //else // log.info("Such a node exists.")
If you want to refer to a node whose name contains dashes (example: 'jabu-ticaba') then the name must be placed inside single quotes like
xml.'jabu-ticaba' // Example of node removing // xml.'jabu-ticaba'.replaceNode { }
Practical examples
Change an attribute value of a property
import groovy.xml.XmlUtil import groovy.util.Node // Parse the content of the document and store it in the 'xml' variable def xml = new XmlSlurper().parse("D:\\someFolder\\web.config") // Change the attribute value for 'xxs-protection' xml.webApplication.'xss-protection'.@enabled = "false" // Construct a FileWriter object and assigns it to the variable 'writer' def writer = new FileWriter("D:\\someFolder\\web.config") // Write the changes to the file XmlUtil.serialize(xml, writer) // Close file writer.close()
Add a new node
import groovy.xml.XmlUtil import groovy.util.Node // Parse the content of the document and store it in the 'xml' variable def xml = new XmlSlurper().parse("D:\\someFolder\\web.config") // Add a node called 'conf' inside the <confs></confs> tags. The node will have 3 attributes (name, project and version) along with their corresponding values ('myName', 'myProj' and 'v0.0') xml.shortcutSection.shortcuts.appendNode { shortcut(name: "myName", project: "myProject", version: "v0.0") } // Construct a FileWriter object and assigns it to the variable 'writer' def writer = new FileWriter("D:\\someFolder\\web.config") // Write the changes to the file XmlUtil.serialize(xml, writer) // Close file writer.close() // The output will look like // <confs> // <conf name="myName" project="myProject" version="v0.0"/> // </confs>
Add a more complex node
import groovy.xml.XmlUtil import groovy.util.Node // Parse the content of the document and store it in the 'xml' variable def xml = new XmlSlurper().parse("D:\\mijn\\Web.config") // Add a more complex node (which contain more nodes or attributes) xml.'hibernate-configuration'.'session-factories'.appendNode { 'session-factory'(name: "test") { properties { property(name: "one hell of a property", value: "great of course") property(name: "another hell of a property", value: "great again of course") property(name: "avcsacsadsadsa", value: "asdsadsadasda") property(name: "asdsadsadas", value: "asdsadsadsa") property(name: "another hell of a property", value: "great again of course") } } } // Construct a FileWriter object and assigns it to the variable 'writer' def writer = new FileWriter("D:\\mijn\\Web.config") // Write the changes to the file XmlUtil.serialize(xml, writer) // Close file writer.close()
Remove a node
import groovy.xml.XmlUtil import groovy.util.Node // Parse the content of the document and store it in the 'xml' variable def xml = new XmlSlurper().parse("D:\\mijn\\Web.config") // Remove a node xml.shortcutSection.replaceNode { } // this removes the shortcutSection node along with its containments // Construct a FileWriter object and assigns it to the variable 'writer' def writer = new FileWriter("D:\\mijn\\Web.config") // Write the changes to the file XmlUtil.serialize(xml, writer) // Close file writer.close()
Remove a node that contains a certain attribute
import groovy.xml.XmlUtil import groovy.util.Node // Parse the content of the document and store it in the 'xml' variable def xml = new XmlSlurper().parse("D:\\mijn\\Groovy projects\\Web.config") // Delete a node that has a certain given attribute xml.'hibernate-configuration'.'session-factories'.'session-factory'.findAll{it.@name == "myName"}.replaceNode { } // Construct a FileWriter object and assigns it to the variable 'writer' def writer = new FileWriter("D:\\mijn\\Groovy projects\\Web.config") // Write the changes to the file XmlUtil.serialize(xml, writer) // Close file writer.close()
Replace a node
import groovy.xml.XmlUtil import groovy.util.Node // Parse the content of the document and store it in the 'xml' variable def xml = new XmlSlurper().parse("D:\\mijn\\Groovy projects\\Web.config") xml.configSections.replaceNode { noMoreConfigSection '' } // Construct a FileWriter object and assigns it to the variable 'writer' def writer = new FileWriter("D:\\mijn\\Groovy projects\\Web.config") // Write the changes to the file XmlUtil.serialize(xml, writer) // Close file writer.close() // The result would be that the configSections node i.e. // <configSections> // <section ...> // <section ...> // </configSections> // would be replaced by <noMoreConfigSection/>