Fool Pool

ハマった記

正規表現の練習 -- XMLの閉じタグ補完

概要

開きタグのみ記述されたXMLコードの閉じタグを補完する。

例)
[入力データ]

<day id="05">5日
<month>4月

[出力データ]

<day id="05">5日</day>
<month>4月</month>

要件

  • タグの階層は1つのみ(入れ子は考えない)
  • タグの属性(id属性など)はあってもよい。

実装

[sample.in]

<day id="01">5日
<month>4月

[tag_complete.pl]

@in_text = <>;
@out_text = ();

for (@in_text) {
    my $line = $_; 
    chomp $line;

    my ($whole,$tag) = ($line =~ m/(<([^> ]+)[^>]*>[^<>]+)/);
    push @out_text, "$whole</$tag>";
}

print "$_\n" for @out_text;

[出力結果]

$ perl tag_complete.pl sample.in
<day id="01">5日</day>
<month>4月</month>

制約

  • 1行につき開きタグは1つのみ
  • タグで囲っている文字列は途中で改行されていない

例)以下のような入力は正しく処理できない。

<day>5日<month>4月
<day>
6日
<month>4
月

以下のような入力は正しく処理できる。

<day>5日
<month>4月
<day>6日
<month>4月
  • XMLのタグ名はスペース( )、およびタグの終端記号(>)をのぞく任意の文字の繰り返しからなる[4]

参考文献

[1] ActivePerlのダウンロード及びインストール -- Perlのインストール方法
[2] Perl入門 -- 初心者向けの How To
[3] Perl基礎入門 | KentWeb -- 正規表現の解説
[4] Extensible Markup Language (XML) 1.0 (Fifth Edition) -- W3C, XML 1.0 勧告

補足

W3C, SML 1.0勧告[4]によると、タグ名にドット(.)やコロン(:)なども許容するらしい。

Names and Tokens

[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
[5] Name ::= NameStartChar (NameChar)*
[6] Names ::= Name (#x20 Name)*
[7] Nmtoken ::= (NameChar)+
[8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*

よりXMLに忠実に書くと、タグ名を切り出す正規表現は以下のようになる。
[仕様]

  • タグ名の開始文字 ::= ":" | [A-Z] | "_" | [a-z]
  • タグ名の2文字目以降 ::= ":" | [A-Z] | "_" | [a-z] | "-" | "." | [0-9]
/([:A-Z_a-z][:A-Z_a-z-.0-9]*)/