- 正規表現
- 属性値の正規化
- テキストの正規化
正規表現
XML での空白は ' ', '\t', '\r', '\n' の4文字なので、Java での正規表現(java.util.regex.Pattern の JavaDoc 参照)で XML の空白文字 (whitespace character) を表現すると
[ \t\r\n]
となります。 同様に空白 (whitespace) (空白文字の1つ以上の連なり)は
[ \t\r\n]+
となります。
属性値の正規化
属性値はパーサによって「正規化 (normalization)」という処理が行われます。 属性値の型が CDATA でない場合、この「正規化」の処理は以下のことを行います:
- 先頭と後尾の空白を取り除く
- 連続する空白文字を1つの空白で置き換える
★先頭と後尾の空白を取り除く★
「先頭と後尾の空白を取り除く」処理には String#trim() が適していそうですが、このメソッドで空白とみなす文字は「文字コードが \u0020 以下の文字」となっています。
幸いにも(というか、そうなるようにしてあるのでしょうが)、XML の属性値の文字列に String#trim() を適用すると、意図した通りに「先頭と後尾の空白を取り除く」ことができます。
これは、「文字コードが \u0020 以下の文字」の文字の内、XML の空白文字 (' ', '\t', '\r', 'n') 以外の文字は禁止されている(使用できる文字として定義されていない)ためです。 例えば、文字コードが \u000b の文字が属性値の先頭にあった場合、「正規化」によってこの文字が除去されてはいけませんが、String#trim() では除去してしまいます。 しかし、こういった文字は属性値の中には現れないことになっています*1。
★連続する空白文字を1つの空白で置き換える★
この処理は、String#replaceAll() メソッドによって実現できます。 上で定義した XML の空白を表す正規表現にも注意:
String attValue = ...; attValue.replaceAll("[ \\t\\r\\n]+", " "); // 正規表現にエスケープが必要
★属性の正規化★
結局のところ、「属性値の正規化」を行うには、以下の処理を行えば良いことになります(必ずしも実装がこうなっているわけではありませんが):
public String normalize(String attValue){ return attValue.trim().replaceAll("[ \\t\\r\\n]+", " "); }
テキストの正規化
テキスト中の空白の扱いは処理する側のアプリケーションに任せられています(@xml:space 属性がない場合)。 とはいっても、よく使われる処理は決まっているかと思います。
Nux JavaDoc API の nux.xom.pool.XOMUtil.Normalizer クラスに空白の取り扱い方を列挙してくれているので、そちらを紹介しておきましょう。 種類は5つ:
- PRESERVE
- STRIPE
- REPLACE
- TRIM
- COLLAPSE
以下、次のサンプル XML 文書についての適用結果と共に処理方法を見ていきましょう:
<root> <text> If at first an idea does not sound absurd, then there is no hope for it. - ALBERT EINSTEIN </text> </root>
★PRESERVE(保存する)★
Whitespace normalization returns the string unchanged; hence indicates no whitespace normalization should be performed at all; This is typically the default for applications.
何もしません。 @xml:space 属性が付いているのと同じです。 大抵の場合、これがアプリケーションのデフォルト処理になっています。
<root> <text> If at first an idea does not sound absurd, then there is no hope for it. - ALBERT EINSTEIN </text> </root>
★STRIP(はぐ)★
Whitespace normalization removes strings that consist of whitespace-only (boundary whitespace), retaining other strings unchanged.
空白のみからなるテキストを取り除き、それ以外のテキストはそのままにします。
<root><text> If at first an idea does not sound absurd, then there is no hope for it. - ALBERT EINSTEIN </text></root>
★REPLACE(置換する)★
Whitespace normalization replaces each whitespace character in the string with a ' ' space character.
空白文字をスペース (' ') で置換します。
<root> <text> If at first an idea does not sound absurd, then there is no hope for it. - ALBERT EINSTEIN </text> </root>
ここでは、改行文字をスペースに変換しています*2。
★TRIM(切り取る)★
Whitespace normalization removes leading and trailing whitespaces, if present, ala String.trim().
先頭と後尾の空白を String#trim() メソッドを用いて取り除きます。
<root><text>If at first an idea does not sound absurd, then there is no hope for it. - ALBERT EINSTEIN</text></root>
★COLLAPSE(崩す)★
Whitespace normalization replaces each sequence of whitespace in the string by a single ' ' space character; Further, leading and trailing whitespaces are removed, if present, ala String.trim().
空白の連なりをスペース (' ') で置き換え、先頭と後尾の空白を String#trim() メソッドで取り除きます。 REPLACE & COLLAPSE。 値が単語の XML プロパティファイルまたは XHTML に使うことが多いと思います。
<root><text>If at first an idea does not sound absurd, then there is no hope for it. - ALBERT EINSTEIN</text></root>