Perl XML в Ха sh отбросить последний xml узел и принудительно вызвать массив - PullRequest
0 голосов
/ 24 января 2020

У меня есть XML, который мне нужно преобразовать в ха sh в указанном формате c, который требует, чтобы некоторые узлы были в массиве. Я пробовал XML :: Simple, но не могу избавиться от одного xml уровня узла.

#!/usr/bin/perl
use Data::Dumper::Simple;
use XML::Simple;

use warnings;
use strict;

my $xml = <<'XML';
<?xml version="1.0"?>
<release id="9999" status="Accepted">
  <images>
    <image height="511" type="primary" uri="" uri150="" width="600"/>
    <image height="519" type="secondary" uri="" uri150="" width="600"/>
    <image height="521" type="secondary" uri="" uri150="" width="600"/>
    <image height="217" type="secondary" uri="" uri150="" width="500"/>
    <image height="597" type="secondary" uri="" uri150="" width="600"/>
    <image height="89" type="secondary" uri="" uri150="" width="600"/>
  </images>
  <artists>
    <artist>
      <id>45</id>
      <name>Aphex Twin</name>
      <anv/>
      <join/>
      <role/>
      <tracks/>
    </artist>
  </artists>
</release>
XML

my $xml_hash = XMLin($xml, ForceArray => qr{image}x );
print Dumper $xml_hash; 

Желаемый вывод

       'images' => [
                     {
                       'type' => 'primary',
                       'width' => 600,
                       'resource_url' => '',
                       'uri150' => '',
                       'height' => 511,
                       'uri' => ''
                     },
                     {
                       'width' => 600,
                       'type' => 'secondary',
                       'resource_url' => '',
                       'uri150' => '',
                       'uri' => '',
                       'height' => 519
                     }, etc...

Что я получаю с моим примером кода:

$xml_hash = {
              'images' => [
                            {
                              'image' => [
                                           {
                                             'uri150' => '',
                                             'type' => 'primary',
                                             'uri' => '',
                                             'height' => '511',
                                             'width' => '600'
                                           },
                                           {
                                             'type' => 'secondary',
                                             'uri150' => '',
                                             'uri' => '',
                                             'height' => '519',
                                             'width' => '600'
                                           },
                                           {
                                             'uri' => '',
                                             'height' => '521',
                                             'width' => '600',
                                             'type' => 'secondary',
                                             'uri150' => ''
                                           },
                              etc...

Как мне избавиться от

'image' => [

и иметь

'images' => [

содержать все хэши?

Спасибо; George

Ответы [ 2 ]

2 голосов
/ 24 января 2020

XML :: Simple препятствует его собственному использованию.

Вот как вы можете получить массив хэшей, используя XML :: Lib XML:

use XML::LibXML;

my $dom = XML::LibXML->load_xml(string => $xml);

my @images = map +{
    map { $_->name => $_->value } $_->findnodes('@*')
}, $dom->findnodes('/release/images/image');
2 голосов
/ 24 января 2020

Любая попытка представить весь документ XML как структуру данных Perl будет сопряжена с крайними случаями и неудобным дизайном по природе двух форматов. Существует много опций для анализа и обхода XML способом, подходящим для формата, например XML :: Lib XML и XML :: Twig . Вот как я мог бы подойти к этому с Mojo :: DOM (который использует CSS селекторы для обхода):

use strict;
use warnings;
use Mojo::DOM;
use Mojo::Util 'dumper';

my $xml = <<'XML';
<?xml version="1.0"?>
<release id="9999" status="Accepted">
  <images>
    <image height="511" type="primary" uri="" uri150="" width="600"/>
    <image height="519" type="secondary" uri="" uri150="" width="600"/>
    <image height="521" type="secondary" uri="" uri150="" width="600"/>
    <image height="217" type="secondary" uri="" uri150="" width="500"/>
    <image height="597" type="secondary" uri="" uri150="" width="600"/>
    <image height="89" type="secondary" uri="" uri150="" width="600"/>
  </images>
  <artists>
    <artist>
      <id>45</id>
      <name>Aphex Twin</name>
      <anv/>
      <join/>
      <role/>
      <tracks/>
    </artist>
  </artists>
</release>
XML

my $dom = Mojo::DOM->new->xml(1)->parse($xml);
my @images = $dom->find('release#9999 > images > image')->map('attr')->each;
print dumper \@images;

Вывод:

[
  {
    "height" => 511,
    "type" => "primary",
    "uri" => "",
    "uri150" => "",
    "width" => 600
  },
  {
    "height" => 519,
    "type" => "secondary",
    "uri" => "",
    "uri150" => "",
    "width" => 600
  },
  {
    "height" => 521,
    "type" => "secondary",
    "uri" => "",
    "uri150" => "",
    "width" => 600
  },
  {
    "height" => 217,
    "type" => "secondary",
    "uri" => "",
    "uri150" => "",
    "width" => 500
  },
  {
    "height" => 597,
    "type" => "secondary",
    "uri" => "",
    "uri150" => "",
    "width" => 600
  },
  {
    "height" => 89,
    "type" => "secondary",
    "uri" => "",
    "uri150" => "",
    "width" => 600
  }
]
...