Удаление узлов в XML с помощью Xpath в Groovy



У меня есть этот Заводной код, работающий для удаления узлов с помощью строк xpath, но у меня возникли проблемы с удалением узлов, где xpath приводит к нескольким экземплярам узлов.



Пример XML...



<root>
<element1>foo</element1>
<element2>bar</element2>
<items>
<item>
<name>a</name>
<desc>b</desc>
<item>
<item>
<name>c</name>
<desc>x</desc>
</item>
</items>
</root>


Код для удаления узлов...



def resource = XmlSlurper().parseText(xml)
def xpathsToDelete = ['/root/element1','/root/items/item/name']
xpathsToDelete.each {
def pathTokens = it.path.tokenize '/'
def currentNode = resource
if ( currentNode.name() == pathTokens.first() ) {
def xpath = pathTokens.tail().join '/'
currentNode = currentNode."${xpath}"
currentNode.replaceNode{}
}
}


Приведенный выше код удаляет узел element1 с помощью xpath /root/element1, который вычисляется для одного узла, но не работает для /root/items/name, который вычисляется для нескольких узлов.
606   2  

2 ответов:

Это очень сложно. Это связано с этим вопросом, который жизненно важен для моего ответа.

Вот решение:

import groovy.util.* 
import groovy.xml.* 

def xml = """<root>
  <element1>foo</element1>
  <element2>bar</element2>
  <items>
     <item>
       <name>a</name>
       <desc>b</desc>
     </item>
     <item>
        <name>c</name>
        <desc>x</desc>
     </item>
  </items>
</root>"""

def removeNodes = { doc, path ->
    def nodes = doc
    path.split("\\.").each { nodes = nodes."${it}" }
    nodes.each { it.replaceNode{} }    
}

def resource = new XmlSlurper().parseText(xml)
def xpathsToDelete = ['/root/element1','/root/items/item/name']

xpathsToDelete.each { xpath ->
    def trimXPath = xpath.replaceFirst( "/root/", "").replace("/",".")
    removeNodes(resource, trimXPath)
}

println XmlUtil.serialize(new StreamingMarkupBuilder().bind {
    mkp.yield resource
})

Это, кажется, тоже работает:

import groovy.xml.*

def xml = '''<root>
            |  <element1>foo</element1>
            |  <element2>bar</element2>
            |  <items>
            |     <item>
            |       <name>a</name>
            |       <desc>b</desc>
            |     </item>
            |     <item>
            |        <name>c</name>
            |        <desc>x</desc>
            |     </item>
            |  </items>
            |</root>'''.stripMargin()

def newxml = new XmlSlurper().parseText( xml ).with { x ->
  [ '/root/element1', '/root/items/item/name' ].each { path ->
    def s = path.split( '/' ).drop( 2 ).inject( x ) { element, p ->
      element."$p"
    }?.replaceNode {}
  }
  x
}

println XmlUtil.serialize(new StreamingMarkupBuilder().bind {
    mkp.yield newxml
})

Comments

    Ничего не найдено.