更改XML标记名称

时间:2013-02-18 13:46:01

标签: groovy xmlslurper

我想转换我用XmlSlurper解析的XML文档。 (相同的)XML标记名称应替换为id属性的值;应删除所有其他属性。从这段代码开始:

def xml = """<tag id="root">
            |  <tag id="foo" other="blah" more="meh">
            |    <tag id="bar" other="huh"/>
            |  </tag>
            |</tag>""".stripMargin()

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

// Some magic here.

println groovy.xml.XmlUtil.serialize(root)

我想得到以下内容:

<root>
  <foo>
    <bar/>
  </foo>
</root>

(我在XML上编写测试断言,并希望简化它们的结构。)我已阅读Updating XML with XmlSlurper并在周围搜索,但找不到replaceNode()或{{1}在保留孩子的同时交换节点。

1 个答案:

答案 0 :(得分:5)

将“魔术”添加到问题中的代码中会给出:

def xml = """<tag id="root">
            |  <tag id="foo" other="blah" more="meh">
            |    <tag id="bar" other="huh"/>
            |  </tag>
            |</tag>""".stripMargin()

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

root.breadthFirst().each { n ->
  n.replaceNode { 
    "${n.@id}"( n.children() )
  }
}

println groovy.xml.XmlUtil.serialize(root)

打印哪些:

<?xml version="1.0" encoding="UTF-8"?><root>
  <foo>
    <bar/>
  </foo>
</root>

然而,这将删除节点中的任何内容。为了维护内容,我们可能需要使用递归和XmlParser从现有的doc生成一个新的文档...我会有一个想法

更一般的解决方案

我认为这更为普遍:

import groovy.xml.*

def xml = """<tag id="root">
            |  <tag id="foo" other="blah" more="meh">
            |    <tag id="bar" other="huh">
            |      something
            |    </tag>
            |    <tag id="bar" other="huh">
            |      something else
            |    </tag>
            |    <noid>woo</noid>
            |  </tag>
            |</tag>""".stripMargin()

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

def munge( builder, node ) {
  if( node instanceof Node && node.children() ) {
    builder."${node.@id ?: node.name()}" {
      node.children().each {
        munge( builder, it )
      }
    }
  }
  else {
    if( node instanceof Node ) {
      "${node.@id ?: node.name()}"()
    }
    else {
      builder.mkp.yield node
    }
  }
}

def w = new StringWriter()
def builder = new MarkupBuilder( w )
munge( builder, root )

println XmlUtil.serialize( w.toString() )

并打印:

<?xml version="1.0" encoding="UTF-8"?><root>
  <foo>
    <bar>something</bar>
    <bar>something else</bar>
    <noid>woo</noid>
  </foo>
</root>

现在传递没有(或空)id属性

的节点