XSLT代码因current-date()无法在Notepad++运行的问题排查
问题
我有一份展示员工合同详情的XML代码,需求是仅显示两类合同:
- 无终止日期的
Indefinite(无固定期限)合同 - 终止日期晚于当前日期的
Fixed-term(固定期限)合同
我编写的XSLT代码如下:
<xsl:variable name="dateM" select="current-date()"/> <xsl:template match="peci:Workers_Effective_Stack/peci:Worker/peci:Effective_Change/peci:Employee_Contract"> <xsl:if test="(((not(peci:End_Date)) or((xs:date(concat(substring(peci:End_Date,1,4),'-',substring(peci:End_Date,5,2),'-',substring(peci:End_Date,7,2)))) > $dateM))) "> <xsl:copy-of select="."/> </xsl:if> </xsl:template>
这段代码在特定在线转换器能得到预期结果,但在Notepad++或W3Schools的XSLT测试工具里无法正常运行,请问我遗漏了什么?
XML示例代码
<peci:Employee_Contract> <peci:Contract_Type>Fixed-term</peci:Contract_Type> <peci:End_Date>20190930</peci:End_Date> </peci:Employee_Contract> <peci:Employee_Contract> <peci:Contract_Type>Fixed-term</peci:Contract_Type> <peci:End_Date>20240930</peci:End_Date> </peci:Employee_Contract> <peci:Employee_Contract> <peci:Contract_Type>Fixed-term</peci:Contract_Type> <peci:End_Date>20260930</peci:End_Date> </peci:Employee_Contract> <peci:Employee_Contract> <peci:Contract_Type>Fixed-term</peci:Contract_Type> <peci:End_Date>20240620</peci:End_Date> </peci:Employee_Contract> <peci:Employee_Contract> <peci:Contract_Type>Indefinite</peci:Contract_Type> </peci:Employee_Contract>
预期输出
<peci:Employee_Contract> <peci:Contract_Type>Fixed-term</peci:Contract_Type> <peci:End_Date>20240930</peci:End_Date> </peci:Employee_Contract> <peci:Employee_Contract> <peci:Contract_Type>Fixed-term</peci:Contract_Type> <peci:End_Date>20260930</peci:End_Date> </peci:Employee_Contract> <peci:Employee_Contract> <peci:Contract_Type>Indefinite</peci:Contract_Type> </peci:Employee_Contract>
解答
无法跨环境运行的核心原因是XSLT版本支持差异,以及代码细节问题,具体修复点如下:
1. 补充XSLT基础声明与命名空间绑定
Notepad++和W3Schools的测试工具默认多使用XSLT 1.0,而你代码里的current-date()、xs:date()都是XSLT 2.0及以上的特性。必须在XSLT开头明确声明版本,并绑定XML中peci对应的命名空间:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:peci="http://实际命名空间URI" <!-- 替换为XML中peci前缀对应的真实命名空间地址 --> exclude-result-prefixes="peci">
注意:如果XML里
peci没有绑定命名空间,所有带peci:前缀的元素匹配都会失效,必须保证命名空间一致。
2. 修复条件判断的语法冗余
原代码的xsl:if条件里有多余的嵌套括号,可能导致解析错误,简化后逻辑更清晰:
<xsl:if test="not(peci:End_Date) or xs:date(concat(substring(peci:End_Date,1,4), '-', substring(peci:End_Date,5,2), '-', substring(peci:End_Date,7,2))) > $dateM">
3. 兼容XSLT 1.0环境(可选)
如果运行环境仅支持XSLT 1.0,需要替换2.0专属特性:
- 手动传入当前日期(格式为
YYYYMMDD,因该格式字符串顺序与日期顺序一致,可直接做字符串比较) - 简化日期判断逻辑:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:peci="http://实际命名空间URI" exclude-result-prefixes="peci"> <xsl:param name="current-date" select="'20240621'"/> <!-- 手动传入当前日期 --> <xsl:template match="peci:Employee_Contract"> <xsl:if test="not(peci:End_Date) or peci:End_Date > $current-date"> <xsl:copy-of select="."/> </xsl:if> </xsl:template> </xsl:stylesheet>
4. 确保模板匹配路径准确
原模板匹配的层级路径peci:Workers_Effective_Stack/peci:Worker/peci:Effective_Change/peci:Employee_Contract如果与XML实际结构不符,会导致无法匹配目标元素。可简化为直接匹配peci:Employee_Contract,确保覆盖所有目标节点。
内容的提问来源于stack exchange,提问作者Coding
相关产品推荐
相关产品推荐

