如何使用XML::LibXML::Reader获取属性名称列表?

How to get list of attribute names with XML::LibXML::Reader?

提问人:w.k 提问时间:7/4/2019 更新时间:7/6/2019 访问量:365

问:

我尝试处理属性中可能有许多数据的XML节点。我想获取属性列表,但无法弄清楚,如何使用 XML::LibXML::Reader 实现它?

有了,我可以得到属性的计数,并迭代它们,但这只给了我值,而不是属性名称。attributeCountgetAttributeNo

我希望看到类似的东西,但是没有这样的属性方法getAttributes

示例代码:

use strict; use warnings; use 5.010;

use XML::LibXML::Reader;

my $reader = XML::LibXML::Reader->new(IO => \*DATA)
    or die "Cannot read from \\*DATA\n";

while ($reader->read) {
  processNode($reader);
}

sub processNode {
  my $reader = shift;


  if ( $reader->name eq 'item' ) {
    my $count = $reader->attributeCount; 
    say "item has $count attributes";

    for (my $i = 0; $i < $count; $i++) {
      say $reader->getAttributeNo( $i );
    }

    # this would my desired way to access attributes:
    # for my $attr ( $reader->getAttributes ) { 
    #   say "$attr ". $reader->getAttribute( $attr );
    # }
  }
}

__DATA__
<items>
  <item code="PK7000346" name="Lucky" class="MUU" purchaseprice="0.2983" object="UPK" hasvariants="0" ts="2019-06-19T20:04:47"/>
</items>

所需的输出是哈希或名称/值对,如下所示:

code PK7000346
name Lucky
class MUU
purchaseprice 0.2983
object UPK
hasvariants 0
ts 2019-06-19T20:04:47
xml perl xml 解析

评论


答:

2赞 choroba 7/5/2019 #1

使用节点的浅拷贝:

if ($reader->name eq 'item'
    && $reader->nodeType == XML_READER_TYPE_ELEMENT
) {
    for my $attr ($reader->copyCurrentNode(0)->getAttributes) {
        say join '=', $attr->name, $attr->value;
    }
}

它似乎没有记录在 XML::LibXML::Element 和 XML::LibXML:Node 中。您还可以使用 ,或将该元素视为哈希引用并询问其键:getAttributesattributes

    my $item = $reader->copyCurrentNode(0);
    for my $attr (keys %$item) {
        say join '=', $attr, $item->{$attr};
    }

评论

0赞 w.k 7/5/2019
你能详细说明一下,这种方法从何而来吗?复制的节点是什么对象?getAttributes
0赞 choroba 7/6/2019
XML::LibXML::元素。
3赞 Håkon Hægland 7/5/2019 #2

下面是使用 moveToAttribute 的另一种方法:

sub processNode {
  my $reader = shift;

  if ( $reader->name eq 'item' ) {
      my $count = $reader->attributeCount;
      for (my $i = 0; $i < $count; $i++) {
          $reader->moveToAttributeNo( $i );
          say $reader->name, " = ", $reader->value;
      }
   }
}

评论

0赞 w.k 7/5/2019
不错的方法,我没有想到要与.$reader->namemoveToAttribute