xslt本身并没有提供现成的split方法让我们对给定的查询字符串进行有效的分隔,不过我们可以借助于substring-before和substring-after函数来实现split的效果。先看一个应用需求:
要进行格式化的xml文档内容
<Items>
<ItemA>a</ItemA>
<ItemB>b</ItemB>
<ItemC>c</ItemC>
<ItemD>d</ItemD>
<ItemE>e</ItemE>
</Items>
用于查找节点内容的xslt文档
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:param name="tag"/>
<xsl:template match="/">
<xsl:value-of select="//*[name() = $tag]" disable-output-escaping="yes"/>
</xsl:template>
</xsl:stylesheet>
将要查找的节点名称作为参数tag的值传递给上述xslt文档,它便能将xml文档中相关节点中的内容输出到页面上,如果xml文档节点中存储的是html标记内容,则在页面上显示的就是具有实际意义的超文本标记,这个是通过disable-output-escaping="yes"属性来决定的,如果该属性的值为false,则html标记会原样输出到页面上。
现在的问题是,我想要上述xslt文档能通过接收到的参数输出多个匹配的xml节点中的内容,如接收到的参数为"ItemA,ItemB,ItemC",则在页面上依次输出这三个节点中的内容,怎么实现呢?最先想到的办法就是在xslt中实现一个类似于split函数的功能,对参数tag的值进行分解,最好是能将分解后的结果存放到数组中,然后遍历数组依次输出检索到的结果。但是xslt中没有split函数,而且也没有数组这种“高级”数据结构,xslt本身是xml文档,它只能实现一些比较简单的逻辑和运算。事实上,在xslt的XPath函数中有两个函数可以实现我们的需求。
substring-before(string1, string2)函数:返回string2在string1中出现之前的子字符串,如substring-before("ItemA,ItemB,ItemC", ",")返回的结果是"ItemA"。
substring-after(string1, string2)函数:返回string2在string1中出现之后的子字符串,如substring-after("ItemA,ItemB,ItemC", ",")返回的结果是"ItemB,ItemC"。
有了这两个函数我们就可以实现上面所说的类似于split函数的功能了,下面是修改后的xslt文档的代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:param name="tag"/>
<xsl:template match="/">
<xsl:call-template name="output-tokens">
<xsl:with-param name="list" select="$tag"/>
<xsl:with-param name="separator">,</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="output-tokens">
<xsl:param name="list"/>
<xsl:param name="separator"/>
<xsl:variable name="newlist" select="concat(normalize-space($list), $separator)"/>
<xsl:variable name="first" select="substring-before($newlist, $separator)"/>
<xsl:variable name="remaining" select="substring-after($newlist, $separator)"/>
<xsl:value-of select="//*[name() = $first]" disable-output-escaping="yes"/>
<br/>
<xsl:if test="substring-before($remaining, $separator) != ''">
<xsl:call-template name="output-tokens">
<xsl:with-param name="list" select="$remaining"/>
<xsl:with-param name="separator" select="$separator"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
方法output-tokens用来进行字符串的拆分并在循环中依次输出查询结果,基本思路就是不断地调用substring-before和substring-after这两个函数逐步拆分分解出来的字符串,直到分解完毕。