默认命名空间中的元素已添加tag0命名空间

18
我正在尝试使用Groovy的XmlSlurper解析和修改Maven的pom.xml。我的pom.xml声明了名称空间xsi。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
     http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>a-group-id</groupId>
<artifactId>an-artifact-id</artifactId>

我的 Groovy 源代码如下:

import groovy.xml.XmlUtil
def pom = new XmlSlurper().parse('pom.xml')
   .declareNamespace('': 'http://maven.apache.org/POM/4.0.0',
      xsi: 'http://www.w3.org/2001/XMLSchema-instance')
//manipulate the pom
println XmlUtil.serialize(pom)

注意,我已将第一个命名空间声明为空。但是在输出中,tag0被添加到了每个地方。

<?xml version="1.0" encoding="UTF-8"?>
<tag0:project xmlns:tag0="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
      http://maven.apache.org/maven-v4_0_0.xsd">
<tag0:modelVersion>4.0.0</tag0:modelVersion>
<tag0:groupId>a-group-id</tag0:groupId>
<tag0:artifactId>an-artifact-id</tag0:artifactId>

如何避免这种情况?

目前我的解决方法是手动删除标签:

println XmlUtil.serialize(pom).replaceAll('tag0:', '').replaceAll(':tag0', '')

2
构造不支持命名空间的XmlSlurper是否足够好?例如:println XmlUtil.serialize( new XmlSlurper( false, false ).parse( 'pom.xml' ) ) - tim_yates
哇,是的,那已经足够了,谢谢Tim。你能把它作为答案提供吗?另外我注意到XML中的所有注释都丢失了,你知道有什么解决方法吗?顺便说一下,这是我写的两个实用工具pomRmpomVersions - stivlo
目前还不知道如何保留评论... :-( 如果今天下午有空的话,我会考虑一下... - tim_yates
可能是XmlSlurper的问题,在《Groovy和Grails Recipes》书中它说“XmlSlurper主要用于只读操作”。也许我应该尝试使用XmlParser。不过,您已经回答了我的原始问题,如果您有时间,在评论中发布您已经给出的答复,我会接受它。 - stivlo
我在邮件列表中找到了一些扩展XmlParser的东西,看起来它正朝着我们想要的方向发展,但是到目前为止还没有成功让它工作:-/ 不确定是解析问题还是序列化问题... - tim_yates
3个回答

24

您可以这样构造没有命名空间感知XmlSlurper

import groovy.xml.XmlUtil

def pom = new XmlSlurper( false, false ).parse( 'pom.xml' )
println XmlUtil.serialize(pom)

这应该会给您想要的答案...目前不清楚如何在 slurp/serialize 循环过程中保留注释 :-(

就像你所说,使用 XmlParser 可能是可行的,但是我目前的尝试失败了 :-( 这里有一些代码 some code here ,可能可以让您接近解决方法,但是目前为止我还没有成功 :-(


谢谢Tim,这个有效,至于评论问题,我会在周末尝试。 - stivlo
CommentCollectingParser用于查找节点前面的注释,例如要打印注释:def parser = new CommentCollectingParser(); def root = parser.parse(new File('plan.xml')); println parser.commentsFor(root.week[0]); 但是,如果我尝试打印整个XML,则不会包括它们。def writer = new StringWriter(); new XmlNodePrinter(new PrintWriter(writer)).print(root); println writer.toString(); 实际上,在XmlParser JavaDoc中,他们说:此解析器忽略注释和处理指令 - stivlo

4
我遇到了与“tag0”添加到未定义命名空间(即在“无命名空间”命名空间中)的元素相同的问题。我通过添加

来解决这个问题。
declareNamespace('': '')

该操作将元素从默认命名空间重置为“无命名空间”命名空间。


1
我发现如果你在处理命名空间和遇到tag0问题时,最好使用XmlParser而不是XmlSlurper。从语法上看,它们似乎相同,如下所示:

def root = new XmlParser().parse(new File('example.xml'))
println XmlUtil.serialize(root)

以上代码将完全按照应有的命名空间输出 example.xml。
如果您想以某种方式处理根节点,例如查找特定节点,请使用 Groovy API 并输出结果,例如:
def root = new XmlParser().parse(new File('example.xml')
def result = root."ns:Element"[0]
println XmlUtil.serialize(result)

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