Writing updated XML to originally parsed file - groovy

I have a gradle.build where I am trying to:
read an XML file
use XmlSlurper to update an attribute in the read XML file
write the updated XML back to the originally parsed xml file.
The third step only works if I write the modified XML to a new non-existing XML file, but not the originally parsed XML file.
What is the simplest way to write the modified XML to the originally parsed XML file?
My code so far:
def inFile = file('file.xml')
def outFile = file('_file.xml')
def xml = new XmlSlurper().parse(inFile)
// update xml code here
def outBuilder = new StreamingMarkupBuilder()
def outWriter = outFile.newWriter()
XmlUtil.serialize(outBuilder.bind{ mkp.yield xml }, outWriter)
I would like outFile to be file.xml so that it overwrites the original XML file.

What happens if you do:
def inFile = file( 'file.xml' )
def xml = new XmlSlurper().parse( inFile )
xml.appendNode {
haha( 'tim_yates' )
}
inFile.withWriter { outWriter ->
XmlUtil.serialize( new StreamingMarkupBuilder().bind{ mkp.yield xml }, outWriter )
}
Is it just not written? (seems to work for me)

Related

How can I decompress a GET response using SOAPUI

I am getting a zipped response from a server.
Using CURL and | gunzip I am able to get the unzipped content response, but I would like not to use CURL and decompress it directly via SOAPUI, by a header, or by a script.
I tried to write something like:
def responseBody=testRunner.testCase.getTestStepByName("getZIp").httpRequest.response.responseContent;
InputStream ins = new ByteArrayInputStream(responseBody.getBytes())
log.info responseBody
def outFile = new FileOutputStream(new File('/users/trythis.zip'))
if (ins) {
com.eviware.soapui.support.Tools.writeAll(outFile, ins )
}
ins.close()
outFile.close()
but the data is still compressed.
something straight-forward like:
InputStream ins = new ByteArrayInputStream(responseBody.getBytes())
def outFile = new File('/users/trythis.txt')
new GZIPInputStream( ins ).withReader{ outFile << it }
In SoapUI's preferences, there are options for working with API's which expected compressed payloads and/or send back compressed responses.
I've used this in the past and SoapUI decompresses the response and presents that in the UI so I didn't have to resort to Groovy scripts to read the response.

Decoding a base64 string from JSON content in SOAPUI using groovy

I get a json response from a REST api that looks like below
{
"parentnode1": {
"childnode1": "abc12345-123-1234-1234-64a0251575f9",
"childnode2": "VAL1",
"childnode3": "format/pdf",
"childnode4": "name.pdf",
"base64content": "JVBERi0xLjUNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwRU9G"},
"messages": "This is a message"
}
I want to decode the value of "base64content" and then convert that into a pdf file and save it to a local directory. Is this possible in SOAP UI and Groovy ?
I came up with this groovy script but have not tested it in SOAPUI (have never used it). Try this and let me know what happens:
def jsonSlurper = new JsonSlurper()
def object = jsonSlurper.parseText (json_response)
String content_decoded = object.base64content.decodeBase64()
def file = new java.io.File("output.pdf")
FileOutputStream fos = new java.io.FileOutputStream(file)
fos.write( content_decoded )
fos.flush()
fos.close()


Parsing xml file at build time and modify its values/content

I want to parse a xml file during build time in build.gradle file and want to modify some values of xml, i follow this SO question and answer Load, modify, and write an XML document in Groovy but not able to get any change in my xml file. can anyone help me out. Thanks
code in build.gradle :
def overrideLocalyticsValues(String token) {
def xmlFile = "/path_to_file_saved_in_values/file.xml"
def locXml = new XmlParser().parse(xmlFile)
locXml.resources[0].each {
it.#ll_app_key = "ll_app_key"
it.value = "123456"
}
XmlNodePrinter nodePrinter = new XmlNodePrinter(new PrintWriter(new FileWriter(xmlFile)))
nodePrinter.preserveWhitespace = true
nodePrinter.print(locXml)
}
xml file :
<resources>
<string name="ll_app_key" translatable="false">MY_APP_KEY</string>
<string name="ll_gcm_sender_id" translatable="false">MY_GCM_SENDER_ID</string>
</resources>
In your code : Is it right ...? Where is node name and attribute ..?
locXml.resources[0].each { // Wrongly entered without node name
it.#ll_app_key = "ll_app_key" // Attribute name #name
it.value = "123456" // you can't change or load values here
}
You tried to read and write a same file. Try this code which replaces the exact node of the xml file. XmlSlurper provides this facility.
Updated :
import groovy.util.XmlSlurper
import groovy.xml.XmlUtil
def xmlFile = "test.xml"
def locXml = new XmlSlurper().parse(xmlFile)
locXml.'**'.findAll{ if (it.name() == 'string' && it.#name == "ll_app_key") it.replaceBody 12345 }
new File (xmlFile).text = XmlUtil.serialize(locXml)
Groovy has a better method for this than basic replacement like you're trying to do - the SimpleTemplateEngine
static void main(String[] args) {
def templateEngine = new SimpleTemplateEngine()
def template = '<someXml>${someValue}</someXml>'
def templateArgs = [someValue: "Hello world!"]
println templateEngine.createTemplate(template).make(templateArgs).toString()
}
Output:
<someXml>Hello world!</someXml>

How can I write the output using Groovy XmlNodePrinter?

How can I write the output of an object to a teststep (Soaprequest) in soapUI using XmlNodePrinter.
I have the below groovy script in which I have an input xml file. I perform file operations and then would like to write the object using xmlnodeprinter, to a teststep (soaprequest) in soapUI (highlighted in bold...not sure wat should be going in place of ---)
I tried writing to an external file which works (highlighted in green)
def alert = com.eviware.soapui.support.UISupport;
//Define a file pointer for groovy to handle the file operations.
def inputFile = new File("V:\\Sample\\Sample.xml")
if(!inputFile.exists())
{
//Display an alert if the file is not found.
alert.showInfoMessage("Input File 'Sample.xml' not found!");
}
else
{
xml=new XmlParser().parseText(inputFile.text)
def nodeToDel=xml.A.B.find{it.#C3='1'}
def parent = nodeToDel.parent()
parent.remove(nodeToDel)
//new XmlNodePrinter(new PrintWriter(new FileWriter(new File('V:\\Sample\\e.xml')))).print(parent)
new XmlNodePrinter(new PrintWriter(new FileWriter(---))).print(parent)
}
define a string writer
def sw = new StringWriter()
new XmlNodePrinter(new PrintWriter(sw)).print(parent)
def modifiedXml = sw.toString()
modifiedXml variable will contain the xml with deleted nodes which you can further use for your test step.

How to avoid outer-scope values messing with using the MarkupBuilder?

I need an element named file in my xml, however the gradle project have a property named file which is called instead. What is the best way around this?
import groovy.xml.MarkupBuilder
task test {
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.elem1(test: 'fest') {
elem2(a: 'b')
file(c: 'd')
elem4(e: 'f')
}
println(writer)
}
You should be able to do:
xml.file( c: 'd' )
You should be able to use the 'delegate' variable, which is automatically made available within each XML element's code block.
For example:
import groovy.xml.MarkupBuilder
task test {
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.elem1(test: 'fest') {
elem2(a: 'b')
delegate.file(c: 'd')
elem4(e: 'f')
}
println(writer)
}

Resources