如何从shell执行XPath单行程序?

cla*_*cke 182 xml shell xpath cross-platform

对于Ubuntu和/或CentOS,是否有一个包,它有一个命令行工具,可以执行XPath单线程,foo //element@attribute filename.xml或者foo //element@attribute < filename.xml逐行返回结果?

我正在寻找一些可以让我只是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
Run Code Online (Sandbox Code Playgroud)

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");
}
Run Code Online (Sandbox Code Playgroud)

xpath来自XML :: XPath返回太多噪音,-- NODE --attribute = "value".

xml_grep 来自XML :: 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="'&#10;'"/>
    </xsl:for-each> 
  </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

运行xsltproc --stringparam pattern //element/@attribute --stringparam value . arbitrary-xpath.xslt filename.xml.

Gil*_*not 252

你应该尝试这些工具:

  • xmlstarlet :可以编辑,选择,转换...默认情况下不安装,xpath1
  • xmllint:经常默认使用libxml2xpath1 安装(检查我的包装器是否有换行符分隔输出
  • xpath:通过perl的模块XML::XPathxpath1 安装
  • xml_grep:通过perl的模块安装XML::Twig,xpath1(有限的xpath用法)
  • xidel:xpath3
  • saxon-lint :我自己的项目,包装在@Michael Kay的Saxon-HE Java库xpath3上

xmllint附带libxml2-utils(可用作--shell交换机的交互式外壳)

xmlstarletxmlstarlet.

xpath 附带perl的模块 XML::Xpath

xml_grep 附带perl的模块 XML::Twig

xidelxidel

saxon-lint使用SaxonHE 9.6,XPath 3.x(+复古兼容性)

例如:

xmllint --xpath '//element/@attribute' file.xml
xmlstarlet sel -t -v "//element/@attribute" file.xml
xpath -q -e '//element/@attribute' file.xml
xidel -se '//element/@attribute' file.xml
saxon-lint --xpath '//element/@attribute' file.xml
Run Code Online (Sandbox Code Playgroud)

.

  • 优秀!`xmlstarlet sel -T -t -m'// element/@ attribute'-v'.' -n filename.xml`完全符合我的要求! (6认同)
  • 注意:某些旧版本的`xmllint`不支持命令行参数`--xpath`,但大多数似乎支持`--shell`.略微更脏的输出,但在绑定中仍然有用. (4认同)
  • 注意:传闻 xmlstarlet 已被废弃,但现在又在积极开发中。 (2认同)

Ben*_*ela 18

你也可以尝试我的Xidel.它不在存储库的包中,但您可以从网页下载它(它没有依赖项).

它具有此任务的简单语法:

xidel filename.xml -e '//element/@attribute' 
Run Code Online (Sandbox Code Playgroud)

它是支持XPath 2的这些工具中罕见的一种.

  • Xidel看起来很酷,但你可能会提到你也是你推荐的这个工具的作者. (2认同)

cla*_*cke 15

一个很可能已安装在系统上的软件包已经存在python-lxml.如果是这样,可以在不安装任何额外包的情况下实现:

python -c "from lxml.etree import parse; from sys import stdin; print '\n'.join(parse(stdin).xpath('//element/@attribute'))"
Run Code Online (Sandbox Code Playgroud)

  • 这适用于`stdin`.这样就不需要在已经非常冗长的单行中包含`open()`和`close()`.要解析文件,只需从lxml.etree import parse运行`python -c";从sys import stdin运行; print'\n'.join(parse(stdin).xpath('// element/@ attribute'))"< my_file.xml`让你的shell处理文件查找,打开和关闭. (2认同)

Mic*_*Kay 10

Saxon不仅可以用于XPath 2.0,还可以用于XQuery 1.0和(商业版)3.0.它不是一个Linux包,而是一个jar文件.语法(您可以轻松地将其包装在一个简单的脚本中)是

java net.sf.saxon.Query -s:source.xml -qs://element/attribute
Run Code Online (Sandbox Code Playgroud)

  • 如果要查看此查询选择的属性节点的完整详细信息,请在命令行上使用-wrap选项.如果只需要属性的字符串值,请将/ string()添加到查询中. (3认同)
  • 如果您不想要XML标头,请添加选项!method = text. (2认同)

Mik*_*ike 10

在我查询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 -r rexml/document -e 'include REXML; 
     puts XPath.first(Document.new($stdin), "/project/version/text()")' < pom.xml
Run Code Online (Sandbox Code Playgroud)

是什么让我发现这个是以下文章:

  • 我想补充一点**以避免结果**,在Ruby命令中使用`puts`而不是`p`. (2认同)

cho*_*oba 5

您可能也对xsh感兴趣.它具有交互模式,您可以使用该文档执行任何操作:

open 1.xml ;
ls //element/@id ;
for //p[@class="first"] echo text() ;
Run Code Online (Sandbox Code Playgroud)

  • @cracke:不是,但可以通过 `cpan XML::XSH2` 从 CPAN 安装。 (2认同)

sid*_*ker 5

clacke 的回答很好,但我认为只有当您的源代码是格式良好的 XML 而不是普通的 HTML 时才有效。

因此,对普通 Web 内容(不一定是格式良好的 XML 的 HTML 文档)执行相同操作:

echo "<p>foo<div>bar</div><p>baz" | python -c "from sys import stdin; \
from lxml import html; \
print '\n'.join(html.tostring(node) for node in html.parse(stdin).xpath('//p'))"
Run Code Online (Sandbox Code Playgroud)

并改为使用 html5lib(以确保您获得与 Web 浏览器相同的解析行为——因为与浏览器解析器一样,html5lib 符合 HTML 规范中的解析要求)。

echo "<p>foo<div>bar</div><p>baz" | python -c "from sys import stdin; \
import html5lib; from lxml import html; \
doc = html5lib.parse(stdin, treebuilder='lxml', namespaceHTMLElements=False); \
print '\n'.join(html.tostring(node) for node in doc.xpath('//p'))
Run Code Online (Sandbox Code Playgroud)