Замена узла Groovy XML вызывает проблемы в последующих вызовах findAll

#groovy #xml-parsing #findall

#groovy #xml-синтаксический анализ #findall

Вопрос:

Я использую groovy для синтаксического анализа XML-файла с помощью XMLParser. Просто чтобы избежать обработки префиксов пространства имен, я использовал метод XmlRoot.’**’.findAll() для поиска некоторых узлов. Пример кода показывает, как это работает правильно, пока я просто не прочитаю узлы, потому что каждый элемент, передаваемый в закрытие, является объектом узла. Но когда я изменяю содержимое узла (в данном случае, только текст узла), следующий вызов findAll не выполняет итерацию объектов узла. Для каждого символа, который я ввожу в текст, объект String передается в закрытие. Я решил это, проверяя тип с помощью instanceof, но, похоже, это ошибка.

Я делаю что-то не так или это ошибка?

  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 amp;amp; 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()
    }

}
  

Комментарии:

1. не ясно, что вы хотите сделать. вводить весь текст в верхнем регистре в узлах с некоторыми именами?

2. и что это значит something strange happens to the node tree ? в чем именно проблема?

3. это означает, что если вы рассматриваете node.findAll() как обход дерева, вы увидите, что для каждого символа в строке вы получаете вызов с параметром «it», который является не узлом, а строкой с символом.

Ответ №1:

Я открыл проблему в Groovy: это объяснение того, что произошло