【问题标题】:Perl, Parsing XML with XML::Simple and Having IssuesPerl,使用 XML::Simple 解析 XML 并存在问题
【发布时间】:2012-02-11 21:29:13
【问题描述】:

我在 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
}

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

【问题讨论】:

    标签: arrays perl hash xml-parsing xml-simple


    【解决方案1】:

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

    ForceArray => [名称]

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

    也可以(从 2.05 版开始)包含已编译的正则 列表中的表达式 - 与模式匹配的任何元素名称 将被强制数组。如果列表只包含一个正则表达式, 那么就没有必要将它包含在一个arrayref中。例如:

    ForceArray => qr/_list$/

    所以我可以试试:

    ForceArray => ['test']
    

    【讨论】:

      【解决方案2】:

      XML::Simple

      ForceArray => 1
      

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

      【讨论】:

      • 我试过这个,但是它把所有的散列设置为数组。还有什么我可以做的吗?
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        虽然您似乎可以让 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
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-10-09
          • 2013-10-14
          • 2013-02-01
          • 1970-01-01
          • 2011-02-27
          • 1970-01-01
          • 2011-10-11
          • 2014-10-11
          相关资源
          最近更新 更多