XSLT1中条件设置节点集到变量失败问题求助
XSLT 1.0条件变量赋值失败的核心原因及修正
问题背景
在XSLT 1.0环境中,单独定义变量选取Mode为Midweek或Weekly的Assignment节点集时,脚本可正常运行;但使用xsl:choose进行条件赋值后,报告无法渲染。核心问题出在对XSLT 1.0变量类型和RTF限制的忽略。
忽略的XSLT 1.0核心概念
1. 变量类型:节点集 vs 结果树片段(RTF)
- 单独用
select属性定义的变量,存储的是节点集(Node-set),支持直接用XPath表达式筛选(比如$duty-assignments[@Index='15'])。 - 用
xsl:choose包裹、未指定select属性的变量,存储的是结果树片段(Result Tree Fragment, RTF)。XSLT 1.0中,RTF是只读的树结构片段,不能直接对其使用XPath轴或筛选表达式,这是导致后续变量使用失效的根本原因。
2. xsl:value-of的行为误解
你在xsl:choose中使用xsl:value-of,只会提取所有匹配节点的文本内容并拼接成字符串,完全丢失了节点的结构和属性信息。就算你想保留节点,也应该用xsl:copy-of复制节点结构,但即便如此,变量依然是RTF,无法直接用XPath查询。
3. XSLT 1.0的RTF限制
XSLT 1.0标准不支持直接操作RTF,若必须使用xsl:choose的方式,需依赖处理器扩展函数(如MSXML的msxsl:node-set())将RTF转换为节点集,但这是非标准实现,兼容性受限。
修正方案
方案一:纯标准XSLT 1.0实现(推荐)
直接在select属性中用条件表达式动态选择节点集,变量仍为节点集,无需额外处理:
<xsl:variable name="duty-assignments" select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode=if (CircuitVisit='1') then 'Weekly' else 'Midweek']/msa:Assignment"/>
方案二:使用扩展函数转换RTF(兼容原有结构)
若必须保留xsl:choose结构,需先复制节点生成RTF,再用扩展函数转为节点集(以MSXML为例):
<!-- 生成RTF --> <xsl:variable name="duty-assignments-rtf"> <xsl:choose> <xsl:when test="CircuitVisit='1'"> <xsl:copy-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekly']/msa:Assignment"/> </xsl:when> <xsl:otherwise> <xsl:copy-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Midweek']/msa:Assignment"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- 将RTF转换为节点集 --> <xsl:variable name="duty-assignments" select="msxsl:node-set($duty-assignments-rtf)/msa:Assignment" xmlns:msxsl="urn:schemas-microsoft-com:xslt"/>
额外语法错误修正
原代码中xsl:when的test属性缺少闭合引号,需修正为:
<xsl:when test="CircuitVisit='1'">
变量使用验证
修正后,原变量使用方式可正常生效:
<xsl:value-of select="$duty-assignments[@Index='15' and @IndexType='Fixed']"/>
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

