对于Ubuntu和/或CentOS,是否有一个包,它有一个命令行工具,可以执行像 foo //element@attribute filename.xml
或 foo //element@attribute < filename.xml
这样的XPath单行并逐行返回结果?
我正在寻找能够让我只需 apt-get install foo
或 yum install foo
的东西,然后只需开箱即用,无需包装或其他必要的改编 .
以下是一些接近的事例:
引入nokogiri . 如果我写这个包装器,我可以用上面描述的方式调用包装器:
#!/usr/bin/ruby
require 'nokogiri'
Nokogiri::XML(STDIN).xpath(ARGV[0]).each do |row|
puts row
end
XML :: XPath的 . 可以使用这个包装器:
#!/usr/bin/perl
use strict;
use warnings;
use XML::XPath;
my $root = XML::XPath->new(ioref => 'STDIN');
for my $node ($root->find($ARGV[0])->get_nodelist) {
print($node->getData, "\n");
}
来自XML :: XPath的 xpath
返回太多噪音, -- NODE --
和 attribute = "value"
.
来自XML的 xml_grep
:: Twig无法处理不返回元素的表达式,因此无法在不进一步处理的情况下提取属性值 .
编辑:
echo cat //element/@attribute | xmllint --shell filename.xml
返回类似于 xpath
的噪音 .
xmllint --xpath //element/@attribute filename.xml
返回 attribute = "value"
.
xmllint --xpath 'string(//element/@attribute)' filename.xml
返回我想要的内容,但仅适用于第一场比赛 .
对于几乎满足该问题的另一个解决方案,这里有一个可用于评估任意XPath表达式的XSLT(需要dyn:在XSLT处理器中评估支持):
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:dyn="http://exslt.org/dynamic" extension-element-prefixes="dyn">
<xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
<xsl:template match="/">
<xsl:for-each select="dyn:evaluate($pattern)">
<xsl:value-of select="dyn:evaluate($value)"/>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
使用 xsltproc --stringparam pattern //element/@attribute --stringparam value . arbitrary-xpath.xslt filename.xml
运行 .
13 回答
您可能也对xsh感兴趣 . 它具有交互模式,您可以使用该文档执行任何操作:
你应该尝试这些工具:
xmlstarlet
:可以编辑,选择,转换...默认情况下不安装xpath1xmllint
:默认情况下经常安装libxml2
,xpath1(检查我的wrapper是否有换行符分隔输出xpath
:通过perl的模块XML::XPath
,xpath1安装xml_grep
:通过perl的模块安装XML::Twig
,xpath1(限制xpath用法)xidel
:xpath3saxon-lint
:我自己的项目,@Michael Kay的Saxon-HE Java库包装器,xpath3xmllint
附带libxml2-utils
(可用作--shell
开关的交互式shell)xmlstarlet
是xmlstarlet
.xpath
附带perl的模块XML::Xpathxml_grep
附带perl的模块XML::Twigxidel
是xidel
saxon-lint
使用SaxonHE 9.6,XPath 3.x(复古兼容性)例如:
xmlstarlet page
man xmllint
xpath page
xml_grep
xidel
saxon-lint
.
你也可以试试我的Xidel . 它不在存储库的包中,但您可以从网页下载它(它没有依赖项) .
它具有此任务的简单语法:
它是支持XPath 2的这些工具中罕见的一种 .
一个很可能已安装在系统上的软件包已经
python-lxml
. 如果是这样,这可以不安装任何额外的包:Saxon不仅可以用于XPath 2.0,还可以用于XQuery 1.0和(商业版)3.0 . 它不是Linux软件包,而是jar文件 . 语法(您可以轻松地将其包装在一个简单的脚本中)是
在我查询maven pom.xml文件时,我遇到了这个问题 . 但是我有以下限制:
必须跨平台运行 .
必须存在于所有主要Linux发行版上,无需安装任何其他模块
必须处理复杂的xml文件,例如maven pom.xml文件
简单的语法
我已经尝试了上述许多方法而没有成功:
python lxml.etree不是标准python发行版的一部分
xml.etree但是没有很好地处理复杂的maven pom.xml文件,没有深入挖掘
python xml.etree由于未知原因无法处理maven pom.xml文件
xmllint也不起作用,核心转储经常在ubuntu 12.04 "xmllint: using libxml version 20708"
我遇到的唯一解决方案是稳定,简短并且在许多平台上工作,而且成熟的是在ruby中内置的rexml lib:
是什么让我发现这个是以下文章:
Ruby/XML, XSLT and XPath Tutorial
IBM: Ruby on Rails and XML
clacke’s answer很棒,但我认为只有你的源是格式良好的XML而不是普通的HTML才有效 .
因此,对于不一定格式良好的XML的普通Web内容HTML文档也要这样做:
而是使用html5lib(以确保您获得与Web浏览器相同的解析行为 - 因为像浏览器解析器一样,html5lib符合HTML规范中的解析要求) .
除了XML::XSH和XML::XSH2之外,还有一些
grep
类似的实用程序很糟糕App::xml_grep2和XML::Twig(其中包括xml_grep
而不是xml_grep2
) . 在为快速oneliner或Makefile
目标处理大量或大量XML文件时,这些非常有用 . 当你想要比$SHELL
和xmllint
xstlproc
提供更多的处理时,XML::Twig
特别适合使用perl
脚本方法 .应用程序名称中的编号方案表明"2"版本是更新/更高版本的基本相同的工具,可能需要更高版本的其他模块(或
perl
本身) .类似于Mike和clacke的答案,这里是python one-liner(使用python> = 2.5)从pom.xml文件获取构建版本,该文件解决了pom.xml文件通常没有dtd或默认命名空间,所以不要在libxml中显示格式正确:
在Mac和Linux上测试过,不需要安装任何额外的软件包 .
值得一提的是,nokogiri本身附带了一个命令行工具,该工具应该与
gem install nokogiri
一起安装 .你可能会找到this blog post useful .
我已经尝试了几个命令行XPath实用程序,当我意识到我花了太多时间谷歌搜索并弄清楚它们是如何工作的,所以我在Python中编写了最简单的XPath解析器,它完成了我需要的工作 .
如果XPath表达式求值为字符串,则下面的脚本显示字符串值;如果结果是节点,则显示整个XML子节点:
它使用
lxml
- 一个用C编写的快速XML解析器,它不包含在标准的python库中 . 用pip install lxml
安装它 . 在Linux / OSX上可能需要使用sudo
作为前缀 .用法:
lxml也可以接受URL作为输入:
在机箱节点下提取url属性,即
<enclosure url="http:...""..>)
:Google Chrome中的
Xpath
作为一个不相关的旁注:如果您想要针对网页的标记运行XPath表达式,那么您可以直接从Chrome devtools执行:右键单击Chrome中的页面>选择Inspect,然后在DevTools中console将您的XPath表达式粘贴为
$x("//spam/eggs")
.获取此页面上的所有作者:
由于这个项目显然是相当新的,查看https://github.com/jeffbr13/xq,似乎是
lxml
的包装,但这就是你真正需要的(并在其他答案中使用lxml发布临时解决方案)这是一个xmlstarlet用例,用于从嵌套元素elem1中提取数据,elem2从这种类型的XML中提取一行文本(还显示了如何处理命名空间):
输出将是
在此片段中,-m匹配嵌套的elem2,-v输出属性值(带表达式和相对寻址),-o文本文本,-n添加换行符:
如果elem1需要更多属性,可以这样做(也显示concat()函数):
注意(IMO不必要的)并发命名空间(ns,用-N声明),让我几乎放弃了xpath和xmlstarlet,并编写了一个快速的ad-hoc转换器 .