perl:如何按顺序解析xml文件

perl:如何按顺序解析xml文件,perl,xml-parsing,Perl,Xml Parsing,我有一个XML文件,它描述了我可以在UDP通道上交换的数据结构。 例如: 这是我的输入XML文件,描述了我的数据结构 <ds> <uint32 name='a'/> <uint32 name='b'/> <string name='c'/> <int16 name='d'/> <uint32 name='e'/> </ds> 如您所见,在解析之后,我无法确定字段“e”相对于数据结构开头的相对位置 &l

我有一个XML文件,它描述了我可以在UDP通道上交换的数据结构。 例如: 这是我的输入XML文件,描述了我的数据结构

<ds>
 <uint32 name='a'/>
 <uint32 name='b'/>
 <string name='c'/>
 <int16 name='d'/>
 <uint32 name='e'/>
</ds>
如您所见,在解析之后,我无法确定字段“e”相对于数据结构开头的相对位置

<ds>
 <uint32 name='a'/>
 <uint32 name='b'/>
 <string name='c'/>
 <int16 name='d'/>
 <uint32 name='e'/>
</ds>
我想找出这些元素的偏移量

我尝试搜索PerlXML解析器,它允许我按顺序解析XML文件,类似于“getnexttag()”之类的功能,但找不到任何


以编程方式执行此操作的最佳方法是什么?如果不是perl,那么哪种语言最适合做这项工作?

您需要使用具有适当回调的流式解析器,这也将提高解析速度(如果正确完成,并减少内存消耗),这是一件非常好的事情

我建议您使用
XML::SAX
,以下链接提供了对该模块的介绍:

start\u元素
提供回调,这样您可以一次读取每个元素的值


你能给我举个简单的例子吗? 是的,我已经有了<强>;-)

下面的代码片段将解析OP提供的数据,并打印每个元素的名称以及属性key/value

这应该很容易理解,但如果你有任何问题,请随意添加它们作为评论,我会更新这篇文章更详细的信息

use warnings;
use strict;

use XML::SAX;

my $parser = XML::SAX::ParserFactory->parser(
  Handler => ExampleHandler->new
);

$parser->parse_string (<<EOT
<ds>
  <uint32 name='a'/>
  <uint32 name='b'/>
  <string name='c'/>
  <int16 name='d'/>
  <uint32 name='e'/>
</ds>
EOT
);

# # # # # # # # # # # # # # # # # # # # # # # #

package ExampleHandler;

use base ('XML::SAX::Base');

sub start_element {
  my ($self, $el) = @_;

  print "found element: ", $el->{Name}, "\n";

  for my $attr (values %{$el->{Attributes}}) {
    print "  '", $attr->{Name}, "' = '", $attr->{Value}, "'\n";
  }

  print "\n";
}

我对XML::SAX不满意,还有其他可用的模块吗? 是的,有很多选择。阅读以下列表,并选择适合您的特定问题的列表:


不同的解析方法有什么区别? 我还建议阅读以下有关XML解析的常见问题解答。它将介绍使用树解析器(如XML::parser::Simple)或流式解析器的利弊:


    • 使用Perl肯定是可行的

      下面是一个例子:

      使用严格;
      使用警告;
      使用特征“说”;
      使用XML::LibXML;
      my$xml=xml::LibXML->load_xml(位置=>'test.xml');
      my($dsNode)=$xml->findnodes('/ds');
      my@kids=$dsNode->nonBlankChildNodes;#此数组的索引将
      #给出偏移量
      我的$first_kid=shift@kids;#干掉第一个孩子
      说$first_kid->toString;#""
      我的$second=$first_kid->nextNonBlankSibling();
      my$third=$second->nextNonBlankSibling();
      说$third->toString;#""
      
      下面是一个使用

      这将产生:

      tag uint32 : name = a
      tag uint32 : name = b
      tag string : name = c
      tag int16 : name = d
      tag uint32 : name = e
      

      非常感谢你给出如此清晰的答案。这很有帮助。
      use strict;
      use warnings;
      use feature 'say';
      use XML::LibXML;
      
      my $xml = XML::LibXML->load_xml( location => 'test.xml' );
      
      my ( $dsNode ) = $xml->findnodes( '/ds' );
      
      my @kids = $dsNode->nonBlankChildNodes;     # The indices of this array will
                                                  # give the offset
      
      my $first_kid = shift @kids;                # Pull off the first kid
      say $first_kid->toString;                   # "<uint32 name='a'/>"
      
      my $second = $first_kid->nextNonBlankSibling();     
      my $third  = $second->nextNonBlankSibling();
      
      say $third->toString;                       # "<string name="c"/>"
      
      use XML::Twig;
      
      XML::Twig->new( twig_handlers => { 'ds/*' => \&each_child } )
               ->parse( $your_xml_data );
      
      sub each_child {
          my ($twig, $child) = @_;
          printf "tag %s : name = %s\n", $child->name, $child->{att}->{name};
      }
      
      tag uint32 : name = a
      tag uint32 : name = b
      tag string : name = c
      tag int16 : name = d
      tag uint32 : name = e