Groovy: XmlSlurper, Не удалось сначала заменить узел и попытаться снова добавить тот же узел.любой сталкивался с этой проблемой - PullRequest
1 голос
/ 01 апреля 2012

// Невозможно добавить замененные узлы обратно в xml, используя xml slurper. Выдает исключение stackoverflow. Теперь идея, как это сделать

def xml = """<container>
                   <listofthings>
                       <thing id="100" name="foo"/>
                   </listofthings>
                 </container>"""

    def root = new XmlSlurper().parseText(xml)
    def fun = new ArrayList(root.listofthings.collect{it})
    root.listofthings.thing.each {
       it.replaceNode {}
       }
    root.listofthings.appendNode  ( { thing(id:102, name:'baz') })
    fun.each {
    root.listofthings.appendNode it
    }

    def outputBuilder = new groovy.xml.StreamingMarkupBuilder()
    String result = outputBuilder.bind { mkp.yield root }
    print result

1 Ответ

0 голосов
/ 02 апреля 2012

Вы звоните:

def fun = new ArrayList(root.listofthings.collect{it})

Который устанавливает fun в качестве узла <listofthings> (и, кстати, можно сократить до: def fun = root.listofthings)

Затем в строке:

fun.each {
  root.listofthings.appendNode it
}

Вы добавляете этот узел к узлу <listofthings>.Это означает, что ваше дерево никогда не закончится (поскольку вы присоединяете узел к себе), и, следовательно, StackOverflowException

Чтобы запустить код, вы можете изменить его на:

import groovy.xml.StreamingMarkupBuilder

def xml = """<container>
            |  <listofthings>
            |    <thing id="100" name="foo"/>
            |  </listofthings>
            |</container>""".stripMargin()

def root = new XmlSlurper().parseText(xml)

root.listofthings.thing*.replaceNode {}

root.listofthings.appendNode { 
  thing( id:102, name:'baz' )
}

def outputBuilder = new StreamingMarkupBuilder()
String result = outputBuilder.bind { mkp.yield root }

print result

то есть: избавиться от рекурсивного добавления узла.

Однако я не уверен, что вы пытались сделать с рекурсивным добавлением, так что это, вероятно, не делает то, что вы хотели сделать... Можете ли вы объяснить подробнее, какой результат вы хотели увидеть?

Редактировать

Мне удалось заставить XmlParser делать то, что, как я думаю, вы пытались сделать?

def xml = """<container>
            |  <listofthings>
            |    <thing id="100" name="foo"/>
            |  </listofthings>
            |</container>""".stripMargin()

def root = new XmlParser().parseText(xml)
def listofthings = root.find { it.name() == 'listofthings' }
def nodes = listofthings.findAll { it.name() == 'thing' }

listofthings.remove nodes

listofthings.appendNode( 'thing', [ id:102, name:'baz' ] )

nodes.each {
  listofthings.appendNode( it.name(), it.attributes(), it.value() )
}

def writer = new StringWriter()
new XmlNodePrinter(new PrintWriter(writer)).print(root)
def result = writer.toString()

print result

Это печатает:

<container>
  <listofthings>
    <thing id="102" name="baz"/>
    <thing id="100" name="foo"/>
  </listofthings>
</container>
...