XML标记以分层方式关闭

时间:2012-01-10 07:24:55

标签: xml perl

嗨,我在多级标签关闭时遇到问题,我想从内层关闭标签,然后关闭其外层,例如

<P_Normal><list-bull></P_Normal>
<P_list-bull(1)>Use Microsoft Windows accessibility</P_list-bull(1)>
<P_list-simple(2)>Magnify the display </P_list-simple(2)>
<P_list-simple(2)>Change the size of text and icons</P_list-simple(2)>
<P_list-bull(1)>Adjust background colours </P_list-bull(1)>
<P_Normal></list-bull></P_Normal>
 

我的输出应该像下面的代码

<list list-type="bullet">
<list-item><p>Use Microsoft Windows accessibility options to:
<list list-type="simple">
<list-item><p> Magnify the display</p></list-item>
<list-item><p> Change the size of text and icons</p></list-item>
</list></p></list-item>
<list-item><p> Adjust background colours</p></list-item>
</list>

我尝试下面的代码,但它只显示单个列表项

while($str =~ /<list-(bull|num|alpha)(?:(?:(?!<\/list-\1>).)*)<\/list-\1>/sgi){
    $str =~ s#<list-(bull|num|alpha)(?:(?:(?!<\/list-\1>).)*)<\/list-\1>#&ListFind($&)#sgei;
}
sub ListFind{
my $line = @_;
my $currentlevel = 0;
while($line =~ s#^[\s\S]*?<(P_list-(\w+)\((\d+)\))>(.*?)</\1>\s*##g)
{
my ($tag, $kind, $level, $text) = ($1, $2, $3, $4);
if ($currentlevel < $level) {
while($currentlevel < $level) {
        $line= "\n<list list-type=$kind>\n<list-item><p>";

        $currentlevel++;
    }
 } elsif ($currentlevel > $level) {
    # close lists down to the given level
    while($currentlevel > $level) {
        $currentlevel--;
        $line ="</p></list-item>\n</list>\n";
    }
    $line = "</p></list-item>\n<list-item><p>";

  } else {
    # close former item
   $line = "</p></list-item>\n<list-item><p>";

  }
  $line .= $text;
 }
 while($currentlevel > 0) {
 $currentlevel--;
 $line .= "</p></list-item>\n</list>\n";

 }
 return "$line";
 }

1 个答案:

答案 0 :(得分:0)

结帐Perl SAX。这应该会让你走上正确的道路。