すでに取り上げていますが、xsl:analyze-stringをもう一度使ってみる機会がありましたので紹介します.
目的は"($Index_Indent_Value) * %level + 2mm"のようなスタイル記述の文字列で、"$"で始まっている変数的なものを取り出して値で置換する、他はそのままというものです.例えば"$Index_Indexnt_Value"は"7mm"に変換します.”%level"という変数的な記述もありますが、これはスタイル適用時に動的に値を変えたい主旨です.
サンプルはこのようなものになります.結果がわかりやすいようにマッチングした箇所は<match>~</match>、マッチングしない箇所は<unmatch>~</unmatch>で出力します.
<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 indent="yes"/>
<xsl:template match="/">
<xsl:variable name="exp" as="xs:string" select="'($Index_Indent_Value) * (%level - 1)'"/>
<xsl:variable name="expandExpRegX" as="xs:string" select="'[\s\(\),\*\+\-]+'"/>
<result>
<xsl:analyze-string select="$exp" regex="$expandExpRegX">
<xsl:matching-substring>
<match>
<xsl:value-of select="."/>
</match>
</xsl:matching-substring>
<xsl:non-matching-substring>
<unmatch>
<xsl:choose>
<xsl:when test=". eq '$Index_Indent_Value'">
<xsl:text>7mm</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</unmatch>
</xsl:non-matching-substring>
</xsl:analyze-string>
</result>
</xsl:template>
</xsl:stylesheet>
で一発で動いてくれるものと自信満々だったのですが、結果は敢え無く撃沈で
<result>
<unmatch>($Index_Indent_Value) * (%level - 1)</unmatch>
</result>
となってしまいました.置換も何もあったものではありません.最近xsl:analyze-stringは使っていなかったので必死に過去の例を引っ張り出して見直したら、
<xsl:analyze-string select="$exp" regex="{$expandExpRegX}">
<result>
<match>(</match>
<unmatch>7mm</unmatch>
<match>) * (</match>
<unmatch>%level</unmatch>
<match> - </match>
<unmatch>1</unmatch>
<match>)</match>
</result>
バッチリ置換していてくれます.構文解析まではとても行きませんが、置換には非常に有用です.これを一般的なスタイル記述で使えるようにするともっと動的にスタイルを当てることができるようになります.
さて<xsl:variable name="expandExpRegX" as="xs:string" select="'[\s\(\),\*\+\-]+'"/>に注目していただきたいのですが、正規表現で使用する文字はすべてバックスラッシュででエスケープします.ここがポイントです.あと<xsl:variable name="expandExpRegX" as="xs:string" select="'[\s\(\),\*\+\-]+?'"/>と変えると最少範囲でマッチングしてくれるようになります.これも時として必要になります.
<result>
<match>(</match>
<unmatch>7mm</unmatch>
<match>)</match>
<match> </match>
<match>*</match>
<match> </match>
<match>(</match>
<unmatch>%level</unmatch>
<match> </match>
<match>-</match>
<match> </match>
<unmatch>1</unmatch>
<match>)</match>
</result>
xsl:analyze-stringは正規表現を駆使すればテキスト処理で非常に強力な武器になります.