如何使用XSLT 1.0将XML层级结构转换为HTML表格?
解决XSLT转换XML层级到HTML表格时Id列位置不固定的问题
你遇到的核心问题是:当前的for-each会根据节点的祖先数量生成对应数量的<td>,然后直接追加Id的<td>,导致Id列的位置随着节点层级变化而错位。要解决这个问题,我们需要固定Level列的数量(这里是4列),先填充当前节点及其祖先的Name到对应Level列,再补充空的<td>填满剩余Level列,最后固定输出Id列。
解决方案代码
<xsl:template match="/"> <table> <tr> <th>Level 1</th> <th>Level 2</th> <th>Level 3</th> <th>Level 4</th> <th>Id</th> </tr> <!-- 处理所有narrower节点,如果需要包含TopTerm,改成"//TopTerm | //narrower" --> <xsl:apply-templates select="//narrower"/> </table> </xsl:template> <xsl:template match="narrower"> <tr> <!-- 从顶层节点到当前节点输出Name,reverse保证顺序是Level1到当前层级 --> <xsl:for-each select="reverse(ancestor-or-self::*)"> <td><xsl:value-of select="@Name"/></td> </xsl:for-each> <!-- 计算需要补充的空td数量:总层级数4减去当前节点的层级深度 --> <xsl:variable name="current-level" select="count(ancestor-or-self::*)"/> <xsl:for-each select="1 to (4 - $current-level)"> <td></td> </xsl:for-each> <!-- 固定位置输出Id列 --> <td><xsl:value-of select="@Id"/></td> </tr> </xsl:template>
代码解释
- 顺序修正:
reverse(ancestor-or-self::*)会把节点的祖先+自身的顺序从「当前节点→顶层节点」反转成「顶层节点→当前节点」,这样输出的<td>正好对应Level1到当前层级的内容。 - 填充空列:通过
count(ancestor-or-self::*)获取当前节点的层级深度,用总层级数(4)减去这个深度得到需要补充的空<td>数量,确保Level列始终是4个。 - 固定Id列:最后统一输出Id的
<td>,不管节点层级如何,它都会固定在表格的最后一列。
扩展:包含TopTerm节点的行
如果你需要把TopTerm本身也生成一行,可以修改根模板的select,并添加一个通用模板匹配TopTerm和narrower:
<xsl:template match="/"> <table> <tr> <th>Level 1</th> <th>Level 2</th> <th>Level 3</th> <th>Level 4</th> <th>Id</th> </tr> <xsl:apply-templates select="//TopTerm"/> </table> </xsl:template> <xsl:template match="TopTerm | narrower"> <tr> <xsl:for-each select="reverse(ancestor-or-self::*)"> <td><xsl:value-of select="@Name"/></td> </xsl:for-each> <xsl:variable name="current-level" select="count(ancestor-or-self::*)"/> <xsl:for-each select="1 to (4 - $current-level)"> <td></td> </xsl:for-each> <td><xsl:value-of select="@Id"/></td> </tr> <!-- 递归处理子节点 --> <xsl:apply-templates select="narrower"/> </xsl:template>
这样生成的表格会包含TopTerm的行,并且所有节点的Id列都固定在最后一列,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Jack Le
相关产品推荐
相关产品推荐

