Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-9664

Groovy 3.0 does not work with Groovy 2 code using groovy.xml.XmlUtil



    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 3.0.5
    • 3.0.6
    • XML Processing
    • None


      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">

      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?




            paulk Paul King
            zman0900 Dan Ziemba
            0 Vote for this issue
            2 Start watching this issue