Christopher Klewes
Christopher Klewes

Reputation: 11435

Howto update XML with groovy's XML Slurper?

I read the Groovy Codehaus article about Updating XML with XmlSlurper, this leads me to the following question. Consider we have a input XML structured as the upcoming:

<customer>
  <address>
    <street />
    <city />
    <postalcode />
  </address>
</customer>

Is it possible to change the XML without knowing its concrete structure? Concrete: We have a reference to the address Node and want to multiply it 3 times without knowing any details?

address.multiply(3)

The output should look like this:

<customer>
  <address>
    <street />
    <city />
    <postalcode />
  </address>
  <address>
    <street />
    <city />
    <postalcode />
  </address>
  <address>
    <street />
    <city />
    <postalcode />
  </address>
</customer>

This could be possible with appendNode but I'm missing a clone method for nodes in groovy. Is there any solution to achieve this?

Upvotes: 4

Views: 8125

Answers (2)

Pierluigi Vernetto
Pierluigi Vernetto

Reputation: 2050

GPathResult.replaceBody() works for me. Example:

http://www.javamonamour.org/2011/11/groovy-modifying-xml-with-xmlslurper.html

Upvotes: 1

tim_yates
tim_yates

Reputation: 171054

The only way I can think of currently for cloning nodes is to serialize them to text, and parse them back in as new bits of xml

Like so:

import groovy.xml.StreamingMarkupBuilder
import groovy.xml.XmlUtil

def xml = """
<customer>
  <address>
    <street />
    <city />
    <postalcode />
  </address>
</customer>
"""

def root = new XmlSlurper().parseText( xml )
2.times {
  String addressXml = new StreamingMarkupBuilder().bindNode( root.address )
  clonedAddress = new XmlSlurper().parseText( addressXml )
  root.appendNode( clonedAddress )
}

println XmlUtil.serialize( root )

Which prints out:

<?xml version="1.0" encoding="UTF-8"?>
<customer>
  <address>
    <street/>
    <city/>
    <postalcode/>
  </address>
  <address>
    <street/>
    <city/>
    <postalcode/>
  </address>
  <address>
    <street/>
    <city/>
    <postalcode/>
  </address>
</customer>

There's probably a neater way of doing this...but at the moment, my mind is a blank...

Upvotes: 9

Related Questions