下面是用于执行多个替换成一个字符串XSLT转换 - 没有扩展功能所需:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:reps>
<rep>
<old>Dwelling</old>
<new>FLAT</new>
</rep>
<rep>
<old>Lodge</old>
<new>SHOP</new>
</rep>
</my:reps>
<xsl:variable name="vReps" select="document('')/*/my:reps/*"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="LD/text()" name="replace">
<xsl:param name="pText" select="."/>
<xsl:choose>
<xsl:when test="not($vReps/old[contains($pText, .)])">
<xsl:value-of select="$pText"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="multiReplace">
<xsl:with-param name="pText" select="$pText"/>
<xsl:with-param name="pReps"
select="$vReps[contains($pText, old)]"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="multiReplace">
<xsl:param name="pText"/>
<xsl:param name="pReps"/>
<xsl:choose>
<xsl:when test="$pReps">
<xsl:variable name="vRepResult">
<xsl:call-template name="singleReplace">
<xsl:with-param name="pText" select="$pText"/>
<xsl:with-param name="pOld" select="$pReps[1]/old"/>
<xsl:with-param name="pNew" select="$pReps[1]/new"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="multiReplace">
<xsl:with-param name="pText" select="$vRepResult"/>
<xsl:with-param name="pReps" select="$pReps[position() >1]"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pText"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="singleReplace">
<xsl:param name="pText"/>
<xsl:param name="pOld"/>
<xsl:param name="pNew"/>
<xsl:if test="$pText">
<xsl:choose>
<xsl:when test="not(contains($pText, $pOld))">
<xsl:value-of select="$pText"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($pText, $pOld)"/>
<xsl:value-of select="$pNew"/>
<xsl:call-template name="singleReplace">
<xsl:with-param name="pText" select="substring-after($pText, $pOld)"/>
<xsl:with-param name="pOld" select="$pOld"/>
<xsl:with-param name="pNew" select="$pNew"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
当这个变换所提供的XML文档应用:
<Addy>
<Row>
<LD>Dwelling, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Lodge</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
想要的,更新ECT结果产生:
<Addy>
<Row>
<LD>FLAT, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>SHOP</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
重要:
该解决方案是完整和正确的。肖恩的表现很肤浅。
<Addy>
<Row>
<LD>Dwelling, Lodge, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Lodge, Dwelling</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
肖恩的解决方案producces不正确更换:
<Addy>
<Row>
<LD>FLAT, Lodge, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Lodge, FLAT</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
目前,正确的解决办法
由两个解决方案,当下面的XML文档应用比较结果从这个答案,产生正确的替换:
<Addy>
<Row>
<LD>FLAT, SHOP, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>SHOP, FLAT</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
说明:
的身份规则 “原样” 每节点匹配它被选择用于executiom为其副本。
它由与任何LD
元素的任何文本节点子元素匹配的单个模板覆盖 - 必须完成替换的节点。
该模板检查匹配的文本节点是否包含old
(字符串值)中的任何一个,如全局内联my:reps
元素中指定的那样。为方便起见,在全局变量$vReps
中选择了所有my:reps/rep
元素,并且引用此变量。如果这些字符串都不包含在当前节点中,则将其复制到输出中。
如果至少有一个$vReps/old
元素的字符串值包含在当前匹配的文本节点中,那么我们必须进行替换。我们调用名称为"multiReplace"
的模板,该模板执行当前文本节点中的所有替换。我们将这个模板作为参数传递给当前文本节点以及所有$vReps/rep
元素的节点集,其中old
子元素的字符串值包含在当前文本节点中 - 这些都是要进行的替换。
multiReplace
模板调用名为singleReplace
的模板进行第一次替换并将结果捕获到名为$vRepResult
的变量中。这包含在$pText
全部替换(字符串值)$pReps[1]/old
的字符串值为$pReps[1]/new
的结果。然后,multiReplace
模板以递归方式调用自身,以至于$pText
参数迄今作为替换的结果以及排除第一个替换的替换节点集作为参数$pReps
。此递归的“停止条件”是$pReps
参数成为空节点集时。
的singleReplace
模板做什么它的名字一样 - 它取代了其$pText
参数包含等于$pOld
参数与包含在pNew
参数字符串任何字符串的的字符串中。替换次数可能会大于1次,但所有替换次数均为单个替换规格==>因此名称为singleReplace
。当$pText
非空且仍包含$pOld
时,替换再次以递归方式进行,并带有停止条件。
@ LarsH不幸的是我正在使用XSLT 1.0。你可以在1.0中说明这一点吗? – lee
@lee,如果你看看我链接到的页面,http://www.exslt.org/str/functions/replace/index.html,底部有一个链接,指向一个“str”的XSLT 1.0实现:替换'模板。第一页顶部附近是用于调用模板的示例代码。 – LarsH
有没有另一种方法与1.0做到这一点? – lee