2010-09-22 73 views
2

考虑到XML :: Simple是唯一可以使用的模块,所以我被困在从XML中检索值中。结构低于:如何使用Perl的XML :: Simple从XML文件提取值?

<testxml> 
    <dev> 
     <A> 
      <tables> 
       <datatables> 
        <table>a1</table> 
        <table>a2</table> 
        <table>a3</table> 
       </datatables> 
       <propertytables> 
        <table>A1</table> 
        <table>A2</table> 
       </propertytables> 
      </tables> 
     </A> 
     <B> 
      <tables> 
       <datatables> 
        <table>b1</table> 
        <table>b2</table> 
       </datatables> 
       <propertytables> 
        <table>B1</table> 
        <table>B2</table> 
       </propertytables> 
      </tables> 
     </B> 
    </dev> 
</testxml> 

的XMLOut是:

<opt> 
    <dev name="A"> 
    <tables name="datatables"> 
     <table>a1</table> 
     <table>a2</table> 
     <table>a3</table> 
    </tables> 
    <tables name="propertytables"> 
     <table>A1</table> 
     <table>A2</table> 
    </tables> 
    </dev> 
    <dev name="B"> 
    <tables name="datatables"> 
     <table>b1</table> 
     <table>b2</table> 
    </tables> 
    <tables name="propertytables"> 
     <table>B1</table> 
     <table>B2</table> 
    </tables> 
    </dev> 
</opt> 

如何检索表阵列说这个条件:
dev名称= “B” 和表名= “propertytables” #输出B1,B2

+3

为什么它是唯一可以使用的模块? – Ether 2010-09-22 16:05:34

+0

我的老板说在这种情况下XPath或任何其他模块只是一个矫枉过正的情况:( – Abhishek 2010-09-22 17:39:20

+0

因此,你的老板宁愿读整个文件并创建一个大的内存数据结构?:) – 2010-09-22 20:19:25

回答

3

XML :: Simple是这个角色唯一使用的模块。对于这样的事情,我会用一些XPath来使用XML :: LibXML。

但是,如果您想使用XML :: Simple,我发现最好的方法是使用Data :: Dumper转储XML :: Simple构建的数据结构,并使用该转储找出最佳方式走结构。就你而言,这很简单。

#!/usr/bin/perl 

use strict; 
use warnings; 

use XML::Simple; 
use Data::Dumper; 

my $xml = do { local $/; <DATA> }; 

my $doc = XMLin($xml); 

# print Dumper $doc; 

my $dev = 'B'; 
my $table = 'propertytables'; 

foreach (@{$doc->{dev}{$dev}{tables}{$table}{table}}) { 
    print "$_\n"; 
} 

__END__ 
<opt> 
    <dev name="A"> 
    <tables name="datatables"> 
     <table>a1</table> 
     <table>a2</table> 
     <table>a3</table> 
    </tables> 
    <tables name="propertytables"> 
     <table>A1</table> 
     <table>A2</table> 
    </tables> 
    </dev> 
    <dev name="B"> 
    <tables name="datatables"> 
     <table>b1</table> 
     <table>b2</table> 
    </tables> 
    <tables name="propertytables"> 
     <table>B1</table> 
     <table>B2</table> 
    </tables> 
    </dev> 
</opt> 
+0

如何在单个实体上执行强制阵列?我正在尝试这样的事情:对于前者,如果对于dev“B”,如果“propertytables”具有单个表格,则将其视为标量。 my $ config = XMLin('./ test.xml',forcearray => ['{dev} - > {B} - > {tables} - > {propertytables} - > {table}']);但我想这是一个错误的方式。 – Abhishek 2010-09-23 11:06:54

+0

哦,我知道了。我只需要指定forcearray => [qw(table)] – Abhishek 2010-09-23 16:20:10

2
$ref->{dev}{B}{tables}{propertytables}{table} 

将是参考和

@{ $ref->{dev}{B}{tables}{propertytables}{table} } 

将成为列表。

但真正做

my $ref = XMLin($some_source); 
use Smart::Comments; 
### $ref 

# ... OR ... 

use Data::Dumper; 
print Data::Dumper->Dump([ $ref ], [ '*ref' ]); 

检查结构看寻路会是怎样。

相关问题