groovy
  1. groovy
  2. GROOVY-4285

XmlUtil.serialize doesn't seem to pick right method for GPathResult

    Details

    • Number of attachments :
      0

      Description

      The following gives an error:

      import groovy.xml.XmlUtil
      import groovy.xml.StreamingMarkupBuilder
      
      def xmlStr = """<?xml version="1.0" encoding="UTF-8"?>
      <stuff ver="1.0">
        <properties>
          <foo>bar</foo>
        </properties>
      </stuff>"""
      
      def gpr = new XmlSlurper().parseText( xmlStr )
      println XmlUtil.serialize( gpr )
      

      Gives the following error:

      [Fatal Error] :1:1: Content is not allowed in prolog.
      ERROR:  'Content is not allowed in prolog.'
      <?xml version="1.0" encoding="UTF-8"?>
      

      However if we change the println to:

      println XmlUtil.serialize( (groovy.util.slurpersupport.GPathResult)gpr )
      

      We get the correct output:

      <?xml version="1.0" encoding="UTF-8"?>
      <stuff ver="1.0">
        <properties>
          <foo>bar</foo>
        </properties>
      </stuff>
      

      Looks like Groovy is picking the wrong method somewhere... (though I can't see how)

        Activity

        Hide
        Roshan Dawrani added a comment -

        The issue is that groovy.util.slurpersupport.Node#writeTo(Writable) does not generate the String form of the nodes correctly.

        Where it should generate

        <stuff ver='1.0'><properties><foo>bar</foo></properties></stuff>
        

        it generates

        bar
        

        And then with the xml string going simply as "bar", it throws the "Content is not allowed in prolog." error correctly.

        Show
        Roshan Dawrani added a comment - The issue is that groovy.util.slurpersupport.Node#writeTo(Writable) does not generate the String form of the nodes correctly. Where it should generate <stuff ver='1.0'><properties><foo>bar</foo></properties></stuff> it generates bar And then with the xml string going simply as "bar", it throws the "Content is not allowed in prolog." error correctly.
        Hide
        Roshan Dawrani added a comment - - edited

        Apart from the issue highlighted in the previous comment, there also seems to be some method selection bug in here.

        Here are 2 snippets that highlight the difference in method selections made by groovy:
        1)

        interface I {}
        
        class C implements I {}
        
        class Methods {
            def foo(I i) {
                println "foo(Interface) called"
            }
            def foo(C i) {
                println "foo(Class) called"
            }
        } 
        
        new Methods().foo(new C())
        

        results in

        foo(Class) called
        

        2) But if I have a slight variant

        interface I {}
        
        class P implements I {}
        class C extends P {}
        
        class Methods {
            def foo(I i) {
                println "foo(Interface) called"
            }
            def foo(P p) {
                println "foo(Class) called"
            }
        } 
        
        new Methods().foo(new C())
        

        now the method selection is different and it outputs

        foo(Interface) called
        

        Because of this method selection bug, it chooses

        String serialize(Writable writable)
        

        over

        String serialize(GPathResult writable)
        

        and goes into the buggy method.

        Show
        Roshan Dawrani added a comment - - edited Apart from the issue highlighted in the previous comment, there also seems to be some method selection bug in here. Here are 2 snippets that highlight the difference in method selections made by groovy: 1) interface I {} class C implements I {} class Methods { def foo(I i) { println "foo(Interface) called" } def foo(C i) { println "foo( Class ) called" } } new Methods().foo( new C()) results in foo(Class) called 2) But if I have a slight variant interface I {} class P implements I {} class C extends P {} class Methods { def foo(I i) { println "foo(Interface) called" } def foo(P p) { println "foo( Class ) called" } } new Methods().foo( new C()) now the method selection is different and it outputs foo(Interface) called Because of this method selection bug, it chooses String serialize(Writable writable) over String serialize(GPathResult writable) and goes into the buggy method.
        Hide
        Roshan Dawrani added a comment -

        Discussed the method selection with Jochen and the difference highlighted in comments above is by design and desired in other scenarios.

        So fixed the serialization bit in XMLUtil.

        Show
        Roshan Dawrani added a comment - Discussed the method selection with Jochen and the difference highlighted in comments above is by design and desired in other scenarios. So fixed the serialization bit in XMLUtil.

          People

          • Assignee:
            Roshan Dawrani
            Reporter:
            Tim Yates
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: