Perl   发布时间:2022-04-07  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了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 ),'-' 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.

问:在以后的版本中是否存在问题,或者我做错了?

解决方法

documentation of XPath 1.0

(强调我自己).所以你的电话

$node->findnodes( '//Identifier' )

忽略上下文节点$node并在文档中的任何位置搜索所有标识符元素

要获取上下文节点的所有标识符后代,您必须添加一个点,像这样

$node->findnodes('.//Identifier');

但是由于$node始终是Response元素,而Identifier是Response的直接子节点,您可以直接写入

$node->findnodes('Identifier');

你似乎已经有一点点把握了.我知道你已经把代码剪掉了,但你真的需要单独的包吗?可以通过审慎地应用XPath来做到这一点.

最明显的变化是,您不需要循环遍历所有孩子 – 您可以选择您感兴趣的孩子.

这个重构的代码可能值得一读

use Strict;
use warnings;

use XML::LibXML;

my $parser = XML::LibXML->new;
my $doc    = $parser->parse_fh(*DATA);

for my $item ( $doc->findnodes('//Item') ) {

    print "\n";

    my ($id) = $item->findvalue('Id');
    printf "Item Id: %s\n",$item->findvalue('Id');

    my @messages = $item->findnodes('message');

    for my $message (@messages) {
        my ($responsE) = $message->findnodes('Response');
        printf "Response Identifier: %s\n",$response->findvalue('Identifier');
    }
}

__DATA__
<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>

产量

Item Id: 8b9a
Response Identifier: 55D

Item Id: 5350
Response Identifier: 56D

大佬总结

以上是大佬教程为你收集整理的Perl XML :: LibXML $node-> findnodes($xpath)查找不应该的节点全部内容,希望文章能够帮你解决Perl XML :: LibXML $node-> findnodes($xpath)查找不应该的节点所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。