Groovy Nested (Recursive?) XML - groovy

Given a list of objects that contains an ID and an ELEMENT, I need to iterate over the list and produce XML that looks like this:
<object id="1">
<element>...</element>
<object id="2">
<element>...</element>
<object id="3">
<element>...</element>
</object>
</object>
</object>
Note each object is created WITHIN the previous object, and objects are only closed off at the end of the list. (Not my choice, dictated by an external interface)
Is there a way to produce this using the XML Markup Builder?

class MyElement {
def id
def element
}
def list = [new MyElement(id: 1, element: "element1"),
new MyElement(id: 2, element: "element2"),
new MyElement(id: 3, element: "element3")]
println new groovy.xml.StreamingMarkupBuilder().bind {
def foo // note declaration and initialization on different lines
foo = { List<MyElement> l ->
if (l.isEmpty()) return
def head = l.head()
def tail = l.tail()
object {
id head.id
element head.element
foo(tail)
}
}
foo(list)
}
Output (prettified):
<object>
<id>1</id>
<element>element1</element>
<object>
<id>2</id>
<element>element2</element>
<object>
<id>3</id>
<element>element3</element>
</object>
</object>
</object>`

Related

How do you add attribute to array element with xml2js?

I'm trying to figure out how to add attributes to an array element
I get an error Error: Invalid character in name when trying to build the following XML from an object.
<?xml version="1.0" encoding="UTF-8"?>
<Requests xmlns="http://example.com">
<Request>
</Request>
<Request>
</Request>
</Requests>
Here is my object
let myObject = {
Requests:[
{$:{xmlns:"http://example.com"}},
{Request:{}},
{Request:{}}
]
}
let builder = new xml2js.Builder();
let xml = builder.buildObject(myObject);
console.log(xml)
I've also tried wrapping the name in quotes
{"$":{"xmlns":"http://example.com"}},
Stripping out the attribute declaration altogether produces the desired XML but obviously leaves out the needed attribute
<?xml version="1.0" encoding="UTF-8"?>
<Requests>
<Request>
</Request>
<Request>
</Request>
</Requests>
I suppose you should try this:
let myObject = {
Requests:{
$:{xmlns:"http://example.com"},
Request:[{}, {}]
}

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()) }

can't access module elements using geb groovy

I have a page, that is made of frames. I want to access elements of the frame and manipulate them. I want to use module to implement my changes. This is how my code looks like.
<html>
<body>
<frame name="header" ></frame>
<frame name="center" >
<input name='quantity' type='text'>
<input name='ok' type='radio' value='ok'>
</frame>
<frame name="footer" ></frame>
Then I have the groovy page classes like this
class myMainPage extends Page {
static content = {
myModule{module FrameModule}
}
}
class FrameModule extends Module {
def FrameElement
static content = {
Myframe { $('frame', name:'center') }
FrameElement {Myframe.find('input[name="quantity"]')}
myQuantity = FrameElement.module(TextInput)
myQuantity.text = '10'
}
}
I tested this like this
Then:
to myMainPage
and:
myModule.myQuantity
with setup of the module I get
no such property TextInput for class: FrameModule
How do I manipulate those frame's element
It looks like you need to import
import geb.module.TextInput
unless you did do that and just didn't include it in your post.
Actually, looking more closely, you should eliminate your FrameElement, and instead declare myQuantity like below. This will eliminate some fluff and simplify it into one line that finds the element and instantiates it as a TextInput module.
myQuantity = {$("input", name: "quantity").module(TextInput)}
Than you should be able to do myModule.myQuantity like you are currently doing.

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)

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