Erik Ackerman
Erik Ackerman

Reputation: 105

Groovy XML and the "xml:" namespace

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.

Upvotes: 7

Views: 6875

Answers (2)

minsk
minsk

Reputation: 885

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
}

Upvotes: 2

tim_yates
tim_yates

Reputation: 171084

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)

Upvotes: 9

Related Questions