使用XML :: Twig对XML字符串进行基本解析

时间:2015-03-01 07:25:55

标签: xml perl xml-twig

我已经使用了XML :: Simple十多年了,它已经完成了我需要的一切,而且我几乎不再触及Perl了。虽然现在我需要解析一个简单的XML字符串:获取所有作为根的子元素的元素,并为每个元素获取它们的元素类型,属性和内容(我不在乎是否有任何嵌套元素,只是以字符串形式阅读内容是完美的)。我可以用XML实现所有这些:简单除了我还需要保持顺序,当有多种元素类型时,Simple不能这样做。

我刚刚安装了Twig,它看起来非常强大,我希望这是一个快速的脚本。在此之后我不太可能再次使用Twig,这是Twig可以轻松做到的事情吗?

3 个答案:

答案 0 :(得分:3)

在一个简单的层面 - XML::Twig - 遍历孩子:

#!/usr/bin/perl

use strict;
use warnings; 

use XML::Twig;

my $twig = XML::Twig -> new -> parsefile ( 'myxml.xml' );

foreach my $element ( $twig -> root -> children ) { 
    print $element -> text; #element content. 
}

提取元素属性可以通过以下方式完成:

 $element -> att('attributename');

或者您可以使用atts获取哈希引用:

 my $attributes = $element -> atts();
 foreach my $key ( keys %$attributes ) {
     print "$key => ", $attributes -> {$key}, "\n";
 }

我特别喜欢的是,对于XML,您需要处理很长的相似元素列表,您可以定义一个处理程序 - 它们分别称为处理程序解析器遇到的时间并交给XML的子集。

sub process_book {
     my ( $twig, $book )  = @_;
     print $book -> first_child ('title'); 
     $twig -> purge; #discard anything we've already seen. 
}

my $twig = XML::Twig -> new ( twig_handlers => { 'book' => \&process_book } ); 
$twig -> parsefile ( 'books.xml' ); 

示例XML:

<XML>
   <BOOK>
       <title>Elements of style</title>
       <author>Strunk and White</author>
   </BOOK>
</XML>

答案 1 :(得分:1)

下面的代码应该为您提供足够的信息以便开始使用。

一些注意事项:

  • 使用parsefile代替parse
  • 解析文件
  • 您也可以使用'level(1)'代替'/root/*'
  • 如果你想要process_elt和{{1成为全局变量,你可以写$atts,并使用twig和元素作为参数调用处理程序
  • $strings位用于释放刚处理过的元素所使用的内存,如果文件太大而无法放入内存中,则非常有用,否则您不需要使用它< / LI>
  • $atts$strings,它只是检查输出,您可以使用任何其他方式执行此操作('/root/*' => \&process_elt$t->purge,打印......)

以下是代码:

DDP

答案 2 :(得分:0)

我更喜欢XML::LibXML。它的Reader不需要将整个结构保存在内存中,因此它可以处理大文件:

#!/usr/bin/perl
use warnings;
use strict;

use XML::LibXML::Reader;

my $reader = 'XML::LibXML::Reader'->new( location => 'file.xml' );
while ($reader->read) {
    if (1 == $reader->depth
        and XML_READER_TYPE_ELEMENT == $reader->nodeType
       ) {
        my @info = ($reader->name);
        my $inner = $reader->readInnerXml;
        for my $idx (0 .. $reader->attributeCount - 1) {
            $reader->moveToAttributeNo($idx);
            push @info, $reader->name . '=' . $reader->value;
        }
        push @info, $inner;
        print "@info\n";
    }
}