【问题标题】:Change XML tag name更改 XML 标记名称
【发布时间】:2013-02-18 13:46:00
【问题描述】:

我想转换一个用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() 或 replaceBody() 在交换节点的同时保留它的孩子。

【问题讨论】:

  • 我假设一些标签也有内容?如果没有,你可以这样做:root.breadthFirst().each { n -&gt; n.replaceNode { "${n.@id}"( n.children() ) } } 但这会丢失节点中的任何内容
  • @tim_yates:目前没有内容,所以你的解决方案(虽然不完整)已经对我有用。请将其发布为答案!
  • 完成 :-) 我会考虑一个更通用的递归函数
  • 非常感谢您的回答;我很想看到一个通用的解决方案。
  • 添加了似乎——经过快速测试——更通用的解决方案

标签: groovy xmlslurper


【解决方案1】:

在问题中的代码中添加“魔术”给出:

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 从现有文档生成新文档...我会考虑一下

更通用的解决方案

我认为这是更笼统的:

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 属性的节点

【讨论】:

    猜你喜欢
    • 2019-07-14
    • 1970-01-01
    • 2016-05-07
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    • 1970-01-01
    • 2014-09-05
    • 2012-06-06
    相关资源
    最近更新 更多