Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
3.0.5
-
None
Description
I am trying to upgrade a project from Groovy 2.5.12 to 3.0.5, but am running into trouble with an unmaintained library that is built against Groovy 2.4.1. Part of what this library does includes using XmlSlurper to parse an XML string, then using XmlUtil to serialize one of the nodes back to an XML string.
This is the simplified example that reproduces the problem:
import groovy.util.slurpersupport.NodeChild import groovy.util.XmlSlurper import groovy.xml.XmlUtil String xml = '<xml xmlns="http://example.com/ns"><abc><xyz>true</xyz></abc></xml>' String name = "abc" // Note NodeChild and XmlSlurper are both deprecated in Groovy 3 NodeChild parsed = new XmlSlurper().parseText(xml) def node = parsed."$name" // Just to show type of 'node' println "Node class: ${node.getClass()}" println "Node super class: ${node.getClass().getSuperclass()}" // Error happens here println "Result: ${XmlUtil.serialize(node)}"
This is the expected output when running with Groovy 2.5.12:
Node class: class groovy.util.slurpersupport.NodeChildren Node super class: class groovy.util.slurpersupport.GPathResult Result: <?xml version="1.0" encoding="UTF-8"?> <tag0:abc xmlns:tag0="http://example.com/ns"> <tag0:xyz>true</tag0:xyz> </tag0:abc>
The same code fails when running with Groovy 3.0.5:
Node class: class groovy.util.slurpersupport.NodeChildren Node super class: class groovy.util.slurpersupport.GPathResult Error on line 1 column 1 SXXP0003 Error reported by XML parser: Content is not allowed in prolog. groovy.lang.GroovyRuntimeException: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog. at groovy.xml.XmlUtil.serialize(XmlUtil.java:458) at groovy.xml.XmlUtil.serialize(XmlUtil.java:444) at groovy.xml.XmlUtil.serialize(XmlUtil.java:191) at groovy.xml.XmlUtil.serialize(XmlUtil.java:160) at groovy.xml.XmlUtil$serialize.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139) at ideaGroovyConsole.run(ideaGroovyConsole.groovy:17)
The problem relates to GROOVY-4285. The method groovy.xml.XmlUtil#asString(groovy.lang.Writable) has changed its instanceof check to check for groovy.xml.slurpersupport.GPathResult, but the now-deprecated XmlSlurper still returns a sub-class of groovy.util.slurpersupport.GPathResult. So the check fails, leading to the same problem described in the old issue GROOVY-4285.
I see that there is now a deprecated "groovy.util.XmlUtil" class, and the code works if changed to that, but that class did not exist before Groovy 3. I think "groovy.xml.XmlUtil" should be fixed so that code using the deprecated APIs is still able to run unchanged as long as those deprecated API continue to exist. Perhaps groovy.xml.XmlUtil could be changed to check for the old version of GPathResult and call groovy.util.XmlUtil as appropriate?