下面是用於執行多個替換成一個字符串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