如何在所有标记包含属性的位置导航XML

时间:2014-02-27 16:09:33

标签: 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>

在此数据中的大多数情况下,我不需要这些属性 - 或者至少我只在数据中看到过一个可能需要它的情况。无论如何......如果XML看起来像这样:

<Servers>
<Server>
    <HostName>dmitri-spB</HostName>
    <HostIPAddress>14.341.516.564</HostIPAddress>

......我会做类似的事情:

    my $parser = XML::LibXML -> new();
    my $tree = $parser -> parse_file ($source_dir."\\".$xmlfiles);
    for my $Servers ($tree->findnodes ('/Servers')) {
        foreach my $Server ($Servers->findnodes('./Server')) {
            $hostname = $Server->findvalue('HostName');
            $hostIP = $Server->findvalue('HostIPAddress');
        }
    }

我试图通过在代码中使用整个标记来使用相同的方法,并得到“XPath错误:表达式无效”。

所以,实际上有两个问题 - 当我不关心属性时如何导航和提取,以及如何在属性显着时执行此操作?也许这是一个XPath问题,但我根本无法将XPath文档与我正在尝试的内容联系起来。建议?

1 个答案:

答案 0 :(得分:2)

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

因此,请按原样使用您的代码,它应该可以正常工作。

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

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

也无需在单独的循环中迭代路径的每个步骤。例如,您可以像Server一样处理type属性为Category的所有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"; } 个节点

{{1}}