【发布时间】:2013-01-08 11:33:03
【问题描述】:
我想使用 XML::DOM 模块解析一个简单的 XML 文档以进行哈希处理。
<?xml version ="1.0"?>
<Select>
<book>
<prop Name = "prop1" Title = "title1" />
<prop Name = "prop2" Title = "title2" />
</book>
<fruit>
<prop Name = "prop3" Title = "title3" />
<prop Name = "prop4" Title = "title4" />
</fruit>
</Select>
预期的输出是-
$VAR1 = {
Select => {
book => {
prop => [
{ Name => "prop1", Title => "title1" },
{ Name => "prop2", Title => "title2" },
],
},
fruit => {
prop => [
{ Name => "prop3", Title => "title3" },
{ Name => "prop4", Title => "title4" },
],
},
},
}
我写的代码是:
use strict;
use XML::DOM;
use Data::Dumper;
my @stack;
my %hash;
push @stack,\%hash;
my $parser = new XML::DOM::Parser;
my $doc = $parser -> parsefile('demo.xml');
my $root = $doc->getDocumentElement();
my $rootnode = $root->getTagName;
################################################################
foreach my $node ($doc->getElementsByTagName($rootnode)){
push @stack,$stack[$#stack]->{$rootnode};
my @childnode = $node->getChildNodes();
foreach my $child(@childnode){
if($child->isElementNode){
my $childname = $child->getNodeName();
pop(@stack);
push @stack,$stack[$#stack]->{$rootnode} = {$childname,{}};
my @childnodes2 = $child->getChildNodes();
foreach my $subchild(@childnodes2){
if($subchild->isElementNode){
my $subchildname = $subchild->getNodeName();
my $name = $subchild->getAttributes->getNamedItem('Name')->getNodeValue;
my $title = $subchild->getAttributes->getNamedItem('Title')->getNodeValue;
pop(@stack);
push @stack,$stack[$#stack]->{$rootnode}->{$child->getNodeName()} = {$subchildname,{}}; #{} contains $name or $title
}
}
}
}
}
print Dumper(\%hash);
我认为,我无法正确推送和弹出数组。另外,我不想使用XML::Simple 和递归。
如何在 Perl 中做到这一点?
【问题讨论】:
-
您能否定义(用散文或伪代码),哪些规则会产生所需的输出?似乎您希望将属性视为子标签(
<foo bar="baz" />像<foo><bar>baz</bar></foo>),并且您希望将多个标签分组到一个数组中,如果它们是同名的兄弟姐妹。或者这个解析的目的只是为了填写prop字段,而结构的其余部分是不变的? -
另外请详细说明“XML::Simple and recursion”是什么意思,以及为什么要避免它。
-
@amon 是的,你是对的。所需的输出是在 XML::Simple 库的帮助下生成的。我只是想在 XML::Dom 的帮助下找到一种方法来做到这一点,而不使用任何递归函数,因为当 xml 变大时会受到内存限制
-
@user2001559 编写良好的递归解决方案不太可能比迭代解决方案消耗那么多的内存。以易于理解的递归方式编写代码通常很有用,然后将代码转换为迭代(请参阅 Chapter 5 of Higher Order Perl 以获得灵感和广泛讨论)。
-
@user2001559:我假设您在使用
XML::Simple时遇到了内存问题?问题很可能是由于将 整个 XML 树保存在内存中,因为递归解析使用的任何额外内存都相对无关紧要。当然,任何创建相同散列结构的解决方案都将使用相同数量的内存,因此您将不得不考虑像XML::Twig这样的流式 XML 解析器。不幸的是,任何其他依赖XML::Simple数据格式的软件都必须重写。
标签: perl hash xml-parsing xmldom