groovy

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

Details

  • Type: Improvement Improvement
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Fixed
  • Affects Version/s: None
  • Fix Version/s: 1.1-beta-2
  • Component/s: XML Processing
  • Labels:
    None
  • Number of attachments :
    0

Description

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 }

Activity

Hide
Frank Kaiser added a comment -

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});
}
}
}
};
}

Show
Frank Kaiser added a comment - 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}); } } } }; }
Hide
blackdrag blackdrag added a comment -

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.

Show
blackdrag blackdrag added a comment - 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.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: