如何在所有标记都包含属性的XML中导航

如何在所有标记都包含属性的XML中导航,xml,regex,perl,xpath,Xml,Regex,Perl,Xpath,我的XML如下所示: <Servers type="Container"> <Server type="Category"> <HostName type="Property">dmitri-spB</HostName> <HostIPAddress type="Property">14.341.516.564</HostIPAddress> <Servers> <Server>

我的XML如下所示:

<Servers type="Container">
<Server type="Category">
    <HostName type="Property">dmitri-spB</HostName>
    <HostIPAddress type="Property">14.341.516.564</HostIPAddress>
<Servers>
<Server>
    <HostName>dmitri-spB</HostName>
    <HostIPAddress>14.341.516.564</HostIPAddress>
我试图通过在代码中使用整个标记来使用相同的方法,得到了一个“XPath错误:无效表达式”


所以,实际上有两个问题——当我不关心属性时如何导航和提取,以及当属性重要时如何导航和提取?也许这是一个XPath问题,但我无法将XPath文档与我要做的事情联系起来。建议

您可以完全忽略这些属性。它们不是您想象的“整个标记”的一部分,而是关于每个元素的附加信息

因此,请按原样使用代码,它应该可以工作

要根据元素的属性值选择元素,可以在谓词中使用XPath
@
表示法。因此,例如,要查找具有
Category
属性的
type
元素,您可以编写
Server[type=“Category”]

您可以使用
my$document=XML::LibXML->load_data(location=>'myfile')
一次性创建解析器对象并处理源数据
location
允许您传递文件名或URL,还可以指定
string
并传递包含XML的简单Perl字符串,或者
IO
并传递打开以供读取的文件句柄

也不需要在单独的循环中迭代路径的每个步骤。例如,您可以使用
Category
type
属性处理所有
Server
节点,如下所示

use strict;
use warnings;

use XML::LibXML;

my $doc = XML::LibXML->load_xml(location => "$source_dir/$xmlfiles");

for my $server ($doc->findnodes('/Servers/Server[@type = "Category"]')) {
  print ref $server, "\n";
}

什么XPath表达式给了您“XPath错误:无效表达式”?您是否尝试运行上面显示的示例代码?它可能很管用,是的。如果在XPath路径的每个元素中都包含“@”符号,则效果良好。没有它我就没有成功,但那很好。我使用了您关于返回所有节点并显式循环它们的提示。由于我的能力有限,显式循环对我来说更清晰,但你的方法迫使我更多地考虑实际返回的内容以及我如何访问内容——这对我的大脑来说是一个很好的锻炼。你已经移除了我的障碍,它正在按我需要的方式工作。上面,我的意思是写“而不是显式循环”,而不是显式循环。我肯定还纠正了其他一些小错误,因为正如你们所建议的,不管有没有@谓词,代码现在都可以正常工作。一切都很好。@KirkFleming:像您这样编写两个循环的问题是,外部循环只在一个
服务器上循环,因此只执行一次。循环的存在错误地暗示有几个节点需要迭代。
use strict;
use warnings;

use XML::LibXML;

my $doc = XML::LibXML->load_xml(location => "$source_dir/$xmlfiles");

for my $server ($doc->findnodes('/Servers/Server[@type = "Category"]')) {
  print ref $server, "\n";
}