强制 xmllint 忽略错误的默认 xmlns

Force xmllint to ignore bad default xmlns

我正在尝试使用 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 属性,替换根元素如下:

<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. 不会发生这种情况

使用 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' -

returns 这个:

<modelVersion>4.0.0</modelVersion>

如果你有时髦的格式(比如,xmlns 属性在它们自己的行上),运行 它首先通过格式化程序:

cat pom.xml | xmllint --format - | sed '2 s/xmlns=".*"//g' | xmllint --xpath '/project/modelVersion' -
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

它不是很漂亮,但它避免了格式假设 and/or 重新格式化输入 pom.xml 文件。

如果您出于某种原因需要删除“-SNAPSHOT”,请通过 | sed -e "s|-SNAPSHOT||".

传递上述结果