W3C勧告XSLTのバージョンXSLT 2.0の「Regular Expressions / 正規表現」とは
XSL Transformations (XSLT) Version 2.0 / W3C Recommendation 23 January 2007の目次に沿った日本語訳です。
当サイト管理人が2009年04月、意訳したものですが、構文解釈の違いや翻訳の違いが含まれるかもしれません。正式文書はW3C 各種仕様書(英語版)である事を予めご了承ください。
15 正規表現 / Regular Expressions 15.1 [ xsl:analyze-string ]命令 instruction 15.2 キャプチャーした部分文字列 Captured Substrings 15.3 正規表現マッチングの例 |
XPath 2.0における主要な関数ライブラリは、正規表現を利用させる3つの関数を定義します:
matches
FO
は、与えられる正規表現とマッチする文字列か否かの boolean 結果を返します。
replace
FO
は、入力としての文字列と与えられる置換文字列を伴う正規表現とマッチする全ての部分文字列を置換する事によって含んだ文字列を受け取ります。
tokenize
FO
は、与えられる正規表現とマッチするいくつかのセパレータで提供した入力文字列を分割する事によって形成した文字列のシーケンスを返します。
これらの関数は、[関数と演算子]の中で記述されます。
これらの関数を利用する事が可能となる以上のより多くの複雑な文字列処理については、XSLTが、このセクションの中で定義されている命令 xsl:analyze-string
を提供します。
この命令によって利用した正規表現とこれらの正規表現の解釈を操作するフラグは、[関数と演算子]で定義したシンタックス (参照先: セクション 7.6.1 正規表現シンタックスFO)と一致しなければならず、 それは、[XML スキーマ Part 2]で定義したシンタックスを基準とするそれ自身です。
xsl:analyze-string
命令<!-- カテゴリ:
命令 -->
<xsl:analyze-string
select = expression
regex = { string }
flags? = { string }>
<!-- Content: (xsl:matching-substring?,
xsl:non-matching-substring?,
xsl:fallback*) -->
</xsl:analyze-string>
<xsl:matching-substring>
<!-- Content:
sequence-constructor -->
</xsl:matching-substring>
<xsl:non-matching-substring>
<!-- Content:
sequence-constructor -->
</xsl:non-matching-substring>
xsl:analyze-string
命令は、 文字列( select
属性にある式を評価した結果)と正規表現( regex
属性の有効な値)を入力として受け取ります。
もし、 select
式を評価した結果が文字列でない場合には、関数変換規則を適用する事によって文字列に変換されます。
flags
属性は、正規表現の解釈を操作する為に利用される場合があります。
もし、属性が省略される場合には、その効果は、ゼロの長さの文字列供給と同じです。
これは、
関数 matches
FO 、
replace
FO 、
tokenize
FO の $flags
属性と同じ方法で解釈されます。
特に、もし、それが、文字 m
を含む場合には、それは、複数行モードにおけるマッチ演算子。
もし、それが、文字 s
を含む場合には、それは、[dot-all]モード。
もし、それが、文字 i
を含む場合には、それは、[case-insensitive]における演算子。
もし、それが、文字 x
を含む場合には、その時は、正規表現にあるホワイトスペースは無視されます。
これらのモードのより多くの詳細仕様については、[関数と演算子] (セクション 7.6.1.1 フラグFO)参照。
注釈:
regex
属性は、属性値テンプレートである為、正規表現にある波カッコは、二重にしなければいけません。
例えば、記述 regex=".{{1,5}}"
は、1から5までの文字のシーケンスとマッチします。
多くの波カッコを含んでいる正規表現においては、それは、
regex="{'[0-9]{1,5}[a-z]{3}[0-9]{1,2}'}"
のような表記を利用するようにより便利なものにする、または、 変数を利用する場合があります。
xsl:analyze-string
命令の内容は、次に続く形式の内の1つを取らなければいけません:
ゼロ以上の xsl:fallback
命令によって次に続く単独の xsl:matching-substring
命令
ゼロ以上の xsl:fallback
命令によって次に続く単独の xsl:non-matching-substring
命令
ゼロ以上の xsl:fallback
命令によって次に続く単独の xsl:non-matching-substring
命令によって次に続く単独の xsl:matching-substring
命令
[ERR XTSE1130]
もし、 xsl:analyze-string
命令が、 xsl:matching-substring
または、 xsl:non-matching-substring
要素のいずれでもないものを含む場合には、
それは、静的エラーです。
xsl:analyze-string
命令の子の間にあるいくつかのxsl:fallback
要素は、XSLT 2.0プロセッサによって無視されますが、
スタイルシートが、前方互換性モードの中で操作しているXSLT 1.0 プロセッサを伴って利用される際には、定義されているフォールバック(縮退)挙動を許容します。
この命令は、提供した正規表現とマッチする入力文字列の重ならない部分文字列全てを処理する為に設計されます。
[ERR XTDE1140]
もし、 regex
属性の有効な値が、
[関数と演算子]で記述したように要求した正規表現におけるシンタックスと一致しない場合には、
それは、回復されない動的エラーです。
もし、その正規表現が、静的に認知さる場合(例えば、もし、その属性が波カッコで囲まれたいくつかの式を含まない場合)には、
プロセッサは、静的エラーとしてエラーをシグナル出力する場合があります。
[ERR XTDE1145]
もし、 flags
属性の有効な値が、[関数と演算子]で定義した値ではない値を持つ場合には、
それは、回復されない動的エラーです。
もし、その属性の値が、静的に認知される場合(例えば、もし、その属性が波カッコで囲まれたいくつかの式を含まない場合)には、
プロセッサは、静的エラーとしてエラーをシグナル出力する場合があります。
[ERR XTDE1150]
もし、 regex
属性の有効な値が、ゼロの長さの文字列とマッチする正規表現である場合:、
または、もっと具体的に言うと、もし、その正規表現 $r
とフラグ $f
が、 matches("", $r, $f)
で true を返すような場合には、
それは、回復されない動的エラーです。
もし、 その正規表現が静的に認知される場合(例えば、もし、その属性が波カッコで囲まれたいくつかの式を含まない場合)には、
プロセッサは、静的エラーとしてエラーをシグナル出力する場合があります。
xsl:analyze-string
命令は、入力文字列の開始位置で始まり、そして正規表現とマッチする最初の部分文字列を見つけるように試みます。
もし、いくつかマッチするものがある場合には、その最初のマッチは、文字列の最初に来る開始位置になるように定義されます。
もし、正規表現の中のいくつかの取り得る値全てが、入力文字列の中で同じ位置にある場合には、選ばれるマッチは、マッチする最初の取り得る値です。
例えば、もし、入力文字列が、 The quick brown fox jumps
で、その正規表現が、 jump|jumps
である場合には、選ばれるマッチは、 jump
です。
最初のマッチを見つけた時には、その命令は、前のマッチに含まれなかった最初の文字で開始して繰り返し検索する事によって2番目とマッチするサブシーケンスを見つける為に続行します。
入力文字列は、このように、それとマッチしない他の正規表現とマッチするいくつかの部分文字列のシーケンスを区分けします。
各部分文字列は、少なくとも1文字含まれるでしょう。
部分文字列のシーケンスは、 xsl:matching-substring
と xsl:non-matching-substring
子命令を利用して処理されます。
マッチしている部分文字列は、 xsl:matching-substring
要素を利用して処理され、
マッチしない部分文字列は、 xsl:non-matching-substring
要素を利用して処理されます。
これらの要素のそれぞれは、その内容としてシーケンスコンストラクタを受け取ります。
もし、要素が存在しない場合には、その効果は、カラの内容を伴う存在であった時と同じです。
各部分文字列を処理する中では、部分文字列の内容は、(タイプ xs:string
の値として)文脈アイテムとなり、
マッチしている部分文字列とマッチしない部分文字列のシーケンスにある部分文字列の位置は、文脈位置となり、
マッチしている部分文字列とマッチしない部分文字列の数は、文脈サイズとなるでしょう。
もし、入力が、ゼロの長さの文字列である場合には、部分文字列の数はゼロになり、その為、
xsl:matching-substring
、または、 xsl:non-matching-substring
要素のいずれでもないものとして
評価されるでしょう。
regex-group
($group-number
as
xs:integer
) as
xs:string
[定義:
xsl:matching-substring
命令がアクティブである間、
現在獲得(キャプチャー)した部分文字列のセットは、正規表現のカッコでくくられた副次式との一致を可能にします。
]
これらの取得した部分文字列は、関数 regex-group
を利用して入手しやすくなります。
この関数は、グループを識別する為の整数引数を受け取り、取得した部分文字列を表す文字列を返します。
( N > 0 である場合の)キャプチャーした N 番目の部分文字列は、 regex ( regular expression の略=正規表現または、regex 属性)にある N 番目の左かっこによって含んだ副次式によってマッチする文字列です。
ゼロ番目にキャプチャーした部分文字列は、完全な regex とマッチする文字列です。
これが意味するところは、 regex-group(0)
の値は、 .
(dot)の値と同じ「初め」であるという事です。
その関数は、もし、関連する数を伴う存在しないキャプチャーした部分文字列がある場合には、ゼロの長さの文字列を返します。 これは、(以下の)理由の数字において出現する事が可能です:
数字は負です。
正規表現は、与えられる数字を伴うかっこで囲まれた副次式を含みません。
かっこで囲まれた副次式は、存在します、また、入力文字列の一部のいくつかとマッチしませんでした。
かっこで囲まれた副次式は、存在します、また、入力文字列のゼロの長さの部分文字列と一致しました。
獲得した部分文字列のセットは、動的スコープを伴う文脈変数です。
それは、初期のカラのシーケンスです。
xsl:matching-substring
命令の評価中、それは、マッチする正規表現(regex)におけるマッチする部分文字列のシーケンスを設定されます。
xsl:non-matching-substring
命令、または、
パターン、または、スタイルシート関数の評価中、それは、
カラのシーケンスを設定されます。
値変更命令の完了においては、変数は、その前の値に戻します。
現在獲得した部分文字列の値は、
xsl:apply-templates
、
xsl:call-template
、
xsl:apply-imports
、
または、 xsl:next-match
を呼ぶ事を通して、または、
名前付き属性セットの拡張によって影響されません。
課題: カラの br
要素によって abstract
要素内にある文字を全て新しい行に置き換える:
問題解決:
<xsl:analyze-string select="abstract" regex="\n"> <xsl:matching-substring> <br/> </xsl:matching-substring> <xsl:non-matching-substring> <xsl:value-of select="."/> </xsl:non-matching-substring> </xsl:analyze-string>
課題: 新しい要素の内容として角カッコ間に内容を入れて、 cite
要素によって body
内で [...]
に全て置き換える。
問題解決:
<xsl:analyze-string select="body" regex="\[(.*?)\]"> <xsl:matching-substring> <cite><xsl:value-of select="regex-group(1)"/></cite> </xsl:matching-substring> <xsl:non-matching-substring> <xsl:value-of select="."/> </xsl:non-matching-substring> </xsl:analyze-string>
注記としては、もし、 body
要素が、そのまま残すために必要なマークアップを含む場合には、この単純なアプローチは、失敗します。
このケースでは、独立したテキストノードごとに正規表現処理を適用する事が必要です。
もし、 [...]
が、(例えば、角カッコ内に要素があるので)複数のテキストノード範囲を構築する場合には、
おそらく、(適切に分割する為に)2つ作る事が必要となったり、または、(適切な文節になるようより多くの文字を格納する為に)そのデータを更に通過する(ズラす)事になったりするでしょう。
課題: 23 March 2002
のような日付を含む入力文字列を形式 2002-03-23
に変換する。
問題解決 (入力フォーマットが正しくない場合に伴うエラーハンドルはありません):
<xsl:variable name="months" select="'January', 'February', 'March', ..."/> <xsl:analyze-string select="normalize-space($input)" regex="([0-9]{{1,2}})\s([A-Z][a-z]+)\s([0-9]{{4}})"> <xsl:matching-substring> <xsl:number value="regex-group(3)" format="0001"/> <xsl:text>-</xsl:text> <xsl:number value="index-of($months、 regex-group(2))" format="01"/> <xsl:text>-</xsl:text> <xsl:number value="regex-group(1)" format="01"/> </xsl:matching-substring> </xsl:analyze-string>
注釈:正規表現によって実行した作業を単純化する為に normalize-space
を使用、
また、 regex
属性が属性値テンプレートである為、二重波カッコを使用。
16. 新規追加された機能 / Additional Functions >>