Unexpected results with groovy.util.slurpersupport.NodeChild.appendNode() (Groovy 2.2.1)

1.9k Views Asked by At

I think what I am trying to do is simple: Add child nodes dynamically to a node (without even knowing the name of the node to be added - developing some framework) using XmlSlurper.

For ease of explaining, something like this:

def colorsNode = new XmlSlurper().parseText("""
    <colors>
        <color>red</color>
        <color>green</color>
    </colors>""") 

NodeChild blueNode = new XmlSlurper().parseText("<color>blue</color>")  // just for  illustration. The actual contents are all dynamic

colorsNode.appendNode(blueNode) // In real life, I need to be be able to take in any node and append to a given node as child.

I was expecting the resulting node to be the same as slurping the following:

“””
<colors>
    <color>red</color>
    <color>green</color> 
    <color>blue</color>
</colors>"""

However the result of appending is:

colorsNode
    .node
        .children => LinkedList[Node('red') ->   Node('green')   ->   <b>NodeChild</b>(.node='blue')]

In other words, what gets appended to the LinkedList is the NodeChild that wraps the new node, not the node itself.

Not surprising, looking at the source code for NodeChild.java:

protected void appendNode(final Object newValue) { 
    this.node.appendNode(newValue, this);
}

Well, I would gladly modify my code into:

colorsNode.appendNode(blueNode<b>.node</b>)

Unfortunately NodeChild.node is private :(, don't know why! What would be a decent way of achieving what I am trying? I couldn’t see any solutions online.

I was able to complete my prototyping work by tweaking Groovy source and exposing NodeChild.node, but now need to find a proper solution.

Any help would be appreciated.

Thanks, Aby Mathew

1

There are 1 best solutions below

2
On

It would be easier if you use XmlParser:

@Grab('xmlunit:xmlunit:1.1')
import org.custommonkey.xmlunit.Diff
import org.custommonkey.xmlunit.XMLUnit

def xml = """
    <colors>
        <color>red</color>
        <color>green</color>
    </colors>
"""

def expectedResult = """
    <colors>
        <color>red</color>
        <color>green</color>
        <color>blue</color>
    </colors>
"""

def root = new XmlParser().parseText(xml)
root.appendNode("color", "blue")

def writer = new StringWriter()
new XmlNodePrinter(new PrintWriter(writer)).print(root)
def result = writer.toString()

XMLUnit.setIgnoreWhitespace(true)
def xmlDiff = new Diff(result, expectedResult)
assert xmlDiff.identical()