0

I have an issue where I'm trying to dynamically create nested xml nodes in groovy. When I say dynamic, I mean using a StringTokenizer, so passing in a string "a.b", would give be a node like this:

<a>
  <b></b>
</a>

I already have the following code that can create a node with values and attributes (using a MarkupBuilder and StringWriter)

"${node.node_name}"(node.attributes, node.value);

If I were to replace this with

a{b()}

That would give be a nested node, but I need to create the node dynamically. I'm guessing that I'd use a StringTokenizer and do something like this

while(tokenizer.hasMoreElements()) {
    final String nodeName = tokenizer.nextToken();
     if(tokenizer.hasMoreElements()) {
         // create child node
     } else {
         // add value and attribute to final nested node
         "${nodeName}"(node.attributes, node.value);
     }
}

Thanks for any help.

1 Answer 1

1

You could do this with inject to build up a chain of Closures which when run generates the xml:

import groovy.xml.MarkupBuilder

def property = 'a.b.c.d.e.f'
def leafProperties = [id:10, something:'else']

def writer = new StringWriter()
new MarkupBuilder(writer).with { xml ->
    property.split(/\./).reverse().inject(null) { c, p ->
        c ? { x -> xml."$p"(c) } : { x -> xml."$p"(leafProperties) }
    }()
}

println writer.toString()
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, that does successfully create a nested node. How would I go about adding attributes/values to the final node (most nested)? I tried adding them to a few places but kept getting errors.
Updated answer...is that what you mean?
I tried that and I got a MissingMethodException:No signature of method: java.lang.String.call() is applicable for argument types: (java.util.LinkedHashMap, java.lang.String) values: [[:], 012] . Here I've passed in an empty map for the attributes, and a string for the value.
Apoligies, I misread the update. That's all working now, thank you very much.
No worries! Have fun!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.