2011-10-06 19 views
2

單個文件編輯中處理多個XML「文件」:對不起,我輸錯「名」時,我的意思是「裁判」,我已經包括了完整的屬性以及用Perl

我有很多的xml在一行中包含一個完整的xml文檔的文件。一個例子是:

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

有一些屬性,以及我不包括爲清晰起見。

我使用XML :: Parser來解析這個問題& XML :: SimpleObject它可以正常工作。例如,我只是打印出每個元素的屬性,除非我嘗試打印列元素的'ref'屬性。然後我得到一個「未初始化的變量」錯誤。代碼是:

#!/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

在您的示例XML有不是該列的「名稱」屬性,並且您的代碼中無處可見您訪問名稱屬性。也許更準確的例子會給出更好的答案。 – AFresh1

+0

如果您提供了一點與您的代碼一起運行的實際樣本數據,這將更容易回答。 – runrig

+0

示例數據就在第一個灰色框中。 –

回答

1

您的示例數據不會解析(即使刪除了點),因此它不是有效的XML。我不確定你的實際數據是怎樣的,但這對於發現問題非常重要。

我確定XML::ParserXML::SimpleObject沒有問題。所以,請檢查以下內容:

  • 你正確拼寫的元素/屬性(記住XML是區分大小寫
  • 是否元素/屬性實際上存在(例如:做每REQUEST - 元素有service-attribute?是否每個ROW都有一個ref-attribute?)。如果它們不存在,則必須拒絕輸入數據或處理您擁有的數據。這當然取決於你的要求。
  • 可選:根據DTDXSD驗證XML文檔樹來驗證數據完整性。這就像第二點的高級版本。

其實我已經採取了時間,使其工作(僅通過改變元素名稱的情況下,並稍微修改您的「樣本數據」):

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> 

輸出:

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 

我測試過它也有多個WRRequest -elements(複製&粘貼) - 工作就像一個魅力。

+0

謝謝,這有幫助。 –

1

我無法確切知道數據應該如何理想地組織,但我發現XML::Rules方便在這些情況下。如果您打算採取完全不同的方式,例如(我假設「裁判」是每一行中的鍵,列名應保持秩序,所有你關心的是「裁判」屬性等):

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