groovy
  1. groovy
  2. GROOVY-3983

Using xpath returns arraylist instead of nodelist

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Not A Bug
    • Affects Version/s: 1.6.7
    • Fix Version/s: None
    • Component/s: XML Processing
    • Labels:
      None
    • Environment:
      Windows Vista
    • Number of attachments :
      0

      Description

      I just moved code from grails 1.1 to grails 1.2.

      I am parsing an XML structure similar to
      <Items><Item>...</Item><Item>...</Item></Items>

      My groovy code looks like
      for (item in doc.Items.Item)

      {...}

      It used to be that doc.Items.Item returned a Node List and then the variable item got bound to each Item from xml.

      Now the doc.Items.Item returns a one element ArrayList whose single element is the NodeList from before.
      So now item gets bound to the entire Item NodeList.

      This seems like a bug to me.

        Activity

        Hide
        Andrew Ressler added a comment -

        Hello Michael,

        Here's a little helper file I wrote. I wrap getNodeList around every call that has the problem.

        
        class XmlHelper {
        
        
          // Use this when using xpath to get around bug in grails 1.2
          static def getNodeList (nodelist)
          {
            if (nodelist.class == ArrayList)
            {
              return nodelist[0]
            }
            else
            {
              return nodelist
            }
          }
        
        
          static def getNodeName (node)
          {
            def n = node.name()
            if (n instanceof groovy.xml.QName)
            {
              return n.getLocalPart()
            }
            else
            {
              return n.toString()
            }
          }
        
        }
        
        Show
        Andrew Ressler added a comment - Hello Michael, Here's a little helper file I wrote. I wrap getNodeList around every call that has the problem. class XmlHelper { // Use this when using xpath to get around bug in grails 1.2 static def getNodeList (nodelist) { if (nodelist.class == ArrayList) { return nodelist[0] } else { return nodelist } } static def getNodeName (node) { def n = node.name() if (n instanceof groovy.xml.QName) { return n.getLocalPart() } else { return n.toString() } } }
        Hide
        Michael Smolyak added a comment -

        Andrew, thank you for your help. Changing the code to make it work correctly was not the a big problem. XmlParser gives you dozens of ways of accomplishing the same goal, so I managed to rewrite the code that it works.

        What concern me was that the upgrade to Grails 1.2 required me to make all those changes. I would like to understand why XmlParser is behaving differently in Grails 1.2 than it did in 1.1.1 from which I upgraded. Was my code incorrect and XmlParser is stricter about following certain conventions or was a bug introduced into the ecosystem?

        The issue I have mentioned was not the only one that required me to change the code. For example, where before I could write

        box.@llx

        had to be rewritten as

        box.'@llx'

        Were there changes in Groovy language that would cause such change in XmlParser behavior?

        Michael

        Show
        Michael Smolyak added a comment - Andrew, thank you for your help. Changing the code to make it work correctly was not the a big problem. XmlParser gives you dozens of ways of accomplishing the same goal, so I managed to rewrite the code that it works. What concern me was that the upgrade to Grails 1.2 required me to make all those changes. I would like to understand why XmlParser is behaving differently in Grails 1.2 than it did in 1.1.1 from which I upgraded. Was my code incorrect and XmlParser is stricter about following certain conventions or was a bug introduced into the ecosystem? The issue I have mentioned was not the only one that required me to change the code. For example, where before I could write box.@llx had to be rewritten as box.'@llx' Were there changes in Groovy language that would cause such change in XmlParser behavior? Michael
        Hide
        olivier FRESSE added a comment -

        This is a very strange issue

        I use XmlParser to update an XML file used within IzPack.
        basically, I have to update the src attribute of the following node,
        <res id="jlinkProe" src="./installer/shared_lib/xxxxx"/>

        I used the following code :

        The following examples can be tested in the grails console

        This code doesn't work
        
        
        xtext = """<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
        <!-- <!DOCTYPE installation SYSTEM "./installation.dtd"> -->
        
        <installation version="1.0">
        
        
            <resources>
                
                <res id="LicencePanel.licence" src="./installer/resources/Licence.txt"/>
                <res id="InfoPanel.info" src="./installer/resources/Readme.txt"/>
                <res id="ProcessPanel.Spec.xml" src="./installer/scripts/ProcessPanel.Spec.xml"/>
                <res id="userInputSpec.xml" src="./installer/scripts/userInputSpec.xml"/>
                <res id="pworker.war" src="./installer/staging/pworker.war"/>
                <res id="DSL" src="./installer/staging/DSL.zip"/>
        
        
                <res id="jlinkWraper" src="./installer/shared_lib/jlinkWrapper.jar"/>
                <res id="jlinkProe" src="./installer/shared_lib/xxxxx"/>
            </resources>
        
        </installation>"""
        
        
        
           installation = (new XmlParser()).parseText(xtext)
           println "gne ? : ${installation.resources.res.class}"
           proeNode = installation.resources.res.find({
           println "cherchenode ${it.'@id'}"
           println it.class
            it.'@id' == 'jlinkProe'
             })
             
          proeNode.'@src' = "./installer/shared_lib/tatayoyo"
           
          
           proeNode
           
        

        I made the following modifications to make it work.

        proeNode = installation.resources.res [0].find({

        proeNode. attributes['src'] = "./installer/shared_lib/tatayoyo"

        This is definitely a grails issue, as I can't reproduce it in pure groovy code.

        This code works
        
        
        xtext = """<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
        <!-- <!DOCTYPE installation SYSTEM "./installation.dtd"> -->
        
        <installation version="1.0">
        
        
            <resources>
                
                <res id="LicencePanel.licence" src="./installer/resources/Licence.txt"/>
                <res id="InfoPanel.info" src="./installer/resources/Readme.txt"/>
                <res id="ProcessPanel.Spec.xml" src="./installer/scripts/ProcessPanel.Spec.xml"/>
                <res id="userInputSpec.xml" src="./installer/scripts/userInputSpec.xml"/>
                <res id="pworker.war" src="./installer/staging/pworker.war"/>
                <res id="DSL" src="./installer/staging/DSL.zip"/>
        
        
                <res id="jlinkWraper" src="./installer/shared_lib/jlinkWrapper.jar"/>
                <res id="jlinkProe" src="./installer/shared_lib/xxxxx"/>
            </resources>
        
        </installation>"""
        
        
        
           installation = (new XmlParser()).parseText(xtext)
           println "class  : ${installation.resources.res.class}"
           proeNode = installation.resources.res[0].find({
           println "cherchenode ${it.'@id'}"
           println it.class
            it.'@id' == 'jlinkProe'
             })
             
          proeNode.attributes['src'] = "./installer/shared_lib/tatayoyo"
           
          
           proeNode
           
        
        Show
        olivier FRESSE added a comment - This is a very strange issue I use XmlParser to update an XML file used within IzPack. basically, I have to update the src attribute of the following node, <res id="jlinkProe" src="./installer/shared_lib/xxxxx"/> I used the following code : The following examples can be tested in the grails console This code doesn't work xtext = """<?xml version=" 1.0 " encoding=" iso-8859-1 " standalone=" yes" ?> <!-- <!DOCTYPE installation SYSTEM "./installation.dtd" > --> <installation version= "1.0" > <resources> <res id= "LicencePanel.licence" src= "./installer/resources/Licence.txt" /> <res id= "InfoPanel.info" src= "./installer/resources/Readme.txt" /> <res id= "ProcessPanel.Spec.xml" src= "./installer/scripts/ProcessPanel.Spec.xml" /> <res id= "userInputSpec.xml" src= "./installer/scripts/userInputSpec.xml" /> <res id= "pworker.war" src= "./installer/staging/pworker.war" /> <res id= "DSL" src= "./installer/staging/DSL.zip" /> <res id= "jlinkWraper" src= "./installer/shared_lib/jlinkWrapper.jar" /> <res id= "jlinkProe" src= "./installer/shared_lib/xxxxx" /> </resources> </installation>""" installation = ( new XmlParser()).parseText(xtext) println "gne ? : ${installation.resources.res.class}" proeNode = installation.resources.res.find({ println "cherchenode ${it.'@id'}" println it.class it.'@id' == 'jlinkProe' }) proeNode.'@src' = "./installer/shared_lib/tatayoyo" proeNode I made the following modifications to make it work. proeNode = installation.resources.res [0] .find({ proeNode. attributes ['src'] = "./installer/shared_lib/tatayoyo" This is definitely a grails issue, as I can't reproduce it in pure groovy code. This code works xtext = """<?xml version=" 1.0 " encoding=" iso-8859-1 " standalone=" yes" ?> <!-- <!DOCTYPE installation SYSTEM "./installation.dtd" > --> <installation version= "1.0" > <resources> <res id= "LicencePanel.licence" src= "./installer/resources/Licence.txt" /> <res id= "InfoPanel.info" src= "./installer/resources/Readme.txt" /> <res id= "ProcessPanel.Spec.xml" src= "./installer/scripts/ProcessPanel.Spec.xml" /> <res id= "userInputSpec.xml" src= "./installer/scripts/userInputSpec.xml" /> <res id= "pworker.war" src= "./installer/staging/pworker.war" /> <res id= "DSL" src= "./installer/staging/DSL.zip" /> <res id= "jlinkWraper" src= "./installer/shared_lib/jlinkWrapper.jar" /> <res id= "jlinkProe" src= "./installer/shared_lib/xxxxx" /> </resources> </installation>""" installation = ( new XmlParser()).parseText(xtext) println "class : ${installation.resources.res.class}" proeNode = installation.resources.res[0].find({ println "cherchenode ${it.'@id'}" println it.class it.'@id' == 'jlinkProe' }) proeNode.attributes['src'] = "./installer/shared_lib/tatayoyo" proeNode
        Hide
        Paul King added a comment -

        There doesn't seem to be a consensus as to whether this is a groovy or grails issue. In fact, it seems like we don't have a standalone groovy failing test case. I am thinking of closing the issue and we can re-open or create a new one if we can find an example of the problem again. Any objections?

        Show
        Paul King added a comment - There doesn't seem to be a consensus as to whether this is a groovy or grails issue. In fact, it seems like we don't have a standalone groovy failing test case. I am thinking of closing the issue and we can re-open or create a new one if we can find an example of the problem again. Any objections?
        Hide
        Paul King added a comment -

        No objections raised to closing. Please open a new issue with a standalone Groovy test case if you are still having problems.

        Show
        Paul King added a comment - No objections raised to closing. Please open a new issue with a standalone Groovy test case if you are still having problems.

          People

          • Assignee:
            Paul King
            Reporter:
            Andrew Ressler
          • Votes:
            2 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: