Native shell命令设置为从XML提取节点值

时间:2013-06-06 10:35:46

标签: xml xmllint

我正在尝试从pom.xml中提取节点的值:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <parent>
        <groupId>org.me.labs</groupId>
        <artifactId>my-random-project</artifactId>
        <version>1.5.0</version>
    </parent>
    ...
</project>

我需要使用shell命令从XML中提取artifactId和版本。我有以下要求/观察:

  1. shell脚本将在我们工作时使用的构建程序集文件中完成,因此脚本越小越好。
  2. 由于它将在多个系统(通常是RHEL5)上使用,我正在寻找可以在默认图像上本机运行的东西。
  3. 像pom这样的标签可以出现在pom的其他地方,所以我不能简单地为这些标签添加awk。
  4. 我尝试了以下内容:

    1. xpath 适用于我的Mac,但在RHEL计算机上默认不可用。同样适用于xmllint --xpath,我猜这只适用于xmllint的更高版本,我没有,也无法执行。
    2. xmllint --pattern 似乎很有希望,但我似乎无法从xmllint --pattern '//project/parent/version' pom.xml(打印整个XML)或xmllint --stream --pattern '//project/parent/version' pom.xml(无输出)中获得输出
    3. 我在这里意识到这是一个常见问题,但上述几点是我不能使用这些答案的原因。 TIA求助。

6 个答案:

答案 0 :(得分:15)

--format仅用于格式化(缩进等)文档。您可以使用--xpath(在Ubuntu中测试,libxml v20900)来执行此操作:

$ xmllint --xpath "//project/parent/version/text()" pom.xml
1.5.0

答案 1 :(得分:14)

我已经设法使用xmllint --shell暂时使用这个相当不可靠的脚本来解决它。

echo "cat //project/parent/version" | xmllint --shell pom.xml | sed '/^\/ >/d' | sed 's/<[^>]*.//g'

如果XML节点具有像我的pom.xml那样的命名空间属性,那么事情会变得更重,基本上按名称提取节点:

echo "cat //*[local-name()='project']/*[local-name()='parent']/*[local-name()='version']" | xmllint --shell pom.xml | sed '/^\/ >/d' | sed 's/<[^>]*.//g'

希望它有所帮助。如果有人能够简单地表达这些表达方式,我将不胜感激。

答案 2 :(得分:5)

我来到这里是为了寻找一种从网站上获取价值的好方法。以下示例可能对那些具有支持-xpath的xmllint版本的人(与海报不同)有用。

我需要提取elasticsearch .deb文件的最新稳定版本并安装它。维护者已经将版本号放在带有“版本”类的范围内。

version=`curl -s http://www.elasticsearch.org/download/ |\
 xmllint --html --xpath '//span[@class="version"]/text()'\
 2>/dev/null - `;

发生了什么:

我们使用curl -s(silent)选项。

curl -s http://www.elasticsearch.org/download/

我们使用xmllint --html和--xpath开关。 xpath参数(单引号)

'//span[@class="version"]/text()'

...寻找&lt; span&gt;具有类属性(@class)“version”的节点,并提取文本值(/ text())。

由于xmllint(令人惊讶!)是一个linter,它会尖叫你的html流中不可避免的垃圾。我们以通常的方式将stderr指向/ dev / null:

 2>/dev/null

最后,请注意xmllint命令末尾的“ - ”,它告诉xmllint流来自stdin。

答案 3 :(得分:3)

使用text() XPath函数为您提供元素值,而不必删除XML标记:

echo "cat //project/parent/version/text()" | xmllint --shell pom.xml

答案 4 :(得分:0)

你可以尝试

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

答案 5 :(得分:0)

使用POM,您可能会遇到名称空间问题,这会阻止 xmllint 按预期工作。 This articles指出了另一种非常好的解决方案(查看 sed 段落)。