使用XML :: LibXML

时间:2018-06-18 07:15:45

标签: xml perl

我有以下XML文件

<root>
  <test name="test1">
    <node name="node1">
    </node>
    <child type="" line="321" name="">
      <grandChild name="WM">
        ....
      </grandChild>
    </child>
  </test>
  <test name="test2">
    <node name="node2">
    </node>
    <child type="" line="123" name="">
      <grandChild name="WM">
        ....
      </grandChild>
    </child>
  </test>
</root>

如果条件成立,我想访问某些节点,但是我无法获得<grandChild>个子元素。

我的Perl代码如下

my $xml = XML::LibXML::XPathContext->new();

my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs(sr => 'http://www.froglogic.com/XML2');

my $tree         = $parser->parse_file($xmlFile);
my $nodes        = $xml->findnodes("//sr:root/sr:test[$attribute]", $tree);
my $childTagName = 'child';

foreach my $node ( $nodes->get_nodelist ) {

    my $childNodes = $node->getChildNodes();

    foreach my $childNode ( $childNodes->get_nodelist ) {

        if ( $childNode->getName() eq $childTagName ) {

            my $newresults = $childNode->findnodes('//child');
        }
    }
}

当然,删除它的主要部分是为了简化我的问题。

我应该提到$attribute是测试名称(test1,test2,....)。

请您告诉我为什么我无法在$newresults中找到孙子,当我打印到命令控制台时,它总是空的。

1 个答案:

答案 0 :(得分:3)

您的代码无法运行。 $attribute来自哪里?此外,您不会在XML中显示sr命名空间的定义,因此很难猜出问题是什么,但我的猜测是child也属于命名空间。如果是这种情况,您也必须使用它的前缀,并使用XPath上下文来搜索它。另外,使用XPath指定条件而不是迭代子节点:

#! /usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

use XML::LibXML;

my $tree = 'XML::LibXML'->load_xml(IO => *DATA);
my $xpc = 'XML::LibXML::XPathContext'->new($tree);
$xpc->registerNs(sr => 'http://sr');

my $attribute = '@name';
my $test_nodes = $xpc->findnodes("/sr:root/sr:test[$attribute]");
for my $test_node (@$test_nodes) {
    for my $child_node ($xpc->findnodes('sr:child', $test_node)) {
        my $newresults = $xpc->findnodes('sr:grandChild', $child_node);
        say join ' ',
            $test_node->{name},
            $child_node->{line},
            $_->{name}
            for @$newresults;
    }
}

__DATA__
<root xmlns='http://sr'>
    <test name="test1">
        <node name="node1">

        </node>
        <child type="" line="321" name="">
            <grandChild name="WM">
                ....
            </grandChild>
        </child>

    </test>
    <test name="test2">
        <node name="node2">

        </node>
        <child type="" line="123" name="">
            <grandChild name="WM">
                ....
            </grandChild>
        </child>
    </test>
</root>