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 >