2015-02-12 67 views
5

我想用xmllint --xpath来处理大量的xml文件(maven poms)。随着一些试验和错误我想通了,它并不如预期,由于这些文件中的坏默认命名空间声明,这是如下工作:强制xmllint忽略糟糕的xmlns

<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"> 

一个简单的命令如下失败:

$ echo $(xmllint --xpath '/project/modelVersion/text()' pom.xml) 
XPath set is empty 

如果我摆脱了xmlns属性,取代了根元素如下:

<project 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"> 

上面的命令给出了预期输出:

$ echo $(xmllint --xpath '/project/modelVersion/text()' pom.xml) 
4.0.0 

更改数百个pom文件不是一种选择,尤其是因为maven本身不会抱怨。

xmllint有没有办法处理文件的不好xmlns

UPDATE

感谢达米安我能够取得一些进展:

$ (echo setns x=http://maven.apache.org/POM/4.0.0; echo 'xpath /x:project/x:modelVersion/text()';) | xmllint --shell pom.xml 
/> setns x=http://maven.apache.org/POM/4.0.0 
/> xpath /x:project/x:modelVersion/text() 
Object is a Node Set : 
Set contains 1 nodes: 
1 TEXT 
    content=4.0.0 

但是这并不完全做我需要。我的后续问题如下:

  1. 有没有办法只打印文本?我想在上面的例子中输出包含在4.0.0

  2. 看来输出在大约30个字符后被截断。是否有可能获得完整的产出?这不会xmllint --xpath

+0

这不是一个糟糕的命名空间。这是一个命名空间。这通常意味着您还需要在XPath查询中使用名称空间,但我不熟悉用于告诉您具体操作的工具的具体细节。 – 2015-02-12 09:16:14

+0

这很糟糕,因为它导致xmllint失败:)另外,因为schmealocation是错误的。 – 2015-02-12 10:17:02

+1

“xmllint命名空间”上的一些简单搜索出现了[这个问题](http://stackoverflow.com/questions/8264134/xmllint-failing-to-properly-query-with-xpath),它似乎显示了两种可能与*命名空间一起工作的方式。这种模式似乎是正确的。它表示,由URI“maven.apache.org/POM/4.0.0”标识的模式可以位于URL“http:// maven.apache.org/maven-v4_0_0.xsd”和这似乎是真的。 – 2015-02-12 10:39:07

回答

5

条的命名空间发生在pom.xml给出的Sed

<?xml version="1.0" encoding="UTF-8"?> 
<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> 
</project> 

这样的:

cat pom.xml | sed '2 s/xmlns=".*"//g' | xmllint --xpath '/project/modelVersion' - 

返回此:

<modelVersion>4.0.0</modelVersion> 

,如果你有时髦的格式(例如,在XMLNS属性是对自己的线),通过格式化第一次运行它:

cat pom.xml | xmllint --format - | sed '2 s/xmlns=".*"//g' | xmllint --xpath '/project/modelVersion' - 
+0

谢谢,刚才看到这个。我确实有xmlns属性分布在多行上,'--format'可能是一个很好的解决方案 – 2015-05-29 22:06:21

1
xmllint --xpath "/*[local-name() = 'project']/*[local-name() = 'parent']/*[local-name() = 'version']/text()" pom.xml 

它不是真正的漂亮,但它避免格式化假设和/或重新格式化输入的pom.xml文件。

如果因为某些原因需要剥离“-SNAPSHOT”,请将上述结果通过| sed -e "s|-SNAPSHOT||"进行管理。