这个 XSLT 2.0 转换:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*/info">
<xsl:variable name="vSeq" select="string-to-codepoints(txt)"/>
<xsl:variable name="vPatSeq" select="string-to-codepoints(@find)"/>
<xsl:sequence select=
"for $vPat in string(@find),
$vPatLength in string-length(@find)
return
index-of($vSeq, $vPatSeq[1])
[$vPat eq codepoints-to-string(subsequence($vSeq, ., $vPatLength))]
"/>
</xsl:template>
</xsl:stylesheet>
应用于提供的 XML 文档时:
<root>
<info find="ain">
<txt>The rain in Spain falls mainly in the plain.</txt>
</info>
</root>
产生正确的结果:
6 15 26 41
下面是同样简短的转换,它使用它来生成所需的 XML 结果:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*/info">
<xsl:variable name="vSeq" select="string-to-codepoints(txt)"/>
<xsl:variable name="vPatSeq" select="string-to-codepoints(@find)"/>
<find>
<xsl:copy-of select="txt"/>
<xsl:for-each select=
"for $vPat in string(@find),
$vPatLength in string-length(@find)
return
index-of($vSeq, $vPatSeq[1])
[$vPat eq codepoints-to-string(subsequence($vSeq, ., $vPatLength))]">
<hit ndx="{.}"/>
</xsl:for-each>
</find>
</xsl:template>
</xsl:stylesheet>
当此转换应用于同一个提供的 XML 文档(如上)时,会产生所需的结果:
<find>
<txt>The rain in Spain falls mainly in the plain.</txt>
<hit ndx="6"/>
<hit ndx="15"/>
<hit ndx="26"/>
<hit ndx="41"/>
</find>
或者,可以使用:
<xsl:for-each select=
"(1 to string-length(txt) -string-length($vPat) +1)
[starts-with(substring($vTxt, .), $vPat)]
">
完整的转换是:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*/info">
<xsl:variable name="vTxt" select="txt"/>
<xsl:variable name="vPat" select="string(@find)"/>
<find>
<xsl:copy-of select="txt"/>
<xsl:for-each select=
"(1 to string-length(txt) -string-length($vPat) +1)
[starts-with(substring($vTxt, .), $vPat)]
">
<hit ndx="{.}"/>
</xsl:for-each>
</find>
</xsl:template>
</xsl:stylesheet>
请注意此解决方案的简单性和直接性:
没有递归。
没有命名模板。
没有xsl:function
。
没有xsl:param
。
没有xsl:if
。
没有额外的命名空间声明。
没有substring-after()
。
没有正则表达式。
没有replace()
。
没有tokenize()
。
没有 regex-group()` s。
没有string-join()
。
没有count()
。