Perl XML ::LibXML $node ->findnodes ($xpath )находит узлы, которые не должны

Вот некоторый код, с которым у меня проблемы, я обрабатываю некоторый XML и в методе в классе OO я извлекаю элемент из каждого из нескольких узлов, которые повторяются в документе. В поддереве должен быть только один такой элемент для каждого узла, но мой код получает все элементы, как если бы он работал с документом в целом.

Поскольку я ожидал получить только один элемент, я использую только нулевой элемент массива, это приводит к тому, что моя функция выводит неправильное значение (, и оно одинаково для всех элементов в документе )

. Вот некоторый упрощенный код, иллюстрирующий проблему

$ cat t4.pl
#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;

my $xml = <<EndXML;
<Envelope>
  <Body>
    <Reply>
      <List>
        <Item>
          <Id>8b9a</Id>
          <Message>
            <Response>
              <Identifier>55D</Identifier>
            </Response>
          </Message>
        </Item>
        <Item>
          <Id>5350</Id>
          <Message>
            <Response>
              <Identifier>56D</Identifier>
            </Response>
          </Message>
        </Item>
      </List>
    </Reply>
  </Body>
</Envelope>
EndXML

my $foo = Foo->new();

my $parser = XML::LibXML->new();
my $doc    = $parser->parse_string( $xml );
my @list   = $doc->getElementsByTagName( 'Item' );

for my $item ( @list ) {

    my $id = get( $item, 'Id' );
    my @messages = $item->getElementsByLocalName( 'Message' );

    for my $message ( @messages ) {

        my @children = $message->getChildNodes();

        for my $child ( @children ) {

            my $name = $child->nodeName;

            if ( $name eq 'Response' ) {
                print "child is a Response\n";
                $foo->do( $child, $id );
            }
            elsif ( $name eq 'text' ) {

                # ignore whitespace between elements
            }
            else {
                print "child name is '$name'\n";
            }
        }    # child
    }    # Message
}    # Item

#..............................................

sub get {
    my ( $node, $name ) = @_;

    my $value   = "(Element $name not found)";
    my @targets = $node->getElementsByTagName( $name );

    if ( @targets ) {
        my $target = $targets[0];
        $value = $target->textContent;
    }

    return $value;
}

#..............................................

package Foo;

sub new {
    my $self = {};
    bless $self;
    return $self;
}

sub do {
    my $self = shift;
    my ( $node, $id ) = @_;

    print '-' x 70, "\n", ' ' x 12, $node->toString( 1 ), "\n", '-' x 70, "\n";

    my @identifiers = $node->findnodes( '//Identifier' );
    print "do() found ", scalar @identifiers, " Identifiers\n";

    print "$id, ", $identifiers[0]->textContent, "\n\n";
}

Вот результат

$ perl t4.pl
child is a Response
----------------------------------------------------------------------
            <Response>
              <Identifier>55D</Identifier>
            </Response>
----------------------------------------------------------------------
do() found 2 Identifiers
8b9a, 55D

child is a Response
----------------------------------------------------------------------
            <Response>
              <Identifier>56D</Identifier>
            </Response>
----------------------------------------------------------------------
do() found 2 Identifiers
5350, 55D

Я ожидал

do() found 1 Identifiers

Я ожидал, что последняя строка будет

5350, 56D

Я использую старую версию XML ::LibXML из-за проблем с платформой.

В :Проблема существует в более поздних версиях или я что-то не так делаю?

11
задан Borodin 19 August 2015 в 13:52
поделиться