我。 XSLT 1.0 解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="ext">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vrtfContainer">
<html>
<p>Hello, world.</p>
<p> This is <b>just</b> a <i>demo.</i></p>
<p> Of some text</p>
</html>
</xsl:variable>
<xsl:variable name="vContainer" select=
"ext:node-set($vrtfContainer)/*"/>
<xsl:variable name="vrtfSnippet">
<p>Snippet</p>
</xsl:variable>
<xsl:variable name="vSnippet" select=
"ext:node-set($vrtfSnippet)/*"/>
<xsl:variable name="vText" select=
"($vContainer//text()[contains(.,'.')])[last()]"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="$vContainer"/>
</xsl:template>
<xsl:template match="text()">
<xsl:choose>
<xsl:when test="not(generate-id() = generate-id($vText))">
<xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="insertSnippet">
<xsl:with-param name="pText" select="$vText"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="insertSnippet">
<xsl:param name="pText"/>
<xsl:copy-of select="substring-before($pText, '.')"/>
<xsl:variable name="vTail" select=
"substring-after($pText, '.')"/>
<xsl:choose>
<xsl:when test="not(contains(substring($vTail,2), '.'))">
<xsl:copy-of select="$vSnippet"/>
<xsl:value-of select="concat('.', $vTail)"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>.</xsl:text>
<xsl:call-template name="insertSnippet">
<xsl:with-param name="pText"
select="substring-after($pText, '.')"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
当这个转换被应用(到任何 XML 文档——未使用)时,就会产生想要的正确结果:
<html>
<p>Hello, world.</p>
<p> This is <b>just</b> a <i>demo
<p>Snippet</p>.</i></p>
<p> Of some text</p>
</html>
说明:标识规则被递归命名模板覆盖,以查找字符串中的最后一个'.'。
二。 XSLT 2.0 解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vContainer">
<html>
<p>Hello, world.</p>
<p> This is <b>just</b> a <i>demo.</i></p>
<p> Of some text</p>
</html>
</xsl:variable>
<xsl:variable name="vSnippet">
<p>Snippet</p>
</xsl:variable>
<xsl:variable name="vText" select=
"($vContainer//text()[contains(.,'.')])[last()]"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="$vContainer/*"/>
</xsl:template>
<xsl:template match="text()[. is $vText]">
<xsl:variable name="vInd" select=
"index-of(string-to-codepoints(.), string-to-codepoints('.'))[last()]"/>
<xsl:sequence select="substring(., 1, $vInd -1)"/>
<xsl:sequence select="$vSnippet/*"/>
<xsl:sequence select="substring(., $vInd)"></xsl:sequence>
</xsl:template>
</xsl:stylesheet>
当执行此 XSLT 2.0 转换时,再次产生所需的正确结果:
<html>
<p>Hello, world.</p>
<p> This is <b>just</b> a <i>demo
<p>Snippet</p>.</i></p>
<p> Of some text</p>
</html>
说明:使用标准XPath 2.0函数string-to-codepoints()、index-of()、substring()和运算符is。