如何打印保留命名空间的 groovy 节点?

dan*_*anb 5 xml groovy namespaces xml-parsing

当我使用此代码输出一些我解析(和修改)的 XML 时 XmlParser

XmlParser parser = new XmlParser()
def root = parser.parseText(feedUrl.toURL().text)
def writer = new StringWriter()
new XmlNodePrinter(new PrintWriter(writer)).print(root)
println writer.toString()
Run Code Online (Sandbox Code Playgroud)

根节点的命名空间声明不打印,即使他们在那里的toString()...任何想法?

Ted*_*eid 1

看起来它正在对输出进行非规范化,并包括名称空间上下文以及实际需要名称空间上下文的节点。

例如,此问题的网页嵌入了 CreativeCommons 命名空间:

<feed xmlns="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:thr="http://purl.org/syndication/thread/1.0">
  <!-- snip -->
  <creativeCommons:license>http://www.creativecommons.org/licenses/by-nc/2.5/rdf</creativeCommons:license>
  <!-- snip -->
</feed>
Run Code Online (Sandbox Code Playgroud)

当您使用此脚本输出 xml 时:

def root = new XmlParser().parseText("http://stackoverflow.com/feeds/question/227447".toURL().text)
println new XmlNodePrinter().print(root)
Run Code Online (Sandbox Code Playgroud)

它最终将命名空间移动到需要该命名空间的许可证节点。在这种情况下没什么大不了的,因为该命名空间中只有一个节点。如果大部分 XML 都是命名空间的,那么它可能会使事情变得更加臃肿。

<feed xmlns="http://www.w3.org/2005/Atom">
  <!-- snip -->
    <creativeCommons:license xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule">
http://www.creativecommons.org/licenses/by-nc/2.5/rdf
  </creativeCommons:license>
  <!-- snip -->
</feed>
Run Code Online (Sandbox Code Playgroud)

如果您确实希望节点规范化,则必须对 XmlNodePrinter 进行一些调整,以执行两次 XML 传递,首先收集所有使用的命名空间,然后在顶部而不是在每个命名空间节点中输出它们。Groovy 源代码实际上非常可读,并且如果您确实需要的话,修改起来并不困难。