3

我试图解析一个试图找到特定值的 XML 文件。这是 XML:

<?xml version="1.0"?>
<dump>
 <folder id="A0">
  <folder id="A1">
   <setting id="setting0">
    <sequence id="sequence0">
     <group name="info">
      <variable name="foo" value="15"/>
     </group>
    </sequence>
   </setting>
  </folder>
 </folder>
</dump>

数据::Dumper 生产

$VAR1 = {
          'folder' => {
                      'id' => 'A0',
                      'folder' => {
                                  'setting' => {
                                               'sequence' => {
                                                             'group' => {
                                                                        'variable' => {
                                                                                      'value' => '15',
                                                                                      'name' => 'foo'
                                                                                    },
                                                                        'name' => 'info'
                                                                      },
                                                             'id' => 'sequence0'
                                                           },
                                               'id' => 'setting0'
                                             },
                                  'id' => 'A1'
                                }
                    }
        };

我的目标是一份报告,上面写着:“foo 在 A0/A1/setting0/sequence0 处的值为 15”。请注意,我想使用ids 将“面包屑”路径指向foo.

目前我在这个示例 XML 中访问值“15”

use strict;
use warnings;
use XML::Simple;

my $xml = new XML::Simple;
my $data = $xml -> XMLin('test1.xml');
print $data -> {folder}{folder}{setting}{sequence}{group}{variable}{value};

(但是,如果有多个 ,这将不起作用<variable>,并且会有......但这不是我的主要挑战......)

问题是 XML 将包含不可预测的<folder>s 嵌套,我不知道如何找到 a<variable>存在的位置name="foo",因为我不知道它会有多深。将发生多个实例foo,但每个实例只有一个sequence

最后一点是我只能访问 XML::Simple 和 XML::Parser!没有 SAX/Twig/LibXML 等。并且 XML 数据文件的大小可能高达 100MB。

所有这些现在听起来都相当复杂,所以我将重申我的目标:遍历 XML 以找到<variable>存在的任何地方,name="foo"并报告它value在树中的位置。感谢您对此的任何帮助。


编辑:使用下面的mirod方法,这是有效的:

use strict;
use warnings;
use Twig;

my $twig = new XML::Twig( 
                twig_handlers =>
                   { 'variable[@name="foo"]' => \&variable,
                     group => sub { $_->purge; }  }
                        );
$twig->parsefile( "test.xml");

sub variable
  { my( $t, $var)= @_;
    my $location= join '/', grep { $_ } map { $_->id } reverse $var->ancestors;
    print $var->att( 'name'), " has value ", $var->att( 'value'), " at $location\n";
  }
4

1 回答 1

1

有什么理由不能安装 XML::Twig?它是一个纯 Perl 模块(它依赖于您已安装的 XML::Parser),因此您始终可以像在代码目录中Twig.pm一样从发行版中复制文件,然后瞧。myTwig.pmuse myTwig;

那么代码就很简单了:

#!/usr/bin/perl

use myTwig;


XML::Twig->new( twig_handlers => { 'variable[@name="foo"]' => \&variable,
                                   # next line if you need to reduce memory footprint
                                   group => sub { $_->purge; }, 
                                 }
         ->parse( \*DATA); # replace with parsefile( 'my.xml') for the real data

sub variable
  { my( $t, $var)= @_;
    my $location= join '/', grep { $_ } map { $_->id } reverse $var->ancestors;
    print $var->att( 'name'), " has value ", $var->att( 'value'), " at $location\n";
  }

__DATA__
<?xml version="1.0"?>
<dump>
 <folder id="A0">
  <folder id="A1">
   <setting id="setting0">
    <sequence id="sequence0">
     <group name="info">
      <variable name="foo" value="15"/>
     </group>
    </sequence>
   </setting>
  </folder>
 </folder>
</dump>
于 2012-07-06T15:42:15.323 回答