Groovy XMLSlurper Parse Values - groovy

I am so close to getting my code completed. I would like to get only the values in an array. Right now I am getting XML declaration plus the line.
Here's my code:
import groovy.xml.XmlUtil
def serverList = new
XmlSlurper().parse("/app/jenkins/jobs/firstsos_servers.xml")
def output = []
serverList.Server.find { it.#name == SERVER}.CleanUp.GZIP.File.each{
output.add(XmlUtil.serialize(it))
}
return output
Here is my XML File:
<ServerList>
<Server name="testserver1">
<CleanUp>
<GZIP>
<File KeepDays="30">log1</File>
<File KeepDays="30">log1.2</File>
</GZIP>
</CleanUp>
</Server>
<Server name="testserver2">
<CleanUp>
<GZIP>
<File KeepDays="30">log2</File>
</GZIP>
</CleanUp>
</Server>
<Server name="testserver3">
<CleanUp>
<GZIP>
<File KeepDays="30">log3</File>
</GZIP>
</CleanUp>
</Server>
When I select testserver1 my output should be:
['log1','log1.2']
What I am getting is this:
<?xml version="1.0" encoding="UTF-8"?><File KeepDays="30">log1</File>
<?xml version="1.0" encoding="UTF-8"?><File KeepDays="30">log2</File>

You need not require to use XmlUtil.serialize()
Here is what you need and following inline comments.
//Define which server you need
def SERVER = 'testserver1'
//Pass the
def serverList = new
XmlSlurper().parse("/app/jenkins/jobs/firstsos_servers.xml")
//Get the filtered file names
def output = serverList.Server.findAll{it.#name == SERVER}.'**'.findAll{it.name() == 'File'}*.text()
println output
return output
Output:
You can quickly try online Demo

def output = []
def node = serverList.Server.find {
it.'name' = 'testserver1'
}.CleanUp.GZIP.File.each {
output.add(it)
}
return output
also there is a copy & paste error in your .xml. You have to add </ServerList> at the end.
`

Related

Groovy split results

Script:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.xml.XmlUtil;
import groovy.xml.StreamingMarkupBuilder;
import groovy.xml.*;
def Message processData(Message message) {
// get body
def body = message.getBody(java.io.Reader);
// parse xml body
def result = new XmlSlurper().parse(body);
def message1 = result.Message1;
def message2 = result.Message2;
def one = message1.EmployeeDataReplicationConfirmation.EmployeeDataReplicationConfirmation.collect { it.personId.text() }
def two = message2.queryCompoundEmployeeResponse.CompoundEmployee.collect { it.person.person_id.text() }
def intersect = one.intersect(two)
def userid1 = ((one - intersect) + (two - intersect))
println((one - intersect) + (two - intersect))
return message;
Output:
Console Output
Running...
[6107, 10140, 11774]
In the text 1 and text2 fields are different ids. This command will give me IDs that are the same in both.
But he gives them to me like this:[6107, 10140, 11774]
But i need it in XML.. like ..
I need this
<Person>
<User>
<userid>6107</userid>
</User>
<User>
<userid>10140</userid>
</User>
<User>
<userid>11774</userid>
</User>
how can i do it ? Thanks :)
You can use the MarkupBuilder class to create your XML, imagine you already have your data ready, then the only thing you need to do is:
import groovy.xml.MarkupBuilder
def userIds = [6107, 10140, 11774]
def xml = new StringWriter()
def builder = new MarkupBuilder(xml)
builder.people() {
userIds.each { id ->
user() {
userId(id)
}
}
}
println xml
This will be the output
<people>
<user>
<userId>6107</userId>
</user>
<user>
<userId>10140</userId>
</user>
<user>
<userId>11774</userId>
</user>
</people>
For more examples of working with XML, you can see my gist Working with xml

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>

Groovy Script with XmlSlurper

I have an XML file that I am trying to parse through with Groovy.
<?xml version = '1.0' encoding = 'UTF-8'?>
<ServerList>
<Server>server1.me.com</Server>
<CleanUpTest>TESTING</CleanUpTest>
<Server>server2.me.com</Server>
</ServerList>
This code works and gives me the output Result: [server1.me.com]:
def serverList = new XmlSlurper().parse("E:\\Program Files(x86)\\Jenkins\\jobs\\first_servers.xml")
def output = []
serverList.Server.find { it == 'server1.me.com' }.each{
output.add(it)
}
return output
But when I try to get the value in CleanUpTest it is not working.
def serverList = new XmlSlurper().parse("E:\\Program Files(x86)\\Jenkins\\jobs\\first_servers.xml")
def output = []
serverList.Server.find { it == 'server1.me.com' }.CleanUpTest.each{
output.add(it)
}
return output
What do I have wrong? I am expecting Result: [TESTING]

groovy xml namespace definition used in attribute value lost after XmlParse/serialize

When using XmlParser, it automatically strips out unused namespace definitions. It doesn't appear to detect a namespace being used in a value.
Example Code: The value for attribute "type" is "xs:string" which requires the namespace definition, but XmlParser strips it out
import groovy.xml.XmlUtil
def xml = '''<?xml version="1.0" encoding="UTF-8"?>
<value xmlns:xs="http://xs" type="xs:string">http://localhost:8001/MyService</value>
'''
def doc = new XmlParser().parseText(xml)
println(xml)
println(XmlUtil.serialize(doc))
Output:
****ORIGINAL****
<?xml version="1.0" encoding="UTF-8"?>
<value xmlns:xs="http://xs" type="xs:string">http://localhost:8001/MyService</value>
****XML PARSED/SERIALIZED*****
<?xml version="1.0" encoding="UTF-8"?>
<value type="xs:string">http://localhost:8001/MyService</value>
Is there any way to tell XmlParser to keep this namespace definition??
def parser = new XmlParser()
parser.setFeature("http://xml.org/sax/features/namespaces", false)
parser.setFeature("http://xml.org/sax/features/namespace-prefixes", true)
doc = parser.parseText(xml)
println(XmlUtil.serialize(doc))

Xml goes blank, when updated with Groovy XmlParser

I am quite new to groovy and seek your help.
I want to read an delta xml file and update master xml file based on a name attribute. Both the xml files are of same structure. I am trying to update attribute values in the master xml file. But the master file goes blank once, the file is updated. I am not sure where I am wrong.
Below is the xml structure:
<item-descriptor name="user" cache-mode="simple" item-cache-size="3000" query-cache-size="1000" item-cache-timeout="900000" query-expire-timeout="60000" />
<item-descriptor name="contactInfo" cache-mode="simple" item-cache-size="10000" query-cache-size="1000" item-cache-timeout="900000" query-expire-timeout="60000" />
Below is the code for this:
def templatexmlConfig = new XmlParser().parse(templateConfigFile)
def basexmlConfig = new XmlSlurper().parse(baseConfigFile)
def templateItemDesNode = templatexmlConfig.'item-descriptor'
def baseItemDesNode=basexmlConfig.'item-descriptor'
templateItemDesNode.each()
{
Map bindings=[:]
def nameAttr=it.attribute('name')
it.attributes().each{attrName,attrValue->
if(!attrName.equals('name'))
{
bindings.put(attrName,attrValue)
}}
if(baseItemDesNode.find{ it.#name.text().equals(nameAttr)}.size()!=0)
{
bindings.each
{
def a=it.key
def v=it.value
baseItemDesNode.find{ it.#name.text().equals(nameAttr)}.#'a'="${v}" }
}
}
new XmlNodePrinter(new PrintWriter(outputFile)).print(basexmlConfig)
Ok, given two example xml documents:
def templateXml = '''<xml>
| <item-descriptor name="a" cache-mode="r1" item-cache-size="1"/>
| <item-descriptor name="b" cache-mode="r2" item-cache-size="2" new-attr="tim"/>
| <item-descriptor name="z" cache-mode="r3" item-cache-size="3"/>
|</xml>'''.stripMargin() ;
def baseXml = '''<xml>
| <item-descriptor name="b" cache-mode="o1" item-cache-size="10"/>
| <item-descriptor name="c" cache-mode="o2" item-cache-size="11"/>
| <item-descriptor name="a" cache-mode="o3" item-cache-size="12"/>
|</xml>'''.stripMargin()
We can parse these (Using XmlParser for both, you had parser for one, and slurper for the other):
def templatexmlConfig = new XmlParser().parseText( templateXml )
def basexmlConfig = new XmlParser().parseText( baseXml )
And then get the item-descriptor nodes (as you had it)
def templateItemDesNode = templatexmlConfig.'item-descriptor'
def baseItemDesNode = basexmlConfig.'item-descriptor'
Then, loop through the template item-descriptors, generate a map of non-name attributes (using findAll is easier than the loop you had), and replace all nodes on the node in baseXml with the same name:
templateItemDesNode.each() { tidn ->
Map bindings = tidn.attributes().findAll { it.key != 'name' }
def nameAttr = tidn.#name
baseItemDesNode.find { b -> b.#name == nameAttr }?.with { node ->
bindings.each { a, v ->
node.#"$a" = v
}
}
}
And for this easily runnable example, just print out the Xml:
println new StringWriter().with { sw ->
new XmlNodePrinter( new PrintWriter( sw ) ).print(basexmlConfig)
sw.toString()
}
And when run, the above prints out:
<xml>
<item-descriptor name="b" cache-mode="r2" item-cache-size="2" new-attr="tim"/>
<item-descriptor name="c" cache-mode="o2" item-cache-size="11"/>
<item-descriptor name="a" cache-mode="r1" item-cache-size="1"/>
</xml>
Obviously for your working code, you would need to go back to using parse on the XmlParsers to parse your files rather than the Strings I have here, and change the output back to writing to a file...
Hope it helps!

Resources