我正在搜索具有某些属性的xml文件。例如,包含以下模式的文件:
<param-value>
<name>Hosts</name>
<description>some description</description>
<value></value>
</param-value>
对于此类文件,我想解析另一个标记的值,例如:
<param-value>
<name>Roles</name>
<description>some description</description>
<value>asdf</value>
</param-value>
并打印出文件名和“asdf”。从命令行完成此操作的最简单方法是什么?
我想到的一种方法是使用带有-l选项的grep来过滤匹配的文件,然后使用xargs grep来提取角色的值。但是,grep不适用于多行正则表达式。我看到另一个问题表明它可以用-Pzo选项完成,但是没有任何运气让它在我的情况下工作。有更简单的方法吗?
答案 0 :(得分:13)
以下linux命令使用XPath访问XML文件中的指定值
for xml in `find . -name "*.xml"`
do
echo $xml `xmllint --xpath "/param-value/value/text()" $xml`| awk 'NF>1'
done
匹配XML文件的示例输出:
./test1.xml asdf
./test4.xml 1234
答案 1 :(得分:2)
对我来说最简单的方法是从命令行使用Saxon。
以下是使用XPath on the command line的示例。这与shell脚本相结合,可以完全满足您的要求。
答案 2 :(得分:1)
根据the answer to this question,XMLStarlet似乎非常适合这类事情。
答案 3 :(得分:1)
我使用基本的perl / awk功能(基本上是一个穷人对标签的解析)制定了几个解决方案。如果您看到只使用基本perl / awk功能的任何改进,请告诉我。我通过设置一个标志来避免处理多行正则表达式,我看到了一个特定的标签。有点笨拙但有效。
perl的:
perl -ne '$h = 1 if m/Host/; $r = 1 if m/Role/; if ($h && m/<value>/) { $h = 0; print "hosts: ", $_ =~ /<value>(.*)</, "\n"}; if ($r && m/<value>/) { $r = 0; print "\nrole: ", $_ =~ /<value>(.*)</, "\n" }'
AWK:
awk '/Host/ {h = 1} /Role/ {r = 1} h && /<value>/ {h = 0; match($0, "<value>(.*)<", a); print "hosts: " a[1]} r && /<value>/ {r = 0; match($0, "<value>(.*)<", a); print "\nrole: " a[1]}'
答案 4 :(得分:1)
$ xmlstarlet ed -u /param-value/name -v Roles -u /param-value/value -v asdf data.xml
<?xml version="1.0"?>
<param-value>
<name>Roles</name>
<description>some description</description>
<value>asdf</value>
</param-value>
答案 5 :(得分:0)
我原本希望更仔细地解决你的问题,但我已经没时间了,抱歉。
无论如何 - perl有一些非常好的模块用于阅读xml。
特别是,以下文章perl and xml on the command line可能很有用。
答案 6 :(得分:0)
我通常使用Perl的XML::XSH2。您可以在其中以交互方式处理XML文件,也可以编写脚本。该脚本将类似于(未经测试):
for my $file in { glob "*.xml" } {
open $file ;
my $param_value = //param-value[name="Hosts"] ;
if $param_value echo $file $value/value ;
}