Issue Details (XML | Word | Printable)

Key: GROOVY-1955
Type: Improvement Improvement
Status: Closed Closed
Resolution: Fixed
Priority: Minor Minor
Assignee: Jochen Theodorou
Reporter: Frank Kaiser
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
groovy

Adding complete body of XML tag with GPathResult.getBody() including CDATA sections

Created: 27/Jun/07 04:42 PM   Updated: 01/Jul/07 12:03 PM
Component/s: XML Processing
Affects Version/s: None
Fix Version/s: 1.1-beta-2

Time Tracking:
Not Specified


 Description  « Hide
Closes a gap in GPathResult methods by providing a new "getBody()" method.
The method extracts the complete body of an XML tag into a closure wich can
then be inserted at another location in the XML builder.

The example below demonstrates how to use the getBody() method.
In this example the <sec> tag is replaced by a <t> tag.
Then the body of the <sec> tag is inserted into the <t> tag.

The expected result is: <doc><t>Hello<p>World</p></t></doc>

Existing methods of GPathResult ignore CDATA. In the example below
the "Hello" would be ignored.

def xmlOut = new StreamingMarkupBuilder()
def xmlInStr ="""
<doc><sec>Hello<p>World</p></sec></doc>
"""

GPathResult xmlIn = new XmlSlurper().parseText(xmlInStr)

xmlIn.sec.replaceNode{ node ->
t(){ delegate.mkp.yield node.getBody() }
}

println xmlOut.bind{ mkp.yield xmlIn }



 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Frank Kaiser added a comment - 28/Jun/07 05:16 AM
Below is the patch for GPathResult which resolves this issue.

Regards:

Frank

========================================================================

public Closure getBody() {
return new Closure(this.parent(),this) {
public void doCall(Object[] args) {
final GroovyObject delegate = (GroovyObject)getDelegate();
final GPathResult thisObject = (GPathResult)getThisObject();

Node node = (Node)thisObject.getAt(0);
List children = node.children();

for(int i=0; i<children.size(); i++){
Object child = children.get;
delegate.getProperty("mkp");
if(child instanceof Node){
delegate.invokeMethod("yield", new Object[]{new NodeChild((Node)child, thisObject,"*",null)});
}
else{
delegate.invokeMethod("yield", new Object[]{child});
}
}
}
};
}


Jochen Theodorou added a comment - 01/Jul/07 12:03 PM
implemented... while testing this out I found a strange thing that required me to make additional changes using this patch. The usage of NodeIterator leaded to a NPE, because we tried to access a field that was not yet initialized. I am talking here about the this$ instance used in inner classes to access the surrounding class. this$ was initialized only after the constructor was ready, but since the class uses getNextNode in the constructor and this method makes use of this$ I got a NPE. I fixed that problem... with a delayed initialization. I hope I didn't change the semantics.