一種更靈活的解決方案,其不使用嵌套replace()
呼叫的N個:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<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="p/text()">
<xsl:for-each select="tokenize(., ';')">
<xsl:analyze-string select="." regex="((solid)|(dotted)) (\d)">
<xsl:matching-substring>
<xsl:value-of select=
"concat(regex-group(1), ' ', 2*xs:integer(regex-group(4)), ';')"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:sequence select="."></xsl:sequence>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
甚至更通用的解決方案,其中,所述令牌的替換中指定參數(並且可以在單獨的XML文檔中指定):
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pMapping">
<mapArgOf name="solid" old="1" new="2"/>
<mapArgOf name="solid" old="2" new="4"/>
<mapArgOf name="dotted" old="1" new="2"/>
<mapArgOf name="dotted" old="2" new="4"/>
</xsl:param>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/text()">
<xsl:for-each select="tokenize(., ';')[.]">
<xsl:variable name="vTokens" select="tokenize(., '\s+')[.]"/>
<xsl:variable name="vMatch"
select="$pMapping/*[@name eq $vTokens[1] and @old eq $vTokens[2]]"/>
<xsl:value-of select=
"concat(replace(., $vTokens[2], ($vMatch/@new, $vTokens[2])[1]), ';')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
這兩個轉變,當所提供的XML文檔適用的:
<doc>
<p> solid 1; thick 2; solid 2;</p>
<p> double 2; thick 2; dotted 1;</p>
<p> dotted 1; double 2; dotted 2;</p>
<p> solid 2; thick 2; dotted 2;</p>
</doc>
產生想要的,正確的結果:
<doc>
<p> solid 2; thick 2; solid 4;</p>
<p> double 2; thick 2; dotted 2;</p>
<p> dotted 2; double 2; dotted 4;</p>
<p> solid 4; thick 2; dotted 4;</p>
</doc>
請注意:
我們可以指定儘可能多的映射(不僅適用於「soli d「和」點綴「)。
在這裏,我們不再認爲新值的兩倍舊值 - 我們甚至不假設值是一個數字
例如,如果我們要添加替代「厚」,使得1由5所取代,2月8日和3所取代由10所取代,我們只需要改變這樣的映射:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pMapping">
<mapArgOf name="solid" old="1" new="2"/>
<mapArgOf name="solid" old="2" new="4"/>
<mapArgOf name="dotted" old="1" new="2"/>
<mapArgOf name="dotted" old="2" new="4"/>
<mapArgOf name="thick" old="1" new="5"/>
<mapArgOf name="thick" old="2" new="8"/>
<mapArgOf name="thick" old="3" new="10"/>
</xsl:param>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/text()">
<xsl:for-each select="tokenize(., ';')[.]">
<xsl:variable name="vTokens" select="tokenize(., '\s+')[.]"/>
<xsl:variable name="vMatch" select=
"$pMapping/*[@name eq $vTokens[1] and @old eq $vTokens[2]]"/>
<xsl:value-of select=
"concat(replace(., $vTokens[2], ($vMatch/@new, $vTokens[2])[1]), ';')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
而現在我們又得到了新的,想要的結果:
<doc>
<p> solid 2; thick 5; solid 4;</p>
<p> double 2; thick 8; dotted 2;</p>
<p> dotted 2; double 2; dotted 4;</p>
<p> solid 4; thick 10; dotted 4;</p>
</doc>
最後,最通用的多替換解決方案看到這個答案:
XSL Multiple search and replace function
使用的,每個功能 –
@sanjay,還有一個更通用的解決方案,不使用可變數量的嵌套'replace()'函數調用。該解決方案允許指定更換的外部映射。請享用! –