すべての入力 XML が例と一致している場合、つまり要素のみを含む非常に単純な場合、または後で検証するファイルが少数しかない場合、上記の答えは素晴らしいと思います。一般に、XML をテキストとして処理することは悪いことです。その性質上、テキストではありません。高度に構造化されています。たとえば、エンコーディングが重要である場合、さまざまです。たとえば、XML として解析することは間違いありません。
私はXML::Twigの一部になりました。これは、ストリーミングするオプション (XML ツリーを構築することもできます) のおかげです。これは、既にここで見たコマンドライン編集に非常に近い解析スタイルです。大量のデータを扱っています。XML::Twig は実際には非常に使いやすいですが、実装/構成に関する最初の学習曲線には、少し調査作業が必要になる場合があります。
XML::Lib (セットアップが少し簡単) を好む人もいます。XML::Libは、より DOM スタイルのフレーバーを提供しますが、大きなデータ セットに適用するとコストが高くなり、非常に大きなファイルでは少し扱いにくくなります。そこから、さまざまなモジュールの複雑さが少し緩和され、XML::Simpleになります。
繰り返しますが、これは要件、データ サイズ、検証基準などに大きく依存します。ワンライナーは迅速ですが、XML を処理するためのベスト プラクティスとは言えません。
考えられる解決策
仮定 -
- XML は整形式です。つまり、ルート要素があります。
- あなたのチャプターは、入力したい数よりも大きな数に拡張することができます.
- 何らかの形式の小数/分数 (One.One、または One.Half など) のチャプター値はありません。
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>