Come faccio a stampare un nodo groovy con lo spazio dei nomi conservato?
-
03-07-2019 - |
Domanda
Quando uso questo codice per generare un po 'di XML ho analizzato (e modificato) 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()
le dichiarazioni dello spazio dei nomi sul nodo radice non vengono stampate, anche se sono presenti nel toString ()
di root ... qualche idea?
Soluzione
Sembra che stia denormalizzando l'output e includendo il contesto dello spazio dei nomi insieme ai nodi che hanno effettivamente bisogno del contesto dello spazio dei nomi.
Ad esempio, la pagina web per questa domanda arriva con lo spazio dei nomi creativeCommons incorporato:
<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 si genera l'xml usando questo script:
def root = new XmlParser().parseText("http://stackoverflow.com/feeds/question/227447".toURL().text)
println new XmlNodePrinter().print(root)
Finisce per spostare lo spazio dei nomi nel nodo di licenza che necessita di quello spazio dei nomi. Non è un grosso problema in questo caso in quanto esiste solo un singolo nodo in quello spazio dei nomi. Se la maggior parte dell'XML fosse spaziata dal nome, probabilmente farebbe gonfiare le cose un po 'di più.
<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 davvero volessi normalizzare i nodi, dovresti apportare alcune modifiche a XmlNodePrinter per fare 2 passaggi attraverso l'XML, prima per raccogliere tutti gli spazi dei nomi usati e in secondo luogo per visualizzarli in alto anziché all'interno di ciascuno nodo con spazio dei nomi. Il codice sorgente groovy è in realtà abbastanza leggibile e non sarebbe così difficile da modificare se ne avessi davvero bisogno.
Altri suggerimenti
Ho appena avuto lo stesso problema e dopo un po 'di armeggiare ho trovato una soluzione alternativa.
Usi XmlSluper invece di XmlParser e usi StreamingMarkupBuilder anziché XmlNodePrinter . Quindi approfitti della chiusura in bind e usi la variabile incorporata mkp per dichiarare gli spazi dei nomi.
Ad esempio; usando l'esempio xml di origine di Ted dall'alto:
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
Risultati in:
<?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>