[ 
https://issues.apache.org/jira/browse/GROOVY-9048?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

David Obber updated GROOVY-9048:
--------------------------------
    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()
         }

    }

  was:
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>
        <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()
        }

    }


> Replacing a Groovy XML Node causes problems in subsequents findAll calls
> ------------------------------------------------------------------------
>
>                 Key: GROOVY-9048
>                 URL: https://issues.apache.org/jira/browse/GROOVY-9048
>             Project: Groovy
>          Issue Type: Bug
>          Components: XML Processing
>    Affects Versions: 3.x, 2.5.x
>         Environment: Windows/JDK 8
>            Reporter: David Obber
>            Priority: Minor
>
> 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()
>          }
>     }



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to