更改XML标记名称

Ing*_*kat 6 groovy xmlslurper

我想转换我解析过的XML文档XmlSlurper.(相同的)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)
Run Code Online (Sandbox Code Playgroud)

我想得到以下内容:

<root>
  <foo>
    <bar/>
  </foo>
</root>
Run Code Online (Sandbox Code Playgroud)

(我在XML上编写测试断言,并希望简化它们的结构.)我已经阅读了使用XmlSlurper更新XML并进行了搜索,但在保留其子节点时没有找到replaceNode()replaceBody()交换节点.

tim*_*tes 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)
Run Code Online (Sandbox Code Playgroud)

哪个印刷品:

<?xml version="1.0" encoding="UTF-8"?><root>
  <foo>
    <bar/>
  </foo>
</root>
Run Code Online (Sandbox Code Playgroud)

但是,这将删除节点中的任何内容.为了维护内容,我们可能需要使用递归和XmlParser从现有的doc生成一个新的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() )
Run Code Online (Sandbox Code Playgroud)

并打印:

<?xml version="1.0" encoding="UTF-8"?><root>
  <foo>
    <bar>something</bar>
    <bar>something else</bar>
    <noid>woo</noid>
  </foo>
</root>
Run Code Online (Sandbox Code Playgroud)

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