Pergunta

Quando eu uso este código para a saída de alguns XML I analisado (e modificada) com 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()

as declarações de namespace no nó raiz não são impressas, mesmo que eles estão lá na toString() de root ... alguma idéia?

Foi útil?

Solução

Parece que ele está desnormalizar a saída e incluindo o contexto namespace junto com os nós que realmente precisa do contexto namespace.

Por exemplo, a página da Web para esta pergunta vem com CreativeCommons Namespace 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>

Quando você saída xml usando este script:

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

Ele acaba de mover o namespace para o nó de licença que precisa desse namespace. Não é um grande negócio, neste caso, como há apenas um único nó em que namespace. Se a maior parte do XML foram namespaced, ele tinha coisas provavelmente o inchaço um pouco mais.

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

Se você realmente queria os nós normalizada, você teria que fazer alguns ajustes ao XmlNodePrinter para fazer 2 passagens através do XML, primeiro a reunir todos os namespaces e 2º usados ??para a saída-los no topo, em vez de dentro de cada nó de namespace. O código-fonte Groovy é realmente muito legível e não seria tão difícil de modificar, se você realmente precisava disso.

Outras dicas

Eu apenas tive o mesmo problema e depois de um pouco de mexer eu encontrei uma solução alternativa.

Você pode usar o XmlSluper em vez do XmlParser e uso StreamingMarkupBuilder em vez de XmlNodePrinter . Então você tirar proveito do fechamento em ligamento e use o mkp variável interna para declarar os namespaces.

Por exemplo; usando o exemplo xml fonte de Ted de cima:

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

<?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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top