1

我正在用 Perl 解析 xml 文件,并且在一个问题上似乎一切都很好。我有具有相同架构的文件,但它们从解析器返回不同类型的数据。这是一个简化的示例:

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

在转储中,这将返回以下内容:(注意 test 是一个包含两个哈希的数组)

$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
}

但是使用散列,它会给出一个错误“不是数组引用”。我希望这是足够的细节!谢谢!!!

4

4 回答 4

6

也许选项的替代形式ForceArray是您想要的?

ForceArray => [名称]

'ForceArray' 选项的这种替代(和首选)形式允许您指定应始终强制转换为数组表示的元素名称列表,而不是上面的“全有或全无”方法。

也可以(从 2.05 版开始)在列表中包含已编译的正则表达式 - 任何与模式匹配的元素名称都将被强制为数组。如果列表仅包含一个正则表达式,则无需将其包含在 arrayref 中。例如:

ForceArray => qr/_list$/

所以我可能会尝试:

ForceArray => ['test']
于 2012-01-17T02:07:53.573 回答
1

XML::简单

ForceArray => 1

此选项应设置为 '1' 以强制嵌套元素表示为数组,即使只有一个

于 2012-01-17T01:14:58.323 回答
0

您需要使用散列符号取消引用散列:'%'。

于 2012-01-17T01:11:23.590 回答
0

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

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

你的原始代码去

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

(而不是写 $data->{'tests'}->{'test'},我倾向于使用更紧凑的 $$data{tests}{test} ,所以我将在我的示例中使用它。)

我们可以检查引用类型并使用它将所有可能性推入一个数组,所以

foreach $test (
    (ref($$data{tests}{test}) eq 'ARRAY') ? (
        @{$$data{tests}{test}}
    ) : (
        $$data{tests}{test}
    )
)
{
    do something with $test
}
于 2012-01-21T22:47:28.157 回答