2010-09-13 6 views
0

Я использую XML :: Simple для анализа XML-файла. Код приводится ниже с файлом XML,Как сохранить порядок значений в файле XML, когда я прочитал его с помощью XML :: Simple?

use Tie::IxHash; 

tie %$data, "Tie::IxHash"; 

use XML::Simple; 
use Data::Dumper; 

$xml = new XML::Simple; 
$data = $xml->XMLin("ship_order.xml"); 
print Dumper($data); 

XML файл, (ship_order.xml)

<?xml version="1.0" encoding="UTF-8" ?> 

<shipment> 
    <shiptoaddress> 
     <name>Prasad</name> 
     <address>AnnaNagar</address> 
    </shiptoaddress> 
    <items> 
     <quantity>5</quantity> 
     <price>100</price> 
    </items> 
    <items> 
     <quantity>6</quantity> 
     <price>50</price> 
    </items> 
    <num_of_items>2</num_of_items> 
</shipment> 

выход не подходит для того, даже если я использую модуль Tie :: IxHash.

Мой выход:

$VAR1 = { 
      'num_of_items' => '2', 
      'shiptoaddress' => { 
          'name' => 'Prasad', 
          'address' => 'AnnaNagar' 
          }, 
      'items' => [ 
        { 
         'quantity' => '5', 
         'price' => '100' 
        }, 
        { 
         'quantity' => '6', 
         'price' => '50' 
        } 
        ] 
     }; 
+1

см http://stackoverflow.com/questions/3650229/parsing-xml-file-in-perl-retain-sequence/3650297#3650297 –

+0

Когда XML :: Simple не сделайте именно то, что вы хотите, не используйте XML :: Simple. То есть, когда вы используете модуль * :: Simple, чтобы попытаться сделать что-то, чего он не делает, это уже не просто. –

ответ

6

Ах, но вы не используете Tie::IxHash. Или более точно, вы начинаете с помощью Tie::IxHash, а затем уничтожить его:

$data = $xml->XMLin("ship_order.xml"); 

Эта строка отбрасывает хэш ссылку, созданную и назначает один из вызова метода в $data.

Если вам небезразличен порядок элементов (и вам, вероятно, не придется этого делать, поскольку любой достойный формат XML будет включать атрибут, который сообщает вам заказ), вам нужно будет использовать парсер, который возвращает объект, а не структура данных. Объект будет знать порядок просмотра элементов и предоставить вам метод children, который возвращает их.

В качестве альтернативы, можно построить структуру данных, самостоятельно:

#!/usr/bin/perl 

use strict; 
use warnings; 

use XML::Twig; 

my $shipment; 
my $t = XML::Twig->new(
    twig_handlers => { 
     shiptoaddress => sub { 
      my ($t, $elt) = @_; 

      $shipment->{name} = $elt->first_child("name")->text; 
      $shipment->{address} = $elt->first_child("address")->text; 

      $t->purge; 
     }, 
     items => sub { 
      my ($t, $elt) = @_; 

      push @{$shipment->{items}}, { 
       quantity => $elt->first_child("quantity")->text, 
       price => $elt->first_child("price")->text, 
      }; 

      $t->purge; 
     }, 
    }, 
); 

$t->parse(join "", <DATA>); #FIXME: use parsefile later 

use Data::Dumper; 
print Dumper $shipment; 

__DATA__ 
<?xml version="1.0" encoding="UTF-8" ?> 

<shipment> 
    <shiptoaddress> 
     <name>Prasad</name> 
     <address>AnnaNagar</address> 
    </shiptoaddress> 
    <items> 
     <quantity>5</quantity> 
     <price>100</price> 
    </items> 
    <items> 
     <quantity>6</quantity> 
     <price>50</price> 
    </items> 
    <num_of_items>2</num_of_items> 
</shipment> 
+0

Ваша статья «любой достойный формат XML будет включать атрибут, который сообщает вам заказ», является поразительно неправильным. _XML сам по умолчанию будет упорядочен. –

3

Вы могли бы рассмотреть подклассы XML::Simple и overwritting необходимого метода, который создает хэш с Tie::IxHash.

Однако серьезно рассмотреть этот ответ, данный автор XML::Simple на CPAN forum в этой теме: how to preserve XML::Simple element order ...

Сохраняя порядок элемент не является и никогда не будет особенностью XML :: Simple. Для некоторых типов документов XML вы можете взломать его путем подкласса XML :: Simple и переопределения метода new_hashref() для предоставления hashref, привязанного к Tie :: IxHash. Это может решить дело ABC, но оно не решит дело ABA. Короткий ответ: если вам нужен порядок элементов, вам не следует использовать XML :: Simple. XML :: LibXML является отличной альтернативой, которая во многих случаях использование действительно не сложнее, чем XML :: Simple - как описано в работе [1]

А также то, что он положил в Своей code:

############################################################################## 
# Method: new_hashref() 
# 
# This is a hook routine for overriding in a sub-class. Some people believe 
# that using Tie::IxHash here will solve order-loss problems. 
# 

sub new_hashref { 
    my $self = shift; 

    return { @_ }; 
} 

[1] - Stepping up from XML::Simple to XML::LibXML

Смежные вопросы