是否有一个针对Ubuntu和/或CentOS的包,它有一个命令行工具,可以执行像foo //element@attribute filename.xml或foo //element@attribute < filename.xml这样的XPath一行程序,并逐行返回结果?
我正在寻找一些东西,这将允许我只是apt-get安装foo或yum安装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");
}
xpath从XML:: xpath返回太多噪音,——NODE——和attribute = "value"。
来自XML::Twig的xml_grep不能处理不返回元素的表达式,因此不能在没有进一步处理的情况下用于提取属性值。
编辑:
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(需要XSLT处理器中的dyn:evaluate支持):
<?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。
下面是一个xmlstarlet用例,从这种类型的XML中从嵌套元素elem1、elem2到一行文本中提取数据(还展示了如何处理名称空间):
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<mydoctype xmlns="http://xml-namespace-uri" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xml-namespace-uri http://xsd-uri" format="20171221A" date="2018-05-15">
<elem1 time="0.586" length="10.586">
<elem2 value="cue-in" type="outro" />
</elem1>
</mydoctype>
输出将是
0.586 10.586 cue-in outro
在这个代码片段中,-m匹配嵌套的elem2, -v输出属性值(带有表达式和相对寻址),-o文字文本,-n添加换行符:
xml sel -N ns="http://xml-namespace-uri" -t -m '//ns:elem1/ns:elem2' \
-v ../@time -o " " -v '../@time + ../@length' -o " " -v @value -o " " -v @type -n file.xml
如果elem1需要更多的属性,可以这样做(也显示concat()函数):
xml sel -N ns="http://xml-namespace-uri" -t -m '//ns:elem1/ns:elem2/..' \
-v 'concat(@time, " ", @time + @length, " ", ns:elem2/@value, " ", ns:elem2/@type)' -n file.xml
请注意名称空间的复杂性(ns,用-N声明),这让我几乎放弃了xpath和xmlstarlet,而编写了一个快速的临时转换器。
在我搜索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库:
ruby -r rexml/document -e 'include REXML;
puts XPath.first(Document.new($stdin), "/project/version/text()")' < pom.xml
启发我找到这篇文章的是下面的文章:
Ruby/XML, XSLT和XPath教程
IBM: Ruby on Rails和XML
下面是一个xmlstarlet用例,从这种类型的XML中从嵌套元素elem1、elem2到一行文本中提取数据(还展示了如何处理名称空间):
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<mydoctype xmlns="http://xml-namespace-uri" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xml-namespace-uri http://xsd-uri" format="20171221A" date="2018-05-15">
<elem1 time="0.586" length="10.586">
<elem2 value="cue-in" type="outro" />
</elem1>
</mydoctype>
输出将是
0.586 10.586 cue-in outro
在这个代码片段中,-m匹配嵌套的elem2, -v输出属性值(带有表达式和相对寻址),-o文字文本,-n添加换行符:
xml sel -N ns="http://xml-namespace-uri" -t -m '//ns:elem1/ns:elem2' \
-v ../@time -o " " -v '../@time + ../@length' -o " " -v @value -o " " -v @type -n file.xml
如果elem1需要更多的属性,可以这样做(也显示concat()函数):
xml sel -N ns="http://xml-namespace-uri" -t -m '//ns:elem1/ns:elem2/..' \
-v 'concat(@time, " ", @time + @length, " ", ns:elem2/@value, " ", ns:elem2/@type)' -n file.xml
请注意名称空间的复杂性(ns,用-N声明),这让我几乎放弃了xpath和xmlstarlet,而编写了一个快速的临时转换器。