Groovy XML和"xml:"命名空间

7
我正在编写一些用于修改XML文件的脚本。这些文件中使用了xml:lang元素。Groovy(XmlSlurper)似乎会插入tag0命名空间,我不太介意,但它似乎会破坏后续使用XmlUtil进行处理的过程。
例如:
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)

导致
[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.

xml:命名空间应该默认存在,我尝试使用.declareNamespace()添加它,但似乎没有帮助。我感觉我错过了一些明显的东西,但Google无法告诉我是什么。

2个回答

9

我在几年前的这个帖子中找到了以下内容:

问题在于原始文档使用默认命名空间。

SMB通常不使用默认命名空间,因此它会发明一个标记,并将其用于显式标记命名空间中的每个元素。对于XML解析器来说,无论如何指定命名空间都没有关系。然而,有时出于美观原因,使用默认命名空间是可取的。

如果你把mkp.declareNamespace("": "http://java.sun.com/xml/ns/j2ee")作为你的构建器闭包的第一行,你应该得到你想要的输出。

然而,这似乎并不起作用。

我找到的唯一解决方案是让Slurper忽略命名空间和验证;

def root = new XmlSlurper(false,false).parseText(source)

很遗憾,对我没有产生那种效果。我得到了与之前完全相同的错误。我使用的是Groovy 1.8.6,你呢? - Erik Ackerman
@ErikAckerman 我更新了我的答案,展示了我找到的唯一解决方案。 - tim_yates
@tim_yates: +1。我也有类似的问题,你有没有找到其他解决方案?(网址:http://stackoverflow.com/questions/10295178/xml-generation-gives-fatal-error-using-groovy) - AabinGunz
@AbhishekSimon 目前,我不知道任何其他的解决方案 :-( - tim_yates
你能否尝试使用最新版本的Groovy(从github或其中一个快照版本)?我刚刚提交了一个修复此问题的补丁,这可能会解决你的问题:https://jira.codehaus.org/browse/GROOVY-5879如果还有问题,请在下一次发布之前告知,以便进行必要的改进。谢谢。 - Paul King
显示剩余2条评论

2

将默认命名空间设置为空标签对我有用(没有添加“tag0”)。 我使用默认的XmlSlurper构造函数来实现工作命名空间和验证,例如:

def root = new XmlSlurper().parseText(source).declareNamespace(xml: "http://www.w3.org/XML/1998/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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接