Reputation: 2454
I am currently iterating through an XML file like this:
def root = new XmlSlurper().parseText(xml)
root.service.each { service ->
service.receiver.endpoint.each { endpoint ->
println "\t\tEndpoint: ${endpoint.text()}"
}
}
I want to first read the endpoint.text() , and afterwards modify the value of the node, so the file contains a new value. I am reading the node attributes fine, as it is. But how do I write to it afterwards?
I looked at this question, and understand how to write to an existing file. But what I am asking is, can it be done in a more elegant matter, when I am already iterating through the file to read some of it's content? I am hoping there is a more efficient way that suits the way I am iteraring through the file.
So am hoping there is a way to do something like this:
def root = new XmlSlurper().parseText(xml)
root.service.each { service ->
service.receiver.endpoint.each { endpoint ->
println "\t\tEndpoint: ${endpoint.text()}"
// ****WRITE TO NODE****
}
}
hope it makes sense.
Also, here is some example XML:
<project name='Common'>
<service name='name' pattern='something' isReliable='maybe'>
<receiver name='name' isUsingTwoWaySsl='maybe' isWsRmDisabled='maybe'
targetedByTransformation='maybe'>
<endpoint name='local_tst01'>URL</endpoint>
<endpoint name='local_tst02'>URL</endpoint>
<endpoint name='local_tst03'>URL</endpoint>
<environment name='dev' default='local_dev' />
<environment name='tst01' default='test' />
<environment name='tst02' default='local_tst02' />
</receiver>
<operation name='name'>
<sender>sender</sender>
<attribute name='operation' type='String'>name</attribute>
</operation>
</service>
</project>
Upvotes: 3
Views: 8353
Reputation: 21389
Here is the little variant to update the endpoints.
This is flexible so that you can choose what endpoint will need to have the new url as per the name attribute
as defined in the below endpointBinding
map. Of course, you can change the values as needed.
//Set your endpoint name attribute value and new endpoint url in a map
//This would be flexible to have the respective url
def endpointBinding = ['local_tst01': 'http://example01.com', 'local_tst02': 'http://example02.com', 'local_tst03': 'http://example03.com']
pXml = new XmlSlurper().parseText(xml)
//Update the values in xml as per the binding defined above
endpointBinding.collect { k, v -> pXml.'**'.find{it.name() == 'endpoint' && it.@name == k }.replaceBody(v) }
println groovy.xml.XmlUtil.serialize( pXml )
You can quickly try the same online Demo
Upvotes: 2
Reputation: 28634
don't know why replaceBody
method is protected but it works:
def root = new XmlSlurper().parseText(
'''<root>
<service>
<receiver>
<endpoint>123</endpoint>
<endpoint>456</endpoint>
</receiver>
</service>
</root>''')
root.service.each { service ->
service.receiver.endpoint.each { endpoint ->
endpoint.replaceBody("**"+endpoint.text())
}
}
println groovy.xml.XmlUtil.serialize( root )
Upvotes: 4