【问题标题】:perl XML::Simple for repeated elementsperl XML::Simple 用于重复元素
【发布时间】:2013-10-01 07:51:32
【问题描述】:

我有以下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 的代码,我卡住了这些代码。尝试使用 dumper 查看数据结构,但我不知道如何进行。我已经在我的解析脚本的其余部分使用了简单的 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.

【问题讨论】:

  • 我对 XML::Simple 的规则是,当您第一次对如何使用它有疑问时,请停止使用它并转向更好的 XML 系统。 :)
  • @briandfoy 我希望我之前知道,实际上我想到了在堆栈溢出中使用简单的 xml。人们鼓励我使用它

标签: perl xml-simple


【解决方案1】:

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

无论如何,您的问题是您想访问 productsubstrate 子哈希中的 id 字段 - 但它们不存在于 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'
         }
     }
 },

相反,键是数字,每个值都是包含name 的散列。另一个reaction 具有完全不同的结构,因此将为两者编写特殊情况代码。这就是为什么不应该使用 XML::Simple 的原因 - 输出是不可预测的。

输入XML::LibXML。这并不特别,但它实现了 标准 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

【讨论】:

  • 感谢您的回答,但我已经在其余的解析脚本中使用了简单的 XML(这部分是我整个脚本的一小部分),我现在无法更改
  • @user1876128 XML::Simple 文档列出了改变生成的数据结构创建方式的各种选项——您也许能够找到一些创建统一结构的组合。我没有这方面的专业知识,并且更喜欢使用 XPath 遍历 XML——注意我的最终代码有多短。从长远来看,您不会后悔将 XML::Simple 抛在后面。
猜你喜欢
  • 1970-01-01
  • 2012-01-15
  • 2019-11-17
  • 1970-01-01
  • 2021-10-18
  • 2013-01-10
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多