BLOGTIMES
2014/07/25

XSLT 2.0 で正規表現による置換処理を行う

  xml 
このエントリーをはてなブックマークに追加

XSLT 1.0 は文字列の処理が貧弱で、concat(), contains(), string-length(), substring() くらいの本当に基本的な関数しか用意されていないのでちょっとしたテキスト処理をやるだけで苦労することが多々ありましたが、XSLT 2.0 からはちゃんと正規表現が使えるようになっているようなのでちょっとためしてみました。

詳細については仕様書の 15 Regular Expressions にまとまっています*1
これによると <xsl:analyze-string> を使うと正規表現で文字列を変換することができるみたいです。仕様を読む限りは他の言語の gsub() のような感じでしょうか。

<xsl:analyze-string select="(XPath)" regex="(正規表現)"> <xsl:matching-substring> <!-- マッチしたとき --> </xsl:matching-substring> <xsl:non-matching-substring> <!-- マッチしなかったとき --> </xsl:non-matching-substring> </xsl:analyze-string>

後方参照については15.2 Captured Substrings に記載されていますが、regex-group() という関数を呼び出すことによって可能になるようです。

さっそく動かしてみる

前回の日付の処理と同じく、Saxson を使います
テストに使った XML は下記のような簡単なもの。

test.xml

<root> <item id="1">123-4567,890-1234</item> <item id="2">2014/07/25,2014/07/26</item> <item id="3">abcdef,ghijkl</item> </root>

これを下記の XSL で変換をかけてみます。

regex.xsl

<?xml version='1.0' encoding='UTF-8'?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"> <xsl:output media-type="text/xml; charset=UTF-8" encoding="UTF-8"/> <xsl:template match="*"> <xsl:copy> <xsl:for-each select="@*"> <xsl:copy /> </xsl:for-each> <xsl:apply-templates /> </xsl:copy> </xsl:template> <xsl:template match="item"> <xsl:copy> <xsl:for-each select="@*"> <xsl:copy /> </xsl:for-each> <xsl:analyze-string select="." regex="([\d]+)-([\d]+)"> <xsl:matching-substring><b><xsl:value-of select="regex-group(1)" />-<xsl:value-of select="regex-group(2)" /></b></xsl:matching-substring> <xsl:non-matching-substring><br /></xsl:non-matching-substring> </xsl:analyze-string> </xsl:copy> </xsl:template> </xsl:stylesheet>

結果は下記のような感じになります。

$ java -Xss16m -jar saxon9he.jar -xsl:regex.xsl -s:test.xml

<?xml version="1.0" encoding="UTF-8"?> <root> <item id="1"> <b>123-4567</b> <br/> <b>890-1234</b> </item> <item id="2"> <br/> </item> <item id="3"> <br/> </item> </root>

xsl:analyze-string は再帰的に適用されるので、該当する箇所全体が置換されているのがわかります。
また、regex-group()による後方参照もきちんとできていますね。

これでやっと XSLT で少しは実用的な文字列処理ができるのではないかと思います。


トラックバックについて
Trackback URL:
お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/6887
Trackbacks
このエントリにトラックバックはありません
Comments
愛のあるツッコミをお気軽にどうぞ。[policy]
古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
コメントはありません
Comments Form

コメントは承認後の表示となります。
OpenIDでログインすると、即時に公開されます。

OpenID を使ってログインすることができます。

Identity URL: Yahoo! JAPAN IDでログイン