我有一个XML文件,它描述了我可以在UDP通道上交换的数据结构。 例如: 这是我的输入XML文件,描述了我的数据结构。
<ds>
<uint32 name='a'/>
<uint32 name='b'/>
<string name='c'/>
<int16 name='d'/>
<uint32 name='e'/>
</ds>
使用perl的XML解析此XML文件:简单,允许我生成以下哈希
$VAR1 = {
'uint32' => {
'e' => {},
'a' => {},
'b' => {}
},
'int16' => {
'name' => 'd'
},
'string' => {
'name' => 'c'
}
};
如您所见,解析后我无法弄清楚字段'e'相对于数据结构起点的相对位置。
我想找出每个元素的偏移量。
我尝试搜索perl XML解析器,它允许我按顺序解析XML文件,类似于'getnexttag()'类型的功能,但找不到任何。
以编程方式执行此操作的最佳方法是什么?如果不是perl,那么哪种其他语言最适合做这项工作?
答案 0 :(得分:3)
你需要使用带有适当回调的流式解析器,当涉及到更大的数据集时,这也将提高解析速度(并且如果正确完成,可以减少内存消耗),这是一个很好的/ 很棒的事情。
我建议您使用XML::SAX
,可在以下链接中找到该模块的介绍:
为start_element
提供回调,这样您就可以一次读取每个元素的值。
是的,我已经拥有了!的; - )强>
下面的代码片段将解析所提供的数据OP并打印每个元素的名称,以及属性键/值。
理解起来应该很容易,但如果您有任何问题,请随时将其添加为评论,我会更新此帖子并提供更详细的信息。
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";
}
输出
found element: ds
found element: uint32
'name' = 'a'
found element: uint32
'name' = 'b'
found element: string
'name' = 'c'
found element: int16
'name' = 'd'
found element: uint32
'name' = 'e'
是的,有很多可供选择。阅读以下列表并选择适合您特定问题的列表:
我还建议阅读以下有关XML解析的常见问题解答。它将提出使用树解析器(例如XML :: Parser :: Simple)或流解析器的Pro和Con:
答案 1 :(得分:2)
Perl肯定是可能的。
以下是XML::LibXML
的示例:
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"/>"
答案 2 :(得分:1)
以下是使用XML::Twig
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