获取元素属性的值

时间:2017-11-02 21:40:49

标签: xml perl

我试图获取某些XML数据中任何name元素的section属性的值。

my $some_att = $fileLocation->findnodes("//section[/@name]");

有人可以解释这种语法有什么问题吗?

请注意,此处的变量$fileLocation会打开我正在使用的XML的文件位置。

2 个答案:

答案 0 :(得分:2)

我假设您正在使用 XML::LibXML

解释您正在使用的工具(库,语言,操作系统)以及您所看到的错误行为非常重要。

您的"请注意,此处的变量$fileLocation会打开我正在使用的XML的文件位置" 令人不安。它没有多大意义(它是一个变量,不能打开任何东西),你选择的标识符暗示它是XML文件的路径。 但是为了能够在其上调用findnodes,它必须是一个DOM对象,更具体地说是XML::LibXML::Node的实例或子类。

您的代码看起来应该更像

use XML::LibXML;

my $xml_file = '/path/to/file.xml';

my $dom = XML::LibXML->load_xml(
    location => $xml_file
);

my @sections = $dom->findnodes('//section');

for my $section ( @sections ) {
    next unless $section->hasAttribute('name');
    say $section->getAttribute('name');
}

标量上下文中findnodes方法的结果不是单一的 XML::LibXML::Node 对象,而是一个 XML::LibXML::NodeList, 这是重载的,所以它类似于对数组的引用

你不会说出你得到的错误,但是你的"有人可以解释这种语法有什么问题吗?" 我想这个模块拒绝你的XPath表达式?

在本声明中

my $some_att = $fileLocation->findnodes("//section[/@name]")

问题在于谓词 [/@name],如果它是正确的,会过滤section元素,只包含那些name属性的元素。因为它是一个谓词,所以它不需要轴,所以应该写成//section[@name]

但是,这只会找到具有section属性的所有name元素。要选择属性本身,您需要编写//section/@name,类似这样的

 my $section_names = $fileLocation->findnodes('//section/@name')

然后你会有一个XML::LibXML::NodeList  XML::LibXML::Attr 对象,您可以使用类似于

的内容提取其值列表
my @section_names = map { $_->value } $section_names->get_nodelist

您可能更愿意使用XPath表达式section从所有//section元素的列表开始。这会给你一个集合  XML::LibXML::Element 对象,您可以使用name

从中提取$elem->getAttribute('name')元素

请记住,您可以使用数组而不是 如果您愿意,可以通过在XML::LibXML::NodeList调用中选择列表上下文而不是标量上下文来findnodes个对象,如 暴徒回答

答案 1 :(得分:1)

我不知道Perl,但我认为findnodes()旨在评估XPath表达式。你的表达

"//section[/@name]"

在语法上是正确的,但在语义上,这是无稽之谈。 (顺便说一句,我想知道人们是怎么想出这样的东西的?我只能想象你正在从你不理解的例子中剪切和粘贴,而不回到规范看看它实际意味着什么。) / p>

这里有两个主要错误。

  • 首先,方括号代表一个谓词或过滤器:你是 选择满足某些条件的部分,但是你的散文 要求(a)表示你想要检索名称(而不是部分),和 (b)没有说明过滤名单。
  • 其次,/@name无效。表达式开头的“/”选择根(文档)节点,而@name选择属性。文档节点没有属性,因此不会选择任何内容。

您想要的表达式是//section/@name。 (一旦你将它们带入Perl-space,你对这些名称所做的就是我所知道的。)