2011-10-06 3 views
2

Modifié: Désolé, je mal orthographié « name » quand je veux dire « ref » et j'ai inclus les attributs complets aussi bienGérer plusieurs « documents » XML dans un seul fichier avec Perl

J'ai un certain nombre de xml les fichiers contenant, sur une seule ligne, un document XML complet. Un exemple serait:

<Reqeusts> 
    <WRRequest><Request domain="foo.com"><Rows><Row includeascolumn="n" interval="hour" ref="time" type="group"/><Row includeascolumn="n" ref="domain_id" type="group"/><Row />...</Rows><Columns><Column ref="user_id"/><Column ref="country_id"/><Column ref="country_name"/>...</Columns></Request></WRRequest> 
. 
. 
. 
</Requests> 

Il y a un certain nombre d'attributs aussi bien que je ne suis pas compris pour des raisons de clarté. Je l'analyse avec XML :: Parser & XML :: SimpleObject qui fonctionne bien jusqu'à un certain point. Par exemple, je ne fais qu'imprimer les attributs de chacun des éléments qui fonctionnent sauf quand j'essaie d'imprimer l'attribut 'ref' de l'élément column. Ensuite, je reçois une erreur "variable non initialisée". Le code est:

#!/usr/bin/perl 
use warnings; 
use diagnostics; 
use XML::Parser; 
use XML::SimpleObject; 
use Cwd; 


if ($ARGV[0] eq "") { 
    die "usage: sumXML.pl <input file> \n"; 
} 

my $fileName = $ARGV[0]; 

my $parser = new XML::Parser(Style => 'Tree'); 
my $xso = XML::SimpleObject->new($parser->parsefile("$fileName")); 


foreach my $wrRequest ($xso->child('WRRequests')->children('RWRequest')) { 
    print "Client Name: " . $wrRequest->attribute('clientName') . "\n"; 
foreach my $xmlRequest ($wrRequest->child('REQUEST')) { 
    print "Domain name: " . $xmlRequest->attribute('domain') . "\n"; 
    print "Service: " . $xmlRequest->attribute('service') . "\n"; 
    foreach my $xmlRow ($xmlRequest->child('ROWS')->children('ROW')) { 
    print "Row Reference: " . $xmlRow->attribute('ref') . "\n"; 
    } 
    foreach my $xmlColumn ($xmlRequest->child('COLUMNS')->children('COLUMN')) { 
    print "Column Reference: " . $xmlColumn->attribute('ref') . "\n"; 
    } 
} 
    print "\n"; 
} 
+0

Dans votre XML exemple, il n'est pas un attribut 'name' de la colonne, et nulle part dans votre code, vous semblez accéder à un attribut de nom. Peut-être qu'un exemple plus précis donnerait de meilleures réponses. – AFresh1

+0

Il serait plus facile de répondre si vous fournissiez un peu de données d'exemple réelles qui ont fonctionné avec votre code. – runrig

+0

Les données d'échantillon sont là dans la première case grise. –

Répondre

1

Vos données d'échantillon n'analyse pas (même si vous supprimez les points) de sorte qu'il n'est pas XML valide. Je ne sais pas à quoi ressemblent vos données, mais c'est très important pour trouver le problème. Je suis certain qu'il n'y a rien de mal avec XML::Parser ou XML::SimpleObject. Alors, s'il vous plaît vérifier les points suivants:

  • épelez-vous l'élément/attribut correctement (rappelez-XML est sensible à la casse )
  • Est-ce que l'élément/attribut existe réellement (par exemple: le fait chaque REQUEST -Element ont une service -attribute? Est-ce que chaque ROW a un ref -attribute?). S'ils n'existent pas, vous devez soit rejeter les données d'entrée, soit traiter les données dont vous disposez. Cela dépend bien sûr de vos besoins.
  • Facultatif: validez l'arborescence XML-document par rapport à DTD ou XSD pour vérifier l'intégrité des données. C'est comme la version avancée du deuxième point.

J'ai pris le temps pour le faire fonctionner (en changeant juste le cas des éléments noms, et légèrement modifier votre « données de l'échantillon »):

use strict; 
use warnings; 
use XML::Parser; 
use XML::SimpleObject; 
use Cwd; 


my $inXML = join "", <DATA>; 
print $inXML; 

my $parser = new XML::Parser(Style => 'Tree'); 
my $xso = XML::SimpleObject->new($parser->parse($inXML)); 


foreach my $wrRequest ($xso->child('Requests')->children('WRRequest')) { 
    print "Client Name: " . $wrRequest->attribute('clientName') . "\n"; 
    foreach my $xmlRequest ($wrRequest->child('Request')) { 
     print "Domain name: " . $xmlRequest->attribute('domain') . "\n"; 
     print "Service: " . $xmlRequest->attribute('service') . "\n"; 
     foreach my $xmlRow ($xmlRequest->child('Rows')->children('Row')) { 
      print "Row Reference: " . $xmlRow->attribute('ref') . "\n"; 
     } 
     foreach my $xmlColumn ($xmlRequest->child('Columns')->children('Column')) { 
      print "Column Reference: " . $xmlColumn->attribute('ref') . "\n"; 
     } 
    } 
    print "\n"; 
} 


__DATA__ 
<Requests> 
    <WRRequest clientName="foo"> 
    <Request service="fooService" domain="foo.com"> 
     <Rows> 
     <Row includeascolumn="n" interval="hour" ref="time" type="group"/> 
     <Row includeascolumn="n" ref="domain_id" type="group"/> 
     </Rows> 
     <Columns> 
     <Column ref="user_id"/> 
     <Column ref="country_id"/> 
     <Column ref="country_name"/> 
     </Columns> 
    </Request> 
    </WRRequest> 
</Requests> 

Sortie:

Client Name: foo 
Domain name: foo.com 
Service: fooService 
Row Reference: time 
Row Reference: domain_id 
Column Reference: user_id 
Column Reference: country_id 
Column Reference: country_name 

Je l'ai testé aussi avec plusieurs WRRequest -elements (copier & coller) - travaillé comme un charme.

+0

Merci, ça m'a aidé. –

1

Je ne peux pas savoir avec certitude comment les données devraient être idéalement organisées, mais je trouve XML::Rules pratique dans ces situations. Si vous êtes ouvert à une manière complètement différente de le faire, par ex. (Je suppose « ref » est la clé de chaque rangée, les noms de colonnes doivent être conservés dans l'ordre et que tout ce que vous aimez est l'attribut « ref », etc.):

use strict; 
use warnings; 

use Data::Dumper; 
use XML::Rules; 

my $xml = <<XML; 
<Requests> 
    <WRRequest> 
    <Request domain="foo.com" service="SomeService"> 
     <Rows> 
     <Row includeascolumn="n" interval="hour" ref="time" type="group"/> 
     <Row includeascolumn="n" ref="domain_id" type="group"/> 
     </Rows> 
     <Columns> 
     <Column ref="user_id"/> 
     <Column ref="country_id"/> 
     <Column ref="country_name"/> 
     </Columns> 
    </Request> 
    </WRRequest> 
</Requests> 
XML 

my @rules = (
    Request => sub { delete $_[1]->{_content}; print Dumper $_[1]; return }, 
    Rows => 'pass no content', 
    Columns => 'pass no content', 
    Row  => 'no content by ref', 
    Column => sub { '@'.$_[0] => $_[1]{ref} }, 
); 

my $p = XML::Rules->new(
    rules => \@rules, 
); 
$p->parse($xml); 

__END__ 
$VAR1 = { 
      'Column' => [ 
         'user_id', 
         'country_id', 
         'country_name' 
        ], 
      'domain' => 'foo.com', 
      'time' => { 
        'type' => 'group', 
        'includeascolumn' => 'n', 
        'interval' => 'hour' 
        }, 
      'domain_id' => { 
         'type' => 'group', 
         'includeascolumn' => 'n' 
         }, 
      'service' => 'SomeService' 
     }; 
Questions connexes