2011-12-13 12 views
2

をXMLを抽出し、変換するために、私はフォルダ内のxmlファイルを持って、私はhash.My XMLファイルでxmlファイルとストアからいくつかの情報を抽出する必要があるが、このどのようにPerlのデータ構造に

<?xml version="1.0" encoding="UTF-8"?> 
<Servicemodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
<Service Id="478" Name="Pump Motor"> 
<Description>It delivers actual pump speed</Description> 
<ServiceCustomers> 
    <SW Service="SKRM" Path="/work/hr_service.xml"/> 
</ServiceCustomers> 
<ServiceSuppliers> 
    <HW Type="s" Nr="12" Service="1" Path="/work/hardware.xml"/> 
    <HW Type="v" Nr="2" Service="1" Path="/work/hardware.xml"/> 
    <HW Type="mt" Nr="1" Service="1" Path="/work/hardware.xml"/> 
</ServiceSuppliers> 
</Service> 
</Servicemodule> 

のように見えます私は、この情報をキーとしてサービスIDのようなハッシュに保存し、そのキーのハッシュ値の配列としてリーミング情報を保存します。サービス顧客およびサプライヤ要素のSW属性およびHW属性は、ハッシュキー(サービスID)の値の配列です。専門家のための簡単なタスクが、私はこの問題が私に苦しむように新しい学習者です。 私は上記のスクリプトを使用したいとしてハッシュを作成することはできませんよ、この

use strict; 
use warnings; 
use feature ':5.10'; 
use XML::Twig; 
use File::Find; 

my $num=0; 
my %combeh; 
my $dir="V:/Main/work"; 
find(\&wanted, $dir); 
sub wanted() { 
    if (-f and /(_service\.xml)$/) {# find all the files with a suffix of .xml           
my $tweak_server =sub{ 
       my @bhi;                      
    my ($twig, $root) [email protected]_;                      
    my $code=$root->first_child_text('Service Id');                     
    my $ser=$root->first_child('ServiceCustomers');                      
    my $ser_cnt=$root->first_child_text('SW'); 
    my $ser1=$root->first_child('ServiceSuppliers');                      
    my $ser1_cnt=$root->first_child_text('HW');                      
    if ($ser){                              
    push (@bhi, $ser->toString,$File::Find::name);                              
     $combeh{$code}=[@bhi]; 
     } 
     if ($ser1){                              
    push (@bhi, $ser1->toString,$File::Find::name);                              
     $combeh{$code}=[@bhi];   
      }; 
     my $roots = { Service => 1 }; 
    my $handlers = { 'Servicemodule/Service' => $tweak_server,                                            
         }; 
     my $twig = new XML::Twig(TwigRoots => $roots,                                                   
          TwigHandlers => $handlers,                                                   
           pretty_print => 'indented'                                            
           ); 
       $twig->parsefile($_);                      
          }      
         } 
       return (%combeh) ; 
       } 

のように試してみました。プットアウトこの が、これは

'478'=>[ 
      { 
      Description='It delivers actual pump speed' 
      } 
     { 
      Service='SKRM', 
      Path='/work/hr_service.xml' 
      } 
      { 
      Type='s'. 
      Nr='12', 
      Service='s', 
      path='/work/hardware.xml' 
      } 

      { 
      Type='v'. 
      Nr='2', 
      Service='s', 
      path='/work/hardware.xml' 
      } 
      { 
      Type='mt'. 
      Nr='1', 
      Service='1', 
      path='/work/hardware.xml' 
      } 
     ... 
      ... 
      .... 

この問題で私を助けてください好き必要が同じようハッシュで属性値や店舗を取得する方法をスクリプトで私を助けてください。

ありがとうございます。

私はあなたの提案の後、このようにご返信用

#!/usr/bin/perl 
use warnings; 
use strict; 
use XML::Simple; 
use Carp; 
use File::Find; 
use File::Spec::Functions qw(canonpath);  
use Data::Dumper; 

my @ARGV ="C:/Main/work";die "Need directories\n" unless @ARGV; 
find(
    sub { 
    return unless (/(_service\.xml)$/ and -f); 
    extract_information(); 
    return; 
    }, 
@ARGV 
); 

sub extract_information { 
     my $path= $_; 

my $xml=XMLin($path); 
    my $xml_services = $xml->{Service}; 
    my %services; 
    for my $xml_service (@$xml_services) { 

    my %service = (
     description  => $xml_service->{Description}, 
     name   => $xml_service->{Name}, 
     id    => $xml_service->{Id}, 
    ); 

    $service{sw} = _maybe_list($xml_service->{ServiceCustomers}{SW}); 
    $service{hw} = _maybe_list($xml_service->{ServiceSuppliers}{HW}); 
    $service{sw} = _maybe_list($xml_service->{ServiceSuppliers}{SW}); 
    $services{ $service{id} } = \%service; 
} 

print Dumper \%services; 

    } 
sub _maybe_list { 
my $maybe = shift; 
return ref $maybe eq 'ARRAY' ? $maybe : [$maybe]; 
} 

感謝を試してみました、私は、XML :: Simpleはに新しいですし、私はそのモジュールを学び、私はあなたのスクリプトを理解しています。しかし、私はあなたのコードを実行すると私は "配列のリファレンスではない"ループのline.Iで、これを克服するさまざまな方法で試したが、同じエラーが発生しました。そして、サービスサプライヤにSWとHW属性があることがあります。だからあなたのフォーマットと同じ行をもう1つ追加しました。私は1つの質問があります。「XMLに単一の要素がある場合、ラップされませんが、ServiceCustomersではXMLファイルに表示されているような属性を持つ要素が1つしかありません。何をすべきか?これらの問題を手伝ってくれますか?

このエラーで私を助けてください。

+0

「L7a」はどこから来たのですか?さまざまな 'Path'値がXMLでは設定されますが、出力では' ------ 'が設定されるのはなぜですか? – CanSpice

+0

インデントを修正し、空白行を1行おきに削除してください。 – ikegami

答えて

4

XMLファイルのサイズが大きすぎない場合は、XML::Simpleで簡単に変換できます。

XML :: Simpleのメリットは、XMLよりもPerlデータ構造を操作するほうがずっと便利だということです。

XMLファイル全体をメモリにロードする必要があるため、より多くのメモリを消費するという欠点があります。 XMLのケーシングにも敏感です。

use strict; 
use warnings; 

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

process_service_xml(shift); 

sub process_service_xml { 
    my $xml = XMLin(shift); 

    # Illustrating what you've got after XML::Simple processes it. 
    print "******* XML::Simple input ********\n"; 
    print Dumper $xml; 
    print "**********************************\n"; 

    # Pull out the Services 
    my $xml_services = $xml->{Service}; 

    # Iterate through each Service to transform them 
    my %services; 
    for my $xml_service (@$xml_services) { 
     # Pull out the basic information 
     my %service = (
      description  => $xml_service->{Description}, 
      name   => $xml_service->{Name}, 

      # Redundant with the key, but useful to keep all the data about the 
      # service in one place. 
      id    => $xml_service->{Id}, 
     ); 

     # Get SW and HW as their own attributes. 
     # If there's a single element in the XML it won't be wrapped in 
     # an array, so make sure each are a list. 
     $service{sw} = _maybe_list($xml_service->{ServiceCustomers}{SW}); 
     $service{hw} = _maybe_list($xml_service->{ServiceSuppliers}{HW}); 

     # Store the service in the larger hash, keyed by the ID. 
     $services{ $service{id} } = \%service; 
    } 

    # And here's what the information has been transformed into. 
    print "******* Services ********\n"; 
    print Dumper \%services; 
    print "*************************\n";  
} 

sub _maybe_list { 
    my $maybe = shift; 
    return ref $maybe eq 'ARRAY' ? $maybe : [$maybe]; 
} 
+0

あなたのスクリプトには小さな誤りや疑問がありますが、あなたが言ったように試みたので編集した質問を見ることができますか?小さなエラーが発生しています。この問題を手伝ってください。 – verendra

+0

私はあなたの助けを求めています。私を助けてください。 – verendra

+0

@verendra 1)XML文書にServiceエントリがないので、 "配列参照ではありません"が来ているので、 '$ xml_services'は空です。その場合は空の配列refとして初期化するか、ルーチンから返すだけです。 2)追加のSWエントリが前のエントリに吹きつけています。追加するには 'push'を使います。 3) '_maybe_list'は、' ServiceCustomers'または 'ServiceSuppliers'に1つのエントリしかない場合を扱います。あなたは最初のデータダンプでそれを見ることができます。私は修正プログラムをコードするためにあなたに残すつもりです、これは少し "私のコードを書く"のように感じ始めています。 – Schwern

関連する問題