I'm writing a couple of scripts the modify xml files. The files in question use the xml:lang element. Groovy (XmlSlurper) seems to be inserting a tag0 namespace, which I wouldn't mind too much, except it seems to break later processing with XmlUtil.
An example:
import groovy.xml.StreamingMarkupBuilder
import groovy.xml.XmlUtil
String source = """<?xml version='1.0' encoding='UTF-8'?>
<root>
<one xml:lang="en">First</one>
<one xml:lang="de">Second</one>
</root>
"""
def root = new XmlSlurper().parseText(source).declareNamespace(xml: "http://www.w3.org/XML/1998/namespace")
println root
String xml = new StreamingMarkupBuilder().bind{
mkp.xmlDeclaration()
out << root
}
println xml
println XmlUtil.serialize(xml)
results in
[Fatal Error] :2:44: The value of the attribute "prefix="xmlns",localpart="tag0",rawname="xmlns:tag0"" is invalid. Prefixed namespace bindings may not be empty.
The xml: namespace is supposed to exist by default, and I've tried adding it with .declareNamespace() but it doesn't seem to help. I feel like I'm missing something obvious, but Google hasn't been able to tell me what it is.
Found this thread from a few years ago, which says:
The problem is that the original document uses the default namespace.
SMB does not normally use the default namespace so it invents a tag and uses it to explicitly mark each element in the namespace. As far as an XML parser is concerned it doesn't matter how the namespace is indicated. However there are cosmetic reasons why it is sometimes desirable to use default namespaces.
If you put
mkp.declareNamespace("": "http://java.sun.com/xml/ns/j2ee")
as the first line in your builder closure you should get the output you want.
However, this doesn't seem to work
The only solution I have found is to make the Slurper ignore namespaces and validation;
def root = new XmlSlurper(false,false).parseText(source)
Setting default namespace to empty tag works for me (no "tag0"added). I use default XmlSlurper constructor to have working namespacing and validation, eg:
def root = new XmlSlurper().parseText(source).declareNamespace(xml: "http://www.w3.org/XML/1998/namespace")
When binding, declare empty namespace:
def writer = new StreamingMarkupBuilder().bind {
mkp.declareNamespace("": "") //get rid of "tag0"
mkp.declareNamespace(xml: "http://www.w3.org/XML/1998/namespace")
mkp.yield root
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With