Pregunta

Cuando uso este código para generar un XML analizado (y modificado) con 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()

las declaraciones de espacio de nombres en el nodo raíz no se imprimen, incluso aunque estén en toString () de root ... ¿alguna idea?

¿Fue útil?

Solución

Parece que está desnormalizando la salida e incluyendo el contexto del espacio de nombres junto con los nodos que realmente necesitan el contexto del espacio de nombres.

Por ejemplo, la página web para esta pregunta viene con el espacio de nombres de creativeCommons incorporado:

<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>

Cuando genera el xml utilizando este script:

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

Termina moviendo el espacio de nombres al nodo de licencia que necesita ese espacio de nombres. No es un gran problema en este caso, ya que solo hay un nodo en ese espacio de nombres. Si la mayoría de los XML tuvieran un espacio de nombre, probablemente inflaría un poco más las cosas.

<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>

Si realmente quisiera que los nodos se normalizaran, tendría que hacer algunos ajustes a la XmlNodePrinter para hacer 2 pases a través del XML, primero para reunir todos los espacios de nombres usados ??y el segundo para mostrarlos en la parte superior en lugar de dentro de cada uno. nodo de espacio de nombres. El maravilloso código fuente es realmente bastante legible y no sería tan difícil de modificar si realmente lo necesitaras.

Otros consejos

Acabo de tener el mismo problema y después de un poco de juguetear, he encontrado una solución.

Utiliza XmlSluper en lugar de XmlParser y usa StreamingMarkupBuilder en lugar de XmlNodePrinter . Luego aprovechas el cierre en bind y utilizas la variable incorporada mkp para declarar los espacios de nombres.

Por ejemplo; usando el ejemplo xml de origen de Ted desde arriba:

def root = new XmlSlurper().parseText("http://stackoverflow.com/feeds/question/227447".toURL().text))
def outputBuilder = new StreamingMarkupBuilder()
String result = XmlUtil.serialize(outputBuilder.bind {
    mkp.declareNamespace('':'http://www.w3.org/2005/Atom')
    mkp.declareNamespace('creativeCommons':'http://backend.userland.com/creativeCommonsRssModule')
    mkp.declareNamespace('re':'http://purl.org/atompub/rank/1.0')
    mkp.yield root }
)
println result

Resultados en:

<?xml version="1.0" encoding="UTF-8"?><feed xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns="http://www.w3.org/2005/Atom" xmlns:re="http://purl.org/atompub/rank/1.0">
<title type="text">How do I print a groovy Node with namespace preserved? - Stack Overflow </title>
<link rel="self" type="application/atom+xml" href="http://stackoverflow.com/feeds/question/227447"/>
<link rel="alternate" type="text/html" href="http://stackoverflow.com/questions/227447"/>
<subtitle>most recent 30 from stackoverflow.com</subtitle>
<updated>2011-02-16T05:13:17Z</updated>
<id>http://stackoverflow.com/feeds/question/227447</id>
<creativeCommons:license>http://www.creativecommons.org/licenses/by-nc/2.5/rdf</creativeCommons:license>
<entry>
<id>http://stackoverflow.com/questions/227447/how-do-i-print-a-groovy-node-with-namespace-preserved</id>
<re:rank scheme="http://stackoverflow.com">2</re:rank>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top