Perl, парсинг XML с помощью XML :: Простота и проблемы - PullRequest
1 голос
/ 17 января 2012

Я анализирую xml-файлы в Perl, и, кажется, все отлично работает с одной проблемой.У меня есть файлы с одинаковой схемой, но они возвращают разные типы данных из анализатора.Вот упрощенный пример:

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

Но с хэшем он выдает ошибку "Не ссылка на массив".Я надеюсь, что это достаточно подробно!Спасибо !!!

Ответы [ 4 ]

6 голосов
/ 17 января 2012

Возможно, вам нужна альтернативная форма опции ForceArray?

ForceArray => [names]

Эта альтернативная (и предпочтительная) форма опции 'ForceArray' позволяет указать список имен элементов, который всегда должен быть принудительно в представлении массива, а не «все или ничего» подход выше.

Также возможно (начиная с версии 2.05) включать скомпилированные регулярные выражения в списке - любые имена элементов, которые соответствуют шаблону будут вынуждены массивы. Если список содержит только одно регулярное выражение, тогда нет необходимости заключать его в arrayref. Например:

ForceArray => qr / _list $ /

Так что я мог бы попробовать:

ForceArray => ['test']
1 голос
/ 17 января 2012

XML :: Simple

ForceArray => 1

Эта опция должна быть установлена ​​в '1', чтобы заставить вложенные элементы быть представлены как массивы, даже если есть только один

0 голосов
/ 22 января 2012

Хотя кажется, что вы можете заставить синтаксический анализатор 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
}
0 голосов
/ 17 января 2012

Вам необходимо разыменовать хеш, используя хэш-символ: '%'.

...