Importing in XML from a file while using MarkupBuilder - groovy

I want to include data retrieved from an XMLParser and build a new file using the MarkupBuilder. I'm having trouble figuring out how this would work.
If I'm taking the wrong approach here, such as not using MarkupBuilder and using something else, let me know. Thanks!
C:/file.xml:
<externalData>
<data><nestedData><soOnAndSoForth/></nestedData></data>
</externalData>
Code.groovy:
def writer = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(writer).'root'("id":"foo") {
File content = new File("C:/file.xml")
def externalFile = new XmlParser(false,true,true).parse(content)
// may or may not modify this external data...
externalFile.each { elem -> ${elem} }
'moreData'('id':'myData')
}
println writer.toString()
Expected result:
<root id="foo">
<externalData>
<data><nestedData><soOnAndSoForth/></nestedData></data>
</externalData>
<moreData id="myData">
</root>
What I get:
<root id="foo">
<$ />
<moreData id="myData">
</root>

Related

Groovy question to read xml and base64decode

I want to modify the incoming message (As shown in the Modified XML) output.
Incoming XML
<xml>
<Body>
<Request>
<Container>
<name>test</name>
<Numbers>
<sn>//base64encodedstring//</sn>
<sn>//base64encodedstring//</sn>
<sn>//base64encodedstring//</sn>
</Numbers>
</Container>
</Request>
</Body>
</xml>
Modified XML
<xml>
<Body>
<Request>
<Container>
<name>test</name>
<Numbers>
<sn>//Decodedstring//</sn>
<sn>//Decodedstring//</sn>
<sn>//Decodedstring//</sn>
</Numbers>
</Container>
</Request>
</Body>
</xml>
As per the answer received: I can create an array of ListOfResults.
def listOfResults = new XmlSlurper()
.parseText(xml)
.Body.Request.Container.Numbers.sn
.collect { new String(it.text().decodeBase64()) }
I can do the following
def data = "<xml><Body><Request><Container><name>test</name><Numbers>"
for (i= 0; i <listOfResults.size(); i++)
{
data = data +"<sn>" +listOfResults[i] + "</sn>";
}
data = data + "<Numbers></Container></Request></Body></xml>";
Modified data
<xml><Body><Request><Container><name>test</name>
<Numbers>
<sn>decoded string</sn>
<sn>decoded string</sn>
<sn>decoded string</sn>
</Numbers> </Container></Request></Body></xml>
Is this the fastest way to do this operation? Is there any other better way?
You should be able to do (assuming your XML is in a string variable called xml):
def listOfResults = new XmlSlurper()
.parseText(xml)
.Body.Request.Container.Numbers.sn
.collect { new String(it.text().decodeBase64()) }

Building xml and merging CDATA xml using groovy

I have mule flow which stores the xml in session variable. I want this xml to be inserted in the xml which is generated in groovy.
My session variable looks like #[sessionVars.shippingdetails]
This session variable has <a><Subject1>science</Subject1><Subject2>Maths</Subject2></a>
When i use session variable in my xmlmarkup builder as like below. I am getting error as groovy.lang.GroovyRuntimeException: Namespace prefix: CDATA is not bound to a URI (javax.script.ScriptException). Message payload is of type: CaseInsensitiveHashMap (org.mule.api.transformer.TransformerMessagingException). Message payload is of type: CaseInsensitiveHashMap
import groovy.xml.XmlUtil
def builder = new groovy.xml.StreamingMarkupBuilder()
builder.encoding = "UTF-8"
// MAPPING
def person = {
// use mkp object which provides features like setting the namespace
mkp.xmlDeclaration()
mkp.declareNamespace("":"urn:abc:alos:BaseComponents")
//start with the XML root node closure
ItemRequest {
Requester{
subject(message.payload.subject)
}
Item{
Title(message.payload.name)
Description(message.payload.desc)
Category {
CategoryID(message.payload.cat_id)
}
ConditionID (message.payload.condition)
Mark (message.payload.Mark)
ShippingDetails [CDATA[sessionVars.shippingdetails]]
}
}
}
// WRITING
def writer = new StringWriter()
writer << builder.bind(person)
println writer.toString()
XmlUtil.serialize(builder.bind(person))
Hence my output xml should like below.
<?xml version="1.0" encoding="UTF-8"?>
<ItemRequest xmlns="urn:abc:alos:BaseComponents">
<Requester>
<subject>something</subject>
</Requester>
<Item>
<Title>Cooler Can Blue</Title>
<Description>This is the place for description.</Description>
<Category>
<CategoryID>562</CategoryID>
</Category>
<ConditionID>25</ConditionID>
<Mark>3</Mark>
<ShippingDetails>
<a>
<Subject1>science</Subject1>
<Subject2>Maths</Subject2>
</a>
</ShippingDetails>
</Item>
</ItemRequest>
Using Groovy 2.4.3, here is one way to get the output specified. (This does not address Mule):
import groovy.xml.*
def markupBuilder = new StreamingMarkupBuilder()
def xml = markupBuilder.bind { builder ->
mkp.declareNamespace( "": "urn:abc:alos:BaseComponents" )
ItemRequest {
Requester {
subject("something")
}
Item {
Title("Cooler Can Blue")
Description("This is the place for description.")
Category {
CategoryID("562")
}
ConditionID("25")
Mark("3")
ShippingDetails {
a {
Subject1("science")
Subject2("Maths")
}
}
}
}
}
def goal = """<?xml version="1.0" encoding="UTF-8"?><ItemRequest xmlns="urn:abc:alos:BaseComponents">
<Requester>
<subject>something</subject>
</Requester>
<Item>
<Title>Cooler Can Blue</Title>
<Description>This is the place for description.</Description>
<Category>
<CategoryID>562</CategoryID>
</Category>
<ConditionID>25</ConditionID>
<Mark>3</Mark>
<ShippingDetails>
<a>
<Subject1>science</Subject1>
<Subject2>Maths</Subject2>
</a>
</ShippingDetails>
</Item>
</ItemRequest>
"""
assert goal == XmlUtil.serialize(xml)

Merging Checkstyle XML Documents with identical structure using groovy

Good Morning
I have several Checkstyle XML reports with identical structure that I need to merge into a single document, the document looks as follows.
<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="6.15">
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/communication/EMailMessage.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/communication/EMailSender.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/communication/SMSMessage.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/communication/package-info.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/ussd/InputValidation.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/ussd/InputValidationALL.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/ussd/InputValidationINTEGER.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/ussd/InputValidationTEXT.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/ussd/MenuNavigationEvent.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/ussd/SubscriberForUSSD.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/ussd/USSDMenuItem.java">
<error line="327" severity="error" message="Line is longer than 120 characters (found 157)." source="com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck"/>
<error line="327" column="133" severity="error" message="&apos;,&apos; is not followed by whitespace." source="com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAfterCheck"/>
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/ussd/USSDMenuItemManager.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/ussd/USSDResponse.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/ussd/package-info.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/utils/DateUtils.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/utils/DbUtils.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/utils/Enumerators.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/utils/IDNumberValidator.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/utils/SimpleHTTP.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/utils/TextParser.java">
</file>
<file name="/media/sf_Google_Drive/Development/av_microservice/av_microservice/av_microservice_commons/src/main/java/za/co/av/ms_commons/utils/package-info.java">
</file>
</checkstyle>
now I have tried to merge using the following code
def list = []
//create new XML file
File newXMLfile= new File("${rootProject.projectDir}/reports/checkStyleCombined.xml" )
new StreamingMarkupBuilder().bind {
mkp.xmlDeclaration([version:'1.0', encoding:'UTF-8', standalone:'no'])
checkstyle {
//get list of all checkstyle reports
def dir = new File("${rootProject.projectDir}/reports/checkstyle")
dir.eachFileRecurse (FileType.FILES) { file ->
list << file
}
//itterate though the list
list.each {
//parse xml file
def gPathResult = new XmlSlurper().parse(it)
//find all "file" nodes in xml file
gPathResult.file.each{
TEST(XmlUtil.serialize(it))
out << it
}
}
}
}.writeTo(newXMLfile.newWriter("UTF-8"))
The issue I have is twofold firstly it seems that I cant use the XmlUtil.serialize method to write my node because it puts a XML declaration on each line and the formatting looks like this.
<TEST><?xml version="1.0" encoding="UTF-8"?><file name="XXXXXX"/>
Secondly you will note in the XML file that there is an element called file. I cant use the name file in the closure because file is a reserved word so I use "TEST" but this is obviously wrong. So My question is simple does anyone know how to do this in a more simple fashion.
So it seems that the approach I was using was not ideal so what I have done is used one of the XML documents as a root document and merged the other documents into it as follows
def list = []
//This is for the checkstyle report!!!!!!
//create new XML file
File newXMLfile= new File("${rootProject.projectDir}/reports/checkStyleCombined.xml" )
//get list of all checkstyle reports
def dir = new File("${rootProject.projectDir}/reports/checkstyle")
dir.eachFileRecurse (FileType.FILES) { file ->
list << file
}
//set the root xml document to the first document is the list
def root = new XmlSlurper().parse(list.first())
//itterate through the list
list.each {
if(it != list.first())
{
//parse xml file
def gPathResult = new XmlSlurper().parse(it)
//find all file nodes in xml file
gPathResult.file.each{
//append node to root node
root.appendNode(it)
}
}
}
//write the node to file
newXMLfile.withWriter { outWriter ->
XmlUtil.serialize( new StreamingMarkupBuilder().bind{ mkp.yield root }, outWriter )
}
I hope this helps someone someday as it took me quite a while to figure it out.

Command writing to standard error does not produce output to ccnet project report?

I wrote a small c program like this:
#include<stdio.h>
#include<windows.h>
void main()
{
fputs("test\r\n", stderr);
fflush(stderr);
ExitProcess(-1);
}
and included it like this in ccnet.config:
<project name="foobar">
<tasks>
<exec>
<executable>C:\temp\test.exe</executable>
</exec>
</tasks>
</project>
When I forced the foobar project, I got not output whatsoever in the project report.
Why?
I may also mention that if I deliberately misspell the exe-filename, I get an exception (which I appreciate).
Edit:
When debugging CruiseControl.NET, writing a test that tries to run the exe file
that looks like this
[Test]
public void FooTest()
{
const string xml = "<exec executable=\"C:\\temp\\test.exe\"><buildArgs></buildArgs></exec>";
task = (ExecutableTask) NetReflector.Read(xml);
var result = (IntegrationResult) IntegrationResult();
result.Label = "1.0";
result.BuildCondition = BuildCondition.ForceBuild;
result.WorkingDirectory = #"c:\temp\";
result.ArtifactDirectory = #"c:\temp\";
task.Run(result);
Assert.AreEqual(IntegrationStatus.Failure, result.Status);
Assert.IsFalse(task.WasSuccessful);
var firstTaskResult = (ProcessTaskResult)result.TaskResults[0];
Debug.WriteLine(firstTaskResult.Data);
}
The debug console will output xml like this:
<buildresults>
<task>
<buildArgs />
<buildTimeoutSeconds>600</buildTimeoutSeconds>
<baseDirectory />
<dynamicValues />
<environment />
<executable>C:\temp\test.exe</executable>
<priority>Normal</priority>
<successExitCodes />
</task>
<message level="Error">test</message>
</buildresults>
(note, I did beautify this xml before adding it here).

Find GPath exists in given XML document using Groovy

In Groovy given a GPath I want to find that the path exists in XML document. So that I can set a value for the node. I can use xmlslurper for parsing the document. GPath is a string path represented in slashes format.
Look at example:
def xml = '''
<?xml version="1.0" encoding="UTF-8"?>
<data>
<level0 id="1" t="0">
<level1 id="lev1id01" att1="2015-05-12" val="12" status="0" year="2015" month="05" />
</level0>
</data>
'''
// find all nodes named 'level1'
def level1Nodes = new XmlSlurper().parseText(xml).level0.level1
// display found nodes names
level1Nodes.each { node ->
println "node: ${node.name()}"
}
// Get 'year' attribute value for 'level1' node
def level1YearValue = level1Nodes.each { node ->
println "${node.#year}"
}
Could you be more specific in your question?

Resources