Groovy,XMLParser - 在保留子元素的同时删除XML元素

时间:2016-04-28 14:45:20

标签: xml groovy

我尝试通过删除在保留这些元素的所有子项(嵌套元素和文本)时错误添加的标记(下例中的b标记)来修改XML文件。我希望用XMLParser做到这一点,因为这是一个更大的脚本的一部分,其中元素的顺序在后期发挥作用。

示例:

<?xml version="1.0" encoding="UTF-8"?>
<a>
   <b>
      <c />
      Test 1
   </b>
   <b>
      <c />
      Test 2
   </b>
</a>

我想要的东西类似于:

<?xml version="1.0" encoding="UTF-8"?>
<a>
    <c />
    <c />
    Test 1
    Test 2
</a>

到目前为止,我尝试了以下(args [0]是一个包含上述示例的文件),目的是简单地将所有子节点附加到父节点:

import groovy.xml.XmlUtil

def f = new File(args[0])
def parser = new XmlParser()
parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
parser.setFeature("http://xml.org/sax/features/namespaces", false)

def log = parser.parse(f)
def bs = log.'**'.findAll { node -> (node instanceof Node) && node.name() == 'b' }

bs.each { b ->
    Node bparent = b.parent()
    def bchildren = b.children() 

    bchildren.each { child ->
        if (child instanceof Node) {
            bparent.append(child)
        }
    }

    b.replaceNode{}
}


def xmlu = new XmlUtil()

def result = XmlUtil.serialize(log)
println result

但是使用此代码,我丢失了元素的实际文本内容,因为XMLParser返回Node和String对象。所以输出看起来:

<?xml version="1.0" encoding="UTF-8"?>
<a>
    <c />
    <c />
</a>

有没有办法将String对象添加到父节点?或者到目前为止我可能忽略了一种更为简单的方法?

2 个答案:

答案 0 :(得分:1)

这似乎有效......克隆节点并将它们添加到父节点,然后从它的父节点中删除b:

def xmlText = '''<?xml version="1.0" encoding="UTF-8"?>
<a>
   <b>
      <c />
      Test 1
   </b>
   <b>
      <c />
      Test 2
   </b>
</a>'''

import groovy.xml.*

def xml = new XmlParser().parseText(xmlText)
def bs = xml.'*'.findAll { it.name() == 'b' }

bs.each { b ->
    b.children().collect { it instanceof Node ? it.clone() : it }.each { b.parent().children().add(it) }
    b.parent().remove(b)
}

println XmlUtil.serialize(xml)

答案 1 :(得分:0)

以下将输出

<?xml version='1.0' encoding='UTF-8'?>
<a foo='bar'>
  <c blub='bla' />
      Test 1

  <c />
      Test 2

</a>
import groovy.xml.*

def parser = new XmlParser()
parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
parser.setFeature("http://xml.org/sax/features/namespaces", false)

def log = parser.parseText('''<?xml version="1.0" encoding="UTF-8"?>
<a foo="bar">
   <b bii="boo">
      <c blub="bla" />
      Test 1
   </b>
   <b>
      <c />
      Test 2
   </b>
</a>''')

def recurse
recurse = { builder, element ->
    element.children().each { child ->
        switch (child) {
            case { (it instanceof Node) && (it.name() == 'b') }:
                recurse builder, child
                break

            case { it instanceof Node }:
                builder."${child.name()}"(child.attributes()) {
                    recurse builder, child
                }
                break

            default:
                builder.mkp.yield child
                break
        }
    }
}

def builder = new MarkupBuilder(new PrintWriter(System.out))
builder.mkp.xmlDeclaration version: '1.0', encoding: 'UTF-8'
builder."${log.name()}"(log.attributes()) {
    recurse builder, log
}