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

Replacing a Groovy XML Node causes problems in subsequents findAll calls

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Minor
    • Resolution: Not A Problem
    • 3.x, 2.5.x
    • None
    • XML Processing
    • None
    • Windows/JDK 8

    Description

      I use groovy to parse a XML file using XmlParser. Just to avoid the handling of namespace prefixes, I used xmlRoot.'**'.findAll() method to find some nodes. The sample code shows how it works correctly until I just read the nodes, because each item passed to the closure is a Node object. But when I change the contents of a node (in this case, just the text of the node), the next call to findAll does not iterate on Node objects. For each character I put in the text, a String object is passed to the closure. I solved it checking the type with instanceof, but it seems to be that this is a bug.

      Am I doing something wrong or it's a bug?

      class XmlParserTest {
      
          static final String XML_SAMPLE = """
           <ns0:root xmlns:ns0="mycompany.com">
               <ns0:firstParent>
                   <ns0:item1>uppercase_me!</ns0:item1>
               </ns0:firstParent>
               <ns0:secondParent>
                   <ns0:item2>uppercase_me_too!</ns0:item2>
               </ns0:secondParent>
           </ns0:root>
          """
      
          static void main(String[] args) {
              def xmlRoot = new XmlParser(false, false).parseText(XML_SAMPLE)
      
              //******* find item1 and capitalize its text ********
              def nds1 = xmlRoot.'**'.findAll {
                  it.name().equals("ns0:item1")
              }
      
              Node nd1 = nds1[0]
      
              //This changes the text of the node, but something strange happens to the node tree
              nd1.setValue(nd1.value().toString().toUpperCase())
      
              //The same problem happens using replaceNode() instead of setValue()
              //Node newNode = new Node(nd1.parent(), nd1.name(), nd1.value().toString().toUpperCase())
              //nd1.replaceNode(newNode)
      
              //******* find item2 and capitalize its text ********
              def nds2 = xmlRoot.'**'.findAll {
                  //for each character in the string "uppercase me!" a String is passed instead of Node
                  //As String doesn't have a name method, an exception is raised
                  // it.name().equals("ns0:item2")
                  //using instanceof fixes the problem, at least for this case
                  it instanceof Node && it.name().equals("ns0:item2")
              }
      
              Node nd2 = nds2[0]
              nd2.setValue(nd2.value().toString().toUpperCase())
      
              assert nd1.value().toString() == nd1.value().toString().toUpperCase()
              assert nd2.value().toString() == nd2.value().toString().toUpperCase()
          }
      }
      

      Attachments

        Activity

          People

            Unassigned Unassigned
            davidobber David Obber
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: