如何使用xmllint / xpath解析不同元素上的几个属性的值?

时间:2014-11-09 00:46:19

标签: xml bash xpath

对于名为 configurations.xml 的给定xml文件,我想提取每个conf元素的,并将其存储在变量中以供日后使用使用

<configurations>
  <conf name="bob"/>
  <conf name="alice"/>
  <conf name="ted"/>
  <conf name="carol"/>
</configurations>

预期输出为:

bob
ailce
ted
carol

我有 xpath xmllint 可用。 //conf/@name的xpath获取节点,但输出为name="bob",这是我试图避免的。

5 个答案:

答案 0 :(得分:2)

xmlstarlet sel -t -m '//configurations/conf' -v '@name' -n a.xml

因为xmllint似乎没有能力而工作。好介绍here

测试:xmlstarlet版本1.5.0,Ubuntu 14.04。

但是对大文件失败:ulimit -Sv 500000(限制为500Mb)在1.2Gb XML上死机,并且在没有内存限制的情况下阻塞我的计算机。另见:

答案 1 :(得分:1)

我不知道如何通过xmllint实现您想要实现的目标。

由于您安装了xpath,因此您也拥有Perl XML::XPath。那么一点点Perl:

#!/usr/bin/perl

use XML::Path;

my $xp=XML::XPath->new(filename => 'configurations.xml');

my $nodeset=$xp->find('//conf/@name');
foreach my $node ($nodeset->get_nodelist) {
    print $node->getNodeValue,"\0";
}

将输出您想要的内容,以零字符分隔。

以单行风格:

perl -mXML::XPath -e 'foreach $n (XML::XPath->new(filename => "configurations.xml")->find("//conf/\@name")->get_nodelist) { print $n->getNodeValue,"\0"; }'

要在例如Bash数组中检索它们:

#!/bin/bash

names=()
while IFS= read -r -d '' n; do
    names+=( "$n" )
done < <(
    perl -mXML::XPath -e 'foreach $n (XML::XPath->new(filename => "configurations.xml")->find("//conf/\@name")->get_nodelist) { print $n->getNodeValue,"\0" }'
)
# See what's in your array:
display -p names

请注意,此时您可以选择转到Perl并完全删除Bash来解决问题。

答案 2 :(得分:0)

如果确实想要使用xpath 来仅显示没有“name =”部分的属性值,那么这里对我有用: / p>

xpath configurations.xml 'string(//conf/@name)' 2>/dev/null

用简单的英语,将您的XPath查询包装在string()中,并通过在结尾处添加xpath来抑制2>/dev/null的详细输出。

答案 3 :(得分:0)

我到处寻找这个看似简单的答案。似乎xmllint无法从多个节点打印属性值。您可以使用string(//conf/@name),但即使有多个匹配的节点,也只会打印一个值。

如果您遇到xmllint,唯一的方法是使用其他文字处理。这是一种解析属性值的通用方法。它假定值不包含="个字符。

xmllint --xpath //conf/@name | 
tr ' ' '\n' | awk -F= '{print $2}' | sed 's/"//g'

第一个管道将空格转换为换行符。

第二个管道打印=

之后的内容

最后一个管道删除所有"

答案 4 :(得分:-1)

您可以使用awk命令完成此操作。

[root@myserver tmp]# cat /tmp/test.xml
<configurations>
  <conf name="bob"/>
  <conf name="alice"/>
  <conf name="ted"/>
  <conf name="carol"/>
</configurations>
[root@myserver tmp]# awk -F \" '{print $2}' /tmp/test.xml |grep -v '^$'
bob
alice
ted
carol
[root@myserver tmp]#