XSLT2.0+FOP2.8中position()失效及指定节点值拼接问题咨询
问题与解决方案:XML节点位置提取与XSLT修正
需求说明
- 提取XML中所有
ItemValue的内容 - 第3、4个
Item对应的ItemValue需要拼接为一个条目,其余ItemValue保持原样单独生成条目
示例XML
<node> <Item> <ItemName><![CDATA[Name]]></ItemName> <ItemValue><![CDATA[Value]]></ItemValue> </Item> <Item> <ItemName><![CDATA[Name]]></ItemName> <ItemValue><![CDATA[Value]]></ItemValue> </Item> <Item> <ItemName><![CDATA[Name]]></ItemName> <ItemValue><![CDATA[Value3]]></ItemValue> </Item> <Item> <ItemName><![CDATA[Name]]></ItemName> <ItemValue><![CDATA[Value4]]></ItemValue> </Item> <Item> <ItemName><![CDATA[Name]]></ItemName> <ItemValue><![CDATA[Value]]></ItemValue> </Item> </node>
现有XSLT代码的问题
原代码存在三处关键错误,导致Value3和Value4无法正常显示:
- 语法错误:
<xsl:when>必须包裹在<xsl:choose>中,不能直接放在<xsl:if>内部 - 跳过逻辑失效:针对第4个Item的处理没有真正跳过,循环仍会处理该节点,导致空行或错误
- 路径引用错误:拼接时使用
node/Item[position()+1]/ItemValue,这里的position()上下文混乱,无法正确获取下一个Item的内容
修正后的XSLT代码
<xsl:for-each select="node/Item"> <xsl:variable name="currentPos" select="position()"/> <xsl:variable name="cellValue"> <xsl:choose> <!-- 跳过第4个Item,因为已在第3个Item中拼接 --> <xsl:when test="$currentPos = 4"> </xsl:when> <xsl:when test="$currentPos = 3"> <xsl:value-of select="concat(ItemValue, ../Item[$currentPos + 1]/ItemValue)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="ItemValue"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:if test="$cellValue != ''"> <fo:table-row> <fo:table-cell> <fo:block> <xsl:value-of select="$cellValue"/> </fo:block> </fo:table-cell> </fo:table-row> </xsl:if> </xsl:for-each>
代码修正说明
- 新增
currentPos变量存储当前节点的位置,避免上下文混淆 - 用
<xsl:choose>替代原错误的<xsl:if>+<xsl:when>结构,保证语法合规 - 第4个Item直接输出空值,配合后续的
<xsl:if>过滤掉空行 - 拼接时使用
../Item[$currentPos + 1]/ItemValue,通过父节点定位下一个Item,确保路径正确
position()函数的正确使用场景
position()的返回值完全依赖当前的上下文环境,常见使用场景包括:
- 在
<xsl:for-each>循环中:返回当前节点在循环节点序列中的位置(从1开始计数) - 在
<xsl:apply-templates>的匹配模板中:返回当前节点在被处理节点序列中的位置 - 在节点集谓词中:比如
node/Item[position() = 3],返回节点在当前筛选出的节点集中的位置 - 注意:嵌套循环或不同节点集的谓词中,
position()的上下文会切换,必须通过变量存储当前位置避免混淆
内容的提问来源于stack exchange,提问作者Rito Sarkar
相关产品推荐
相关产品推荐

