我有以下函数将字符串($replace
)中搜索字符串($text
)的所有出现替换为另一个字符串($by
):
<xsl:template name="string-replace-all">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text"
select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
这适用于替换单个字符串中的文本,但在尝试替换节点集中的文本时它不起作用。
我正在寻找的是一个功能,例如,它采用以下XML文档:
<nodeSet>
<node>a1;a2;a3</node>
<node>b1;b2;b3</node>
</nodeSet>
并输出以下内容:
<nodeSet>
<node>a1#a2#a3</node>
<node>b1#b2#b3</node>
</nodeSet>
以下模板在预先知道目标和替换字符串时完成工作:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl"
>
<xsl:template name="string-replace-all-in-nodeset">
<xsl:param name="nodeset" />
<xsl:apply-templates select="exsl:node-set($nodeset)" mode="str-repl-in-nodeset"/>
</xsl:template>
<xsl:template match="*/text()" mode="str-repl-in-nodeset">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="replace" select=" ';' "/>
<xsl:with-param name="by" select=" '#' "/>
</xsl:call-template>
</xsl:template>
<xsl:template name="string-replace-all">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@*|node()" mode="str-repl-in-nodeset">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="str-repl-in-nodeset"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
但是,我需要能够动态传递目标和替换字符串(在这种情况下为&#39;&#39;和#39;#&#39;)。有没有办法将这些参数传递给匹配所有文本节点(match="*/text()"
)的模板或任何其他实现我想要的方式?
答案 0 :(得分:2)
这是一个样式表,用于定义replace
和by
字符串的全局参数,然后将其传递给该模式str-repl-in-nodeset
中的所有模板:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="exsl">
<xsl:param name="ns1">
<nodeSet>
<node>a1;a2;a3</node>
<node>b1;b2;b3</node>
</nodeSet>
</xsl:param>
<xsl:param name="replace" select="';'"/>
<xsl:param name="by" select="'#'"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="exsl:node-set($ns1)" mode="str-repl-in-nodeset">
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="/ | @* | node()" mode="str-repl-in-nodeset">
<xsl:param name="replace"/>
<xsl:param name="by"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="str-repl-in-nodeset">
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="*/text()" mode="str-repl-in-nodeset">
<xsl:param name="replace"/>
<xsl:param name="by"/>
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="string-replace-all">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:transform>