如何使用XSLT统计符合复杂条件的XML节点数量并在terminate语句中使用
解决方法
在XSLT 1.0中,你需要先把符合筛选条件的item节点预存到变量中,再通过计数判断是否需要终止转换,大多数XSLT 1.0处理器支持EXSLT的node-set扩展函数来处理结果树片段转节点集的需求,修改后的代码如下:
首先修改<xsl:stylesheet>根节点,声明EXSLT命名空间:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl">
然后修改匹配/data的模板逻辑:
<xsl:template match="/data"> <!-- 预筛选符合条件的item --> <xsl:variable name="qualified-items-rtf"> <xsl:for-each select="items/item"> <xsl:variable name="JDN_start_date"> <xsl:call-template name="JDN"> <xsl:with-param name="date" select="start_date" /> </xsl:call-template> </xsl:variable> <xsl:variable name="JDN_end_date"> <xsl:call-template name="JDN"> <xsl:with-param name="date" select="end_date" /> </xsl:call-template> </xsl:variable> <xsl:if test="($JDN_end_date - $JDN_start_date) > 1"> <!-- 复制符合条件的item节点 --> <xsl:copy-of select="." /> </xsl:if> </xsl:for-each> </xsl:variable> <!-- 转成可计数的节点集 --> <xsl:variable name="qualified-items" select="exsl:node-set($qualified-items-rtf)/item" /> <!-- 判断是否无符合条件的节点,是则终止转换 --> <xsl:if test="count($qualified-items) = 0"> <xsl:message terminate="yes">There are no items left</xsl:message> </xsl:if> <html> <head> <title></title> </head> <body> <p> <xsl:text>Name: </xsl:text> <xsl:value-of select="person/name"/> </p> <table> <thead> <tr><th>Title</th></tr> </thead> <!-- 直接遍历预筛选的节点,无需重复计算日期差 --> <xsl:for-each select="$qualified-items"> <tr> <td><xsl:value-of select="title"/></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template>
补充说明
- 如果你的XSLT处理器是微软的MSXML,需要把命名空间换成
xmlns:msxsl="urn:schemas-microsoft-com:xslt",对应的节点集函数换成msxsl:node-set()即可。 - 预筛选的逻辑只需要执行一次日期差计算,后续直接复用结果,比两次遍历计算效率更高。
内容的提问来源于stack exchange,提问作者Liam
相关产品推荐
相关产品推荐

