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

问题描述 投票:3回答:5

对于名为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",这是我想要避免的。

xml bash xpath
5个回答
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
投票
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上死机,并且在没有内存限制的情况下阻塞我的计算机。也可以看看:


0
投票

如果你真的想使用xpath并且只显示没有“name =”部分的属性值,那么这里对我有用:

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

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


0
投票

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

如果你坚持使用xmllint,唯一的方法是使用额外的文本处理。这是一种解析属性值的通用方法。它假定值不包含="字符。

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

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

第二个管道打印出=之后的内容

最后一个管道删除所有"


-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]#
© www.soinside.com 2019 - 2024. All rights reserved.