XSL处理WordML表格:如何判断单元格是否为第一行第一列?
问题描述
我有一个可正常运行的.xsl文件,希望添加逻辑判断当前表格单元格是否为第一行第一列,编写了如下代码:
<xsl:for-each select="w:tr"> <xsl:for-each select="w:tc[position()!=last()]"> <!-- Check if first row and if is first column --> <xsl:if test="w:tr[position()=first()] and w:tc[position()=first()]"> <xsl:text>\mcx</xsl:text> </xsl:if> <!-- Check if is first row only --> <xsl:if test="w:tr[position()=first()] and w:tc[position()!=first()]"> <xsl:text>\mc</xsl:text> </xsl:if> </xsl:for-each> </xsl:for-each>
但添加这些代码后无法应用该.xsl,移除后则恢复正常,说明判断逻辑有误。请问针对WordML的判断逻辑我是否思路错误,能否提供正确的实现方法?
解决方案
你的判断逻辑存在两个核心问题:
- 上下文错误:在嵌套的
<xsl:for-each select="w:tc">内部,当前节点是w:tc,此时用w:tr[position()=first()]会尝试在当前单元格的子节点里查找w:tr,这完全不符合WordML的结构(WordML中w:tr是行节点,w:tc是它的子节点,单元格不可能包含行)。 first()用法错误:XSLT中并没有first()函数,判断节点是否为集合中的第一个,应该使用position()=1。
正确的实现代码如下:
<xsl:for-each select="w:tr"> <!-- 定义变量记录当前行是否为第一行 --> <xsl:variable name="is-first-row" select="position()=1"/> <xsl:for-each select="w:tc[position()!=last()]"> <!-- 判断第一行第一列 --> <xsl:if test="$is-first-row and position()=1"> <xsl:text>\mcx</xsl:text> </xsl:if> <!-- 判断第一行非第一列 --> <xsl:if test="$is-first-row and position()!=1"> <xsl:text>\mc</xsl:text> </xsl:if> </xsl:for-each> </xsl:for-each>
核心改进说明:
- 外层行循环中提前定义变量
$is-first-row,通过position()=1直接判断当前行是否为第一行,避免内层循环中上下文混淆的问题。 - 内层单元格循环中,
position()的取值是相对于当前行的单元格集合的位置,直接用position()=1就能准确判断是否为当前行的第一个单元格。 - 替换了错误的
first()调用,采用XSLT标准的位置判断方式。
内容的提问来源于stack exchange,提问作者Russell Urquhart C
相关产品推荐
相关产品推荐

