如何在XSLT 1.0中正确使用position()选择XML数据?
排查XSLT 1.0中position()匹配Table:Field节点的问题
以下是针对你遇到的position()无法正确选择
检查命名空间绑定是否正确
因为目标节点带Table:前缀,说明它属于某个XML命名空间。如果XSLT样式表中没有正确声明并绑定这个命名空间,Table:Field的匹配会失败,position()自然无法获取正确的节点位置。
解决方法:在XSLT的根元素<xsl:stylesheet>中添加命名空间声明,比如:<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:Table="http://your-namespace-uri-here">之后所有匹配
<Table:Field>的地方必须使用Table:前缀,不能省略。确认position()的上下文节点集
position()的返回值是当前节点在当前上下文节点集中的位置,而非整个文档中的位置。比如:- 如果你的模板是匹配
<TmpTable>,然后在模板内循环Table:Field,此时position()对应的是<TmpTable>下直接子节点中<Table:Field>的顺序,这是正确的:<xsl:template match="TmpTable"> <table> <xsl:for-each select="Table:Field"> <!-- 这里的position()是当前TmpTable下Field的位置 --> <tr><td>第<xsl:value-of select="position()"/>个字段</td></tr> </xsl:for-each> </table> </xsl:template> - 但如果你的模板匹配的是更宽泛的节点(比如
//*),或者用//Table:Field来遍历,此时position()的上下文是整个文档中所有<Table:Field>的集合,而非仅<TmpTable>下的,这就会导致位置计算错误。
- 如果你的模板是匹配
避免过滤操作导致的position偏移
如果你在选择节点时使用了谓词过滤(比如Table:Field[@type='text']),此时position()返回的是过滤后节点集的位置,而非原始<TmpTable>下所有<Table:Field>的位置。如果需要获取原始位置,先把所有目标节点存到变量中:<xsl:template match="TmpTable"> <xsl:variable name="all-fields" select="Table:Field"/> <table> <xsl:for-each select="$all-fields[@type='text']"> <!-- 获取原始位置:用当前节点在all-fields中的位置 --> <xsl:variable name="original-pos" select="count($all-fields[. << current()]) + 1"/> <tr><td>原始位置:<xsl:value-of select="$original-pos"/></td></tr> </xsl:for-each> </table> </xsl:template>检查是否有干扰节点
确认<TmpTable>下是否存在其他类型的子节点(比如注释、处理指令,或者非<Table:Field>的元素节点)。如果你的选择器用的是child::*而非Table:Field,position()会把这些非目标节点也计入位置,导致偏移。确保始终明确指定匹配Table:Field。
内容的提问来源于stack exchange,提问作者William YK
相关产品推荐
相关产品推荐

