如何将XML :: Simple与可能具有一个或多个子元素的XML标记一起使用?

时间:2009-03-18 23:35:09

标签: xml perl

昨天我问了一个问题How do I retrieve tag attributes with XML::Simple?我用来获取XML的链接:

http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=19273512(1)

http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=19291509(2)

我取得了很好的进展,并编写了以下代码,循环遍历标签并搜索我需要的代码。我正在寻找'ArticleIds'下的'doi'标签

   foreach $item_node (@{$dataSummary->{DocSum}->{Item}})
        {
                if($item_node->{Name} eq 'ArticleIds')
                {
                        foreach $item_node1 (@{$item_node->{Item}})
                        {
                                if ($item_node1->{Name} eq 'doi')
                                {
                                    $doi=  $item_node1->{content};  
                                    last;
                                }
                        }
                        last;

                }
        }

此代码基本上搜索ArticleIds标记,然后搜索其下的子标记以查找“doi”标记。

我遇到的问题是当ArticleIds下有多个子标签时(如(2)所示)那么一切正常。但是,当ArticleIds标签下只有一个子标签时(如(1)所示),则存在错误,程序就会停止。

我正在使用Simple Parser并使用翻斗车我得到了两个结果。 这是转储的一部分 链接(1)

{ 'Type' => 'List', 'Item' => { 'Type' => 'String', 'content' => '19273512', 'Name' => 'pubmed' }, 'Name' => 'ArticleIds' }

表示链接(2)

{ 'Type' => 'List', 'Item' => [ { 'Type' => 'String', 'content' => '909564644', 'Name' => 'pii' }, { 'Type' => 'String', 'content' => '10.1080/13506120802676914', 'Name' => 'doi' }, { 'Type' => 'String', 'content' => '19291509', 'Name' => 'pubmed' } ], 'Name' => 'ArticleIds' }

如你所见。当ArticleIds下有多个标签时,它被视为一个数组,因此方括号。

在这种情况下,有人会建议什么?

3 个答案:

答案 0 :(得分:6)

如果文件只有Item个元素之一,则该项目将显示在哈希中。如果有多个Item元素,那么它将显示为数组。您可以使用ForceArray选项强制某些标记始终包含列表。将它想要强制进入数组的所有属性名称的正则表达式传递给它,并且它将处理其余的。

XMLin( 'file.xml', 
       ForceArray => qr{Item}x );

哦,还要检查您正在使用的XML :: Simple版本。我认为早期版本只能使用ForceArray指定值的数组ref,或者它根本不起作用。如果它只适用于arrayref,您可以使用:

指定它
XMLin( 'file.xml', 
       ForceArray => [ 'Item' ] );

查看The XML::Simple CPAN documentation以查看可能对您有所帮助的更多选项。

就版本而言,如果你使用的是XML :: Simple,比如ActiveState发行版,它很可能已经过时了。尝试抓住一个更新的。

您还可以使用

检查它的类型
$item =~ /HASH/  # hash
$item =~ /ARRAY/ # array

或ref关键字(如您所发现的)

ref($item) eq 'HASH' 
ref($item) eq 'ARRAY'

答案 1 :(得分:4)

我认为你遇到的一个问题是你介于XML :: Simple之间没有给你足够的旋钮和拨号,但问题并不复杂,你写的东西更复杂。

在这种情况下,我会找到像XML::Twig这样的东西。它更受事件驱动,因此它可以遍历您的XML并在您需要时为您提供控制。一旦你得到你喜欢的元素,你可以随心所欲地做任何事情。

除了像Twig之类的东西,像XPath这样的各种东西也可以用同样的方式。它们的构建是为了深入研究XML的一部分,而不像XML :: Simple那样只为您提供数据结构。

答案 2 :(得分:1)

我在XML :: Simple上有旧版本所以我决定使用ref()函数并编写一些额外的代码行。

感谢您的帮助