Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用xmllint/xpath解析不同元素上几个属性的值?_Xml_Bash_Xpath - Fatal编程技术网

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

如何使用xmllint/xpath解析不同元素上几个属性的值?,xml,bash,xpath,Xml,Bash,Xpath,对于一个名为configurations.xml的给定xml文件,我想提取每个conf元素的值,并将其存储在一个变量中供以后使用 <configurations> <conf name="bob"/> <conf name="alice"/> <conf name="ted"/> <conf name="carol"/> </configurations> 我有xpath和xmllint可用。//conf/

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

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

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

可以使用
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]#
[root@myservertmp]#cat/tmp/test.xml
[root@myservertmp]#awk-F \“{print$2}'/tmp/test.xml | grep-v'^$”
上下快速移动
爱丽丝
特德
颂歌
[root@myserver[tmp]#

我不知道如何仅用
xmllint
就能实现您想要实现的目标

由于安装了
xpath
,因此也安装了Perl的
XML::xpath

#!/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
!/bin/bash
名称=()
而IFS=read-r-d''n;do
名称+=(“$n”)
完成<如果您真的想使用
xpath
并且只显示属性值而不显示“name=”部分,那么下面是对我有效的方法:

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

xmlstarlet sel -t -m '//configurations/conf' -v '@name' -n a.xml
因为
xmllint
似乎没有能力工作。介绍得不错

测试版本:xmlstarlet版本1.5.0,Ubuntu 14.04

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


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

如果您一直使用
xmllint
,唯一的方法就是使用额外的文本处理。下面是一种解析属性值的通用方法。它假定值不包含
=
字符

xmllint --xpath //conf/@name | 
tr ' ' '\n' | awk -F= '{print $2}' | sed 's/"//g'
第一条管道将空间转换为换行线

第二个管道打印
=


最后一个管道删除了所有

我需要它是一个更具体的匹配,而不仅仅是从开始的所有内容”。XML文档中还有其他我不想匹配的元素。因此,在这种情况下,您只需要
conf name
?我主要考虑的是在纯bash中是否可能。但我想这最终没有意义。这在libxml版本20901 Ubuntu 14.04上对我不起作用:它只在使用
string()
时打印第一个值。你是对的,我只测试了一个子节点。我会保持答案不变,也许它对0.1%有这个问题的人有用。
xmllint --xpath //conf/@name | 
tr ' ' '\n' | awk -F= '{print $2}' | sed 's/"//g'