如何限制XSLT输出中符合条件的<job>元素数量?
解决XSLT1.0中带条件过滤时限制输出
<job>数量的问题 方法一:纯XSLT实现(推荐)
核心思路是先筛选出符合输出条件的节点,再遍历并限制数量,这样position()就能准确统计实际要输出的<job>数量:
- 定义变量设定最大输出数,比如
$maxJobs - 修改
<xsl:for-each>的select表达式,直接过滤出满足PositionId和JobDescription都存在的Results节点 - 在遍历过程中用
position() <= $maxJobs判断是否输出
修改后的完整代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl in lang user" xmlns:in="http://www.composite.net/ns/transformation/input/1.0" xmlns:lang="http://www.composite.net/ns/localization/1.0" xmlns:f="http://www.composite.net/ns/function/1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:my-scripts"> <msxsl:script language="C#" implements-prefix="user"> <msxsl:assembly name="System.Web" /> <msxsl:using namespace="System.Web" /> <msxsl:using namespace="System.IO" /> <msxsl:using namespace="System.Net" /> <![CDATA[ public string HTMLDecode(string JoDesc) { string jd = JoDesc; jd = HttpUtility.HtmlDecode(jd); return jd; } ]]> </msxsl:script> <xsl:output method="xml" version="1.0" encoding="utf-8" /> <!-- 设定最大输出的job数量 --> <xsl:variable name="maxJobs" select="5"/> <xsl:template match="/"> <xsl:element name="jobs"> <!-- 直接筛选符合条件的Results节点,避免后续if判断 --> <xsl:for-each select="//Results[.//PositionId and JobDescription]"> <!-- 仅当位置小于等于设定值时输出 --> <xsl:if test="position() <= $maxJobs"> <xsl:element name="job"> <xsl:element name="client_job_id"> <xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text> <xsl:value-of select=".//PositionId" disable-output-escaping="yes" /> <xsl:text disable-output-escaping="yes">]]></xsl:text> </xsl:element> <xsl:element name="description"> <xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text> <xsl:value-of select="user:HTMLDecode(JobDescription)" disable-output-escaping="yes" /> <xsl:text disable-output-escaping="yes">]]></xsl:text> </xsl:element> </xsl:element> </xsl:if> </xsl:for-each> </xsl:element> </xsl:template> </xsl:stylesheet>
方法二:通过C#脚本实现计数器
如果你需要保留原有代码结构,不想修改for-each的筛选逻辑,可以利用已有的msxsl脚本添加计数器:
- 在C#脚本中添加静态计数器变量和判断方法
- 在输出
<job>前调用判断方法,只有计数器未达上限时才输出 - 在模板开始时重置计数器,避免多次转换时计数混乱
修改后的完整代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl in lang user" xmlns:in="http://www.composite.net/ns/transformation/input/1.0" xmlns:lang="http://www.composite.net/ns/localization/1.0" xmlns:f="http://www.composite.net/ns/function/1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:my-scripts"> <msxsl:script language="C#" implements-prefix="user"> <msxsl:assembly name="System.Web" /> <msxsl:using namespace="System.Web" /> <msxsl:using namespace="System.IO" /> <msxsl:using namespace="System.Net" /> <![CDATA[ private static int jobCounter = 0; // 设定最大job数量 private static int maxJobCount = 5; public string HTMLDecode(string JoDesc) { string jd = JoDesc; jd = HttpUtility.HtmlDecode(jd); return jd; } // 判断是否可以添加新job,同时递增计数器 public bool CanAddJob() { if (jobCounter < maxJobCount) { jobCounter++; return true; } return false; } // 重置计数器,避免多次转换时计数残留 public void ResetJobCounter() { jobCounter = 0; } ]]> </msxsl:script> <xsl:output method="xml" version="1.0" encoding="utf-8" /> <xsl:template match="/"> <!-- 转换开始时重置计数器 --> <xsl:value-of select="user:ResetJobCounter()"/> <xsl:element name="jobs"> <xsl:for-each select="//Results"> <xsl:variable name="allElementsExist"> <xsl:if test=".//PositionId and JobDescription"> <xsl:value-of select="'true'" /> </xsl:if> </xsl:variable> <!-- 同时判断元素存在性和计数器上限 --> <xsl:if test="$allElementsExist = 'true' and user:CanAddJob()"> <xsl:element name="job"> <xsl:element name="client_job_id"> <xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text> <xsl:value-of select=".//PositionId" disable-output-escaping="yes" /> <xsl:text disable-output-escaping="yes">]]></xsl:text> </xsl:element> <xsl:element name="description"> <xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text> <xsl:value-of select="user:HTMLDecode(JobDescription)" disable-output-escaping="yes" /> <xsl:text disable-output-escaping="yes">]]></xsl:text> </xsl:element> </xsl:element> </xsl:if> </xsl:for-each> </xsl:element> </xsl:template> </xsl:stylesheet>
说明
- 方法一纯XSLT实现更简洁,符合XSLT的声明式编程风格,推荐优先使用
- 方法二适合需要保留原有循环逻辑的场景,利用C#脚本的可变变量实现计数(XSLT1.0原生变量不可变,因此需要扩展脚本)
内容的提问来源于stack exchange,提问作者Drew
相关产品推荐
相关产品推荐

