あなたの例では、括弧はどれも一致せず、すべてが開き括弧です。その場合、一致しない括弧と括弧を削除するタスクは、すべての括弧と括弧を削除することになります。translate
これは、次の関数を使用して最も簡単に実行できます。
<xsl:value-of select="translate(.,'([','')"/>
実際に一致する中括弧を保持し、フォームの入力を に変換する必要がある場合a(b[c]d(e
、ab[c]de
XSLT でこれを行う最も簡単な方法は、入力文字列と、これまでに処理された素材を記録するスタックの 2 つのパラメーターを取る再帰的な名前付きテンプレートを使用することです。(スタックは、選択したセパレーターで区切られた文字列のシーケンスであり、入力に表示されないようにすることができます。入力が属性値からのものとして表示&#x9;
されるため、おそらく安全な選択になります(データ プロデューサーが数字参照を使用しない限り、入力から正規化されています)。ただし、必要|||never-use-this-string-in-a-part-description|||
に応じて代わりに使用できます)。
最初の呼び出しでは、入力文字列だけを渡し、スタックをデフォルトで空にします。
空でない入力を使用する呼び出しごとに、テンプレートは入力ストリームから 1 文字を取り出し、それを使用して正しいことを行います。
- "(" と "[" の場合、新しい文字列をスタックにプッシュします。
- スタックの一番上のアイテムの最初の文字に一致する "]" と ")" の場合、スタックを 2 回ポップし、アイテム 2、アイテム 1 (古い一番上のアイテム)、および文字 "]" または ")" を連結し、連結をスタックにプッシュします。
- 一致しない「]」と「)」については、入力のバランスが悪いので、何かをする必要があります。(ここのコードは文字を削除します。)
- その他の文字については、スタックの一番上の項目に追加します。
したがって、スタック上のすべての項目は、一番下の項目を除き、まだ一致していない開き括弧または括弧で始まります。一致するたびに、括弧で囲まれた文字列がスタックの次の項目に追加されるため、スタック サイズが小さくなります。
入力文字列が使い果たされ、スタックに複数の項目がある場合、スタックの一番上の項目の先頭の中括弧を取り除き、一番上の項目 (中括弧を除く) を次の項目に追加する必要があります。
スタックが 1 つのアイテムになると、そのアイテムには必要な文字列が含まれます。
ここに XSLT があります。
<xsl:template name="paren-match-or-strip">
<xsl:param name="input"/>
<xsl:param name="stack"/>
<xsl:variable name="char"
select="substring($input,1,1)"/>
<xsl:variable name="stacktop"
select="substring-before($stack,$sep)"/>
<xsl:variable name="stackrest"
select="substring-after($stack,$sep)"/>
<xsl:choose>
<xsl:when test="not($input = '')">
<xsl:choose>
<xsl:when test="$char = '(' or $char = '['">
<!--* Push another potential-left-brace on the stack *-->
<xsl:call-template name="paren-match-or-strip">
<xsl:with-param name="input"
select="substring($input,2)"/>
<xsl:with-param name="stack"
select="concat(
$char,
$sep,
$stack
)"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="($char = ']' and substring($stacktop,1,1) = '[')
or
($char = ')' and substring($stacktop,1,1) = '(')
">
<!--* Match the left brace at the top of the stack *-->
<xsl:variable name="stacktop2"
select="substring-before($stackrest,$sep)"/>
<xsl:variable name="stackrest2"
select="substring-after($stackrest,$sep)"/>
<xsl:call-template name="paren-match-or-strip">
<xsl:with-param name="input"
select="substring($input,2)"/>
<xsl:with-param name="stack"
select="concat(
$stacktop2,
$stacktop,
$char,
$sep,
$stackrest
)"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$char = ']' or $char = ')'">
<!--* Unmatched right brace, drop it silently *-->
<xsl:call-template name="paren-match-or-strip">
<xsl:with-param name="input"
select="substring($input,2)"/>
<xsl:with-param name="stack"
select="$stack"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="paren-match-or-strip">
<xsl:with-param name="input"
select="substring($input,2)"/>
<xsl:with-param name="stack"
select="concat(
$stacktop,
$char,
$sep,
$stackrest
)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$input = '' and contains($stackrest,$sep)">
<!--* Input is exhausted and at least one unmatched
* parenthesis is on the stack.
*-->
<xsl:variable name="stacktop2"
select="substring-before($stackrest,$sep)"/>
<xsl:variable name="stackrest2"
select="substring-after($stackrest,$sep)"/>
<xsl:call-template name="paren-match-or-strip">
<xsl:with-param name="input"
select="$input"/>
<xsl:with-param name="stack"
select="concat(
$stacktop2,
substring($stacktop,2),
$sep,
$stackrest2
)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!--* input is exhausted, stack only has one item *-->
<xsl:value-of select="substring-before($stack,$sep)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>