强制xmllint忽略错误的默认xmlns

时间:2015-02-12 09:05:42

标签: xmllint

我正在尝试使用xmllint --xpath处理大量xml文件(maven poms)。通过一些试验和错误,我发现它由于这些文件中的错误默认命名空间声明而无法按预期工作,如下所示:

<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属性,则替换root元素如下:

<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的文件?

更新

感谢Damien我能够取得一些进展:

$ ( 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

  3. 不会发生这种情况

2 个答案:

答案 0 :(得分:7)

使用sed

剥离命名空间

pom.xml中给出:

<?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' -

答案 1 :(得分:5)

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

对于顶级pom.xml:

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

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

如果由于某种原因需要剥离“-SNAPSHOT”,请通过| sed -e "s|-SNAPSHOT||"传递上述结果。