2013-10-01 54 views
1

我有以下XML代码Perl的XML ::简单的重复元素

<?xml version="1.0"?> 
<!DOCTYPE pathway SYSTEM "http://www.kegg.jp/kegg/xml/KGML_v0.7.1_.dtd"> 
<!-- Creation date: Aug 26, 2013 10:02:03 +0900 (GMT+09:00) --> 
<pathway name="path:ko01200" > 
    <reaction id="14" name="rn:R01845" type="irreversible"> 
     <substrate id="108" name="cpd:C00447"/> 
     <product id="109" name="cpd:C05382"/> 
    </reaction> 
    <reaction id="15" name="rn:R01641" type="reversible"> 
     <substrate id="109" name="cpd:C05382"/> 
     <substrate id="104" name="cpd:C00118"/> 
     <product id="110" name="cpd:C00117"/> 
     <product id="112" name="cpd:C00231"/> 
    </reaction> 
</pathway> 

我要打印的基板ID和产品ID与下面的代码,我坚持对具有一个以上的ID。试图使用倾卸器来查看数据结构,但我不知道如何继续。我已经使用XML简单了我的解析脚本的其余部分(这部分是我的整个脚本的一小部分),我无法改变,现在

use strict; 
use warnings; 
use XML::Simple; 
use Data::Dumper; 
my $xml=new XML::Simple; 
my $data=$xml->XMLin("test.xml",KeyAttr => ['id']); 
print Dumper($data); 
    foreach my $reaction (sort keys %{$data->{reaction}}) { 
     print $data->{reaction}->{$reaction}->{substrate}->{id}."\n"; 
     print $data->{reaction}->{$reaction}->{product}->{id}."\n"; 

} 

这里是输出

$VAR1 = { 
     'name' => 'path:ko01200', 
     'reaction' => { 
        '15' => { 
          'substrate' => { 
              '104' => { 
                'name' => 'cpd:C00118' 
                }, 
              '109' => { 
                'name' => 'cpd:C05382' 
                } 
             }, 
          'name' => 'rn:R01641', 
          'type' => 'reversible', 
          'product' => { 
             '112' => { 
                'name' => 'cpd:C00231' 
               }, 
             '110' => { 
                'name' => 'cpd:C00117' 
               } 
             } 
          }, 
        '14' => { 
          'substrate' => { 
              'name' => 'cpd:C00447', 
              'id' => '108' 
             }, 
          'name' => 'rn:R01845', 
          'type' => 'irreversible', 
          'product' => { 
             'name' => 'cpd:C05382', 
             'id' => '109' 
             } 
          } 
        } 
    }; 
108 
109 
Use of uninitialized value in concatenation (.) or string at line 12. 
Use of uninitialized value in concatenation (.) or string at line 13. 
+0

我对XML ::简单的规则是你第一次有关于如何使用它的问题,停止使用,并移动到一个更好的XML系统。 :) –

+0

@briandfoy我希望我知道在这之前,其实我打算使用XML的简单这里堆overflow.people鼓励我用它 – user1876128

回答

3

首先,不要使用XML :: Simple。这是很难预测什么确切的数据结构,它将从一点XML的产生,以及它自己的文档中提到it is deprecated

无论如何,你的问题是,你要访问的productsubstrate subhashes的id场 - 但他们不会在reaction subhashes

'15' => { 
    'substrate' => { 
     '104' => { 
      'name' => 'cpd:C00118' 
     }, 
     '109' => { 
      'name' => 'cpd:C05382' 
     } 
    }, 
    'name' => 'rn:R01641', 
    'type' => 'reversible', 
    'product' => { 
     '112' => { 
      'name' => 'cpd:C00231' 
     }, 
     '110' => { 
      'name' => 'cpd:C00117' 
     } 
    } 
}, 

而不是一个存在,关键是数字,并且每个值都是包含name的散列值。另一个reaction有一个完全不同的结构,所以特殊情况下的代码将被写入两者。这就是为什么XML::Simple不应该使用 - 输出只是不可预测的。

输入XML::LibXML。这是不平凡的,但它implememts 标准API像DOM和XPath遍历XML文档。

use XML::LibXML; 
use feature 'say'; # assuming perl 5.010 

my $doc = XML::LibXML->load_xml(file => "test.xml") or die; 

for my $reaction_item ($doc->findnodes('//reaction/product | //reaction/substrate')) { 
    say $reaction_item->getAttribute('id'); 
} 

输出:

108 
109 
109 
104 
110 
112 
+0

谢谢您的回答的想法,但我已经使用XML简单的其余部分我解析脚本(这部分是我的整个脚本的一小部分),我无法改变,现在 – user1876128

+0

@ user1876128的XML ::简单的文档列出了改变是如何创建的结果数据结构的各种选项 - 你可以找到一些创建一个统一的结构。我没有这方面的专业知识,并且更喜欢使用XPath遍历XML - 注意我的最终代码有多短。从长远来看,您不会后悔离开XML :: Simple。 – amon