2012-01-17 58 views
1

我使用Perl解析xml文件,并且所有内容似乎都很适用于一个问题。我有具有相同模式的文件,但他们从解析器返回不同类型的数据。下面是一个简化的例子:Perl,使用XML解析XML :: Simple和存在问题

<tests> 
     <test> 
      <data1>Hi</data1> 
      <data2>Hello</data2> 
     </test> 
     <test> 
      <data1>Hi2</data1> 
      <data2>Hello2</data2> 
     </test> 
    </tests> 

在转储中,该返回如下:(乘测试是两个散列阵列的注释)

$VAR1 = { 
      'test' => [ 
        { 
         'data2' => 'Hello', 
         'data1' => 'Hi' 
        }, 
        { 
         'data2' => 'Hello2', 
         'data1' => 'Hi2' 
        } 
        ] 
     }; 

现在,对于一组类似的数据的,但只有一个“测试”实体,像这样:

<tests> 
     <test> 
      <data1>Hi</data1> 
      <data2>Hello</data2> 
     </test> 
    </tests> 

这返回类似的数据,除了测试实体不再是一个数组,但奇异散列:

$VAR1 = { 
      'test' => { 
        'data2' => 'Hello', 
        'data1' => 'Hi' 
        } 
     }; 

我的两难处境是我的代码期望有一个数组,因为这是常态。但是,只有一个实体的机会很小,它会为该实体返回一个散列。我的问题是,我如何处理哈希实体,就像它是一个数组一样。或者测试它?

现在我的检索数组的代码是这样的:

foreach $test (@{$data->{'tests'}->{'test'}}) 
{ 
    do something with $test 
} 

但是随着散列,它提供了一个错误“不是一个数组引用”。我希望这是足够的细节!谢谢!!!

回答

6

或许替换形式的,即使ForceArray选项是你想要的吗?

ForceArray => [名称]

的“ForceArray”选项的这种替代(和优选的)形式 允许用户指定应该始终被 被迫进入一个数组表示元素名称的列表,而不是上面的“全部或全部” 方法。

也可以(自2.05版),包括编译的正则表达式 在列表中 - 匹配的模式 将被迫阵列的任何元素名称。如果列表只包含一个正则表达式,则 则不必将其包含在arrayref中。例如:

ForceArray => QR/_list $/

所以我可能会尝试:

ForceArray => ['test'] 
+1

谢谢!这对我来说非常合适! – srowley 2012-01-17 02:27:49

0

您需要通过使用哈希符号来取消引用哈希值:'%'。

1

XML::Simple

ForceArray => 1 

此选项应该被设置为“1”以强制嵌套元素是表示为阵列 仅存在一个

+0

我想这一点,但随后将所有散列设置为数组。还有什么我可以做的吗? – srowley 2012-01-17 01:38:35

0

虽然看起来你可以得到的XML解析器的行为更加一致,这也将让您的代码在变体输出上工作并不困难。

Perl内置函数“ref”可用于确定引用引用的对象的类型。

你原来的代码都

foreach $test (@{$data->{'tests'}->{'test'}}) 
{ 
    do something with $test 
} 

(而不是写$数据 - > { '测试'} - > { '试验'},我会倾向于使用更紧凑$$数据{}测试{}测试,所以我会用在我的例子。)

我们可以检查引用类型,并用它来所有的可能性推到一个数组,所以

foreach $test (
    (ref($$data{tests}{test}) eq 'ARRAY') ? (
     @{$$data{tests}{test}} 
    ) : (
     $$data{tests}{test} 
    ) 
) 
{ 
    do something with $test 
}