2013-11-24 147 views
1

我有一個xml數據顯示如下。我想對這些數據進行一些操作。每當'entry'標籤中缺少'colname'屬性時,我的代碼應該在'tgroup'標籤中插入該屬性採用'cols'屬性的值。邏輯不工作在perl

<tbl ID="I78"> 
<table colsep="0" frame="none" rowsep="0"> 
<tgroup cols="4"> 
<tbody valign="top"> 
<row> 
<entry>i.</entry> 
<entry>181.10</entry> 
<entry>An inmate shall comply with the dispositions imposed by a hearing officer in a Tier I, Tier II and Tier III hearings.</entry> 
<entry>I, II, III</entry> 
</row> 
</tbody> 
</tgroup> 
</table> 
</tbl> 
<tbl ID="I93"> 
<table colsep="0" frame="none" rowsep="0"> 
<tgroup cols="4"> 
<tbody> 
<row> 
<entry align="center"><ital>Pledge number</ital></entry> 
<entry align="center"><ital>Date</ital></entry> 
<entry align="center"><ital>R</ital></entry> 
<entry><ital>A or S</ital></entry> 
</row> 
<row> 
<entry><ital>Disposition column</ital></entry> 
<entry>(<ital>Renewed</ital>)</entry> 
<entry>(<ital>Renewed</ital>)</entry> 
</row> 
<row> 
<entry>(<ital>Auction Sale</ital>)</entry> 
</row> 
</tbody> 
</tgroup> 
<eos></eos> 
</table> 
<eop></eop> 
</tbl> 

我的代碼如下所示:

foreach $line (@data){ 
    if($line =~ /<tgroup(.*?)cols=\"(.*?)\">/i){ 
     $colcount=$2; 
     print "\nTgroup tag found... no of cols are $colcount"; 
    } 

    $templine=$line; 
    my $temp2line; 

    while($templine=~ /<tbody(.*?)>(.*?)<\/tbody>/){ 
     $temp2line=$2; 
     while($temp2line=~ /<row>(.*?)<\/row>/){ 
      $rowdata=$1; 
      $rowdataforfinalreplacing=$rowdata; 
      $temprowdata=$rowdata; 
      while($rowdata=~/<entry align="center">/i){ 
       for ($i; $i<= $colcount; $i++){ 
        $temprowdata=~s/<entry align="center">/<entry align="center" colname=\"$i\">/i; 
        print "\ni value :$i"; 
       } 
       $rowdata=~s/<entry(.*?)<\/entry>//; 
      } 
      while($rowdata=~/<entry>/i){ 
       for (my $i=1; $i<= $colcount; $i++){ 
        $temprowdata=~s/<entry>/<entry colname=\"$i\">/i; 
       } 
       $rowdata=~s/<entry>(.*?)<\/entry>//; 
      } 
      $temp2line=~s/<row>(.*?)<\/row>//i; 
      $line=~s/$rowdataforfinalreplacing/$temprowdata/sgi; 
     } 
    } 

的問題是,當兩行同時存在,只有一排得到更新。當我調試時,我發現值正在正確更新,但在寫入輸出文件時,它們被忽略。我無法找到控制在我的代碼中出錯的地方。任何幫助,這是高度讚賞。提前致謝 !

以下是代碼的輸出。突出顯示的數據沒有更新。

Here is the output of the code

回答

6

請不要用正則表達式來解析xml數據。這是一個痛苦。

表示您的xml數據格式不正確,因爲您有幾個root標籤。我已添加<root>以使其良好組成。

這裏有一個例子與XML::Twig

#!/usr/bin/env perl 

use warnings; 
use strict; 
use XML::Twig; 

my ($colname); 

XML::Twig->new(
    start_tag_handlers => { 
     'tgroup' => sub { $colname = $_->att('cols') }, 
    }, 
    twig_handlers => { 
     'entry' => sub { $_->set_att('colname', $colname) }, 
    }, 
    pretty_print => 'indented', 
)->parsefile(shift)->print; 

運行它想:

perl script.pl xmlfile 

國債收益率:

<root> 
    <tbl ID="I78"> 
    <table colsep="0" frame="none" rowsep="0"> 
     <tgroup cols="4"> 
     <tbody valign="top"> 
      <row> 
      <entry colname="4">i.</entry> 
      <entry colname="4">181.10</entry> 
      <entry colname="4">An inmate shall comply with the dispositions imposed by a hearing officer in a Tier I, Tier II and Tier III hearings.</entry> 
      <entry colname="4">I, II, III</entry> 
      </row> 
     </tbody> 
     </tgroup> 
    </table> 
    </tbl> 
    <tbl ID="I93"> 
    <table colsep="0" frame="none" rowsep="0"> 
     <tgroup cols="4"> 
     <tbody> 
      <row> 
      <entry align="center" colname="4"> 
       <ital>Pledge number</ital> 
      </entry> 
      <entry align="center" colname="4"> 
       <ital>Date</ital> 
      </entry> 
      <entry align="center" colname="4"> 
       <ital>R</ital> 
      </entry> 
      <entry colname="4"> 
       <ital>A or S</ital> 
      </entry> 
      </row> 
      <row> 
      <entry colname="4"> 
       <ital>Disposition column</ital> 
      </entry> 
      <entry colname="4">(<ital>Renewed</ital>)</entry> 
      <entry colname="4">(<ital>Renewed</ital>)</entry> 
      </row> 
      <row> 
      <entry colname="4">(<ital>Auction Sale</ital>)</entry> 
      </row> 
     </tbody> 
     </tgroup> 
     <eos></eos> 
    </table> 
    <eop></eop> 
    </tbl> 
</root> 

UPDATE增加colname屬性。看評論。

#!/usr/bin/env perl 

use warnings; 
use strict; 
use XML::Twig; 

my ($colname, $n); 

XML::Twig->new(
     start_tag_handlers => { 
       'tgroup' => sub { $colname = $_->att('cols') }, 
       'row' => sub { $n = 1 }, 
     }, 
     twig_handlers => { 
       'entry' => sub { $_->set_att('colname', $n++) }, 
     }, 
     pretty_print => 'indented', 
)->parsefile(shift)->print; 
+0

確實運行這個腳本會覆蓋源文件嗎?我看到只有一個參數傳遞給這個.. –

+0

@RaviKumar:不會。它會將它打印到外殼。重定向到一個文件,如:'perl script.pl xmlfile> out_xmlfile' – Birei

+0

好的。在每一行中,如果有四個輸入標籤,則colname值應該從1增加到4.您的輸出顯示常量值。我該如何改變它? –

3

<row>(.*)</row>不尊重XML嵌套。即,你有什麼樣

<row> 
    ... 
    <row> 
     ... 
    </row> 
    <row> 
     ... 
    </row> 
</row> 

和外環只挑選了一切到第一內部行元素的結束和經營。

Lesson?不要使用正則表達式進行XML解析。它可以像Perl一樣用擴展的RE語法來完成,但它很快就會變得非常麻煩。你最好使用合適的XML庫。

+0

我幾乎是新的perl和第一次在xml嵌套工作。感謝您的建議,我會記下這一點。 –

+5

,,你的船,輕輕順流...... :) – toolic

+1

...如果你看到一個正則表達式解析它不要忘記尖叫! :) – Zaid