如何使用perl脚本为xml元素生成序列

时间:2013-11-13 12:12:36

标签: xml perl

输入:

<h2>Chapter One</h2>    
<h2>Chapter Two</h2>    
<h2>Chapter Three</h2>    
<h2>Chapter Four</h2>

输出:我需要什么

<h2 id="1">Chapter One</h2>
<h2 id="2">Chapter Two</h2>
<h2 id="3">Chapter Three</h2>
<h2 id="4">Chapter Four</h2>

请帮助... 感谢

2 个答案:

答案 0 :(得分:1)

快速正则表达式,

perl -pe '($n)=/Chapter\s+([0-9]+)/; s|<h2\K| id="$n"|' file

您也可以查看What's the best XML parser for Perl?

答案 1 :(得分:1)

我认为如果您的所有输入XML与您的示例一致,即上述答案非常好,即非常简单只包含元素,或者您之后只有少量文件需要验证。通常,将XML作为文本处理是一件坏事。就其本质而言,它不是文本;它结构严谨。例如,如果编码很重要,那么,您肯定希望将其解析为XML。

我已经偏向XML::Twig,因为流选项(也可以构建XML树),这是一种解析风格,更接近您在此处看到的命令行编辑。我处理了大量数据。 XML :: Twig实际上非常容易使用,但实现/配置的初始学习曲线可能需要一些研究工作。

有些人更喜欢XML::Lib(设置稍微简单一点),它提供了更多DOM风格的风格,但是对于大型数据集应用更加昂贵,而对于非常大的文件则更加笨拙。从那里,各种模块变得不那么复杂,XML::Simple

同样,这在很大程度上取决于您的要求,数据大小,验证标准等。单行代码很快,但不是处理XML的最佳实践。

可能的解决方案

假设 -

  • 您的XML格式正确;也就是说,它有一个根元素。
  • 你的章节可以延伸到一个大于你的一个数字 愿意输入。
  • 你不会有章节值的某种形式的小数/分数(One.One, 或者一个半等。)

您可以使用XML :: Twig和Lingua::EN::Words2Nums

所以,给定输入:

<root>
   <h2>Chapter One</h2>
   <h2>Chapter Two</h2>
   <h2>Chapter Three</h2>
   <h2>Chapter Four</h2>
</root>

此代码:

use XML::Twig;
use Lingua::EN::Words2Nums;

my $twig = new XML::Twig( 
      twig_roots => { 'h2' => \&h2_handler },
      twig_print_outside_roots => 1);

sub h2_handler { 
   my ($twig,$elt) = @_;
   my $engNum = $elt->trimmed_text;
   $engNum =~ s/^chapter\s([a-z]+)$/$1/i;
   my $num = words2nums("$engNum");
   if (defined($num) and $num=~/\d+/){
      $elt->set_att( id => $num);
    }else{
       # Whatever you do if some chapter number is not what's expected
    }
   $elt->flush;
}

$twig->parsefile(pathToYourFile);

将输出:

<root>
   <h2 id="1">Chapter One</h2>
   <h2 id="2">Chapter Two</h2>
   <h2 id="3">Chapter Three</h2>
   <h2 id="4">Chapter Four</h2>
</root>