You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何统计评估XML节点,使用XSLT生成带正确rowspan值的HTML表格

问题描述

我有一个XML文档,节点层级如下:

  • Management:包含若干Upravlinnya节点
  • Upravlinnya:包含若干viddil(部门)节点
  • viddil:包含多名员工节点

目前实现的逻辑仅对viddil层级的rowspan计算生效,其余层级的rowspan计算不正确。

现有代码

XSLT代码

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Labka -7 Kondera Sviatoslav</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Management Name</th>
<th>Upravlinnya Name</th>
<th>Viddil Name</th>
<th>Name</th>
<th>Surname</th>
<th>Birth Year</th>
</tr>
<xsl:for-each select="Managements/Management">
<xsl:for-each select="Upravlinnyas/Upravlinnya">
<xsl:for-each select="Viddils/Viddil">
<xsl:for-each select="Workers/Worker">
<tr>
<xsl:if test="position() = 1">
<td rowspan="{last()}">
<xsl:value-of select="ancestor::Management[1]/ManagementName"/>
</td>
</xsl:if>
<xsl:if test="position() = 1">
<td rowspan="{last()}">
<xsl:value-of select="ancestor::Upravlinnya[1]/UpravlinnyaName"/>
</td>
</xsl:if>
<xsl:if test="position() = 1">
<td rowspan="{last()}">
<xsl:value-of select="ancestor::Viddil[1]/ViddilName"/>
</td>
</xsl:if>
<td><xsl:value-of select="WorkerName"/></td>
<td><xsl:value-of select="WorkerSurname"/></td>
<td><xsl:value-of select="BirthYear"/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

XML示例

<?xml-stylesheet type = "text/xsl" href = "labka.xsl"?>
<Managements>
<Management id="1111">
<ManagementName>Management_1</ManagementName>
<Upravlinnyas>
<Upravlinnya id="1111">
<UpravlinnyaName>Upravlinnya_1</UpravlinnyaName>
<Viddils>
<Viddil id ="1111">
<ViddilName>Viddil_1</ViddilName>
<Workers>
<Worker id="1111">
<WorkerName>Sviatoslav</WorkerName>
<WorkerSurname>Kondera</WorkerSurname>
<BirthYear>2002</BirthYear>
</Worker>
<Worker id="2222">
<WorkerName>Orest</WorkerName>
<WorkerSurname>Rodcevich</WorkerSurname>
<BirthYear>1999</BirthYear>
</Worker>
<Worker id="3333">
<WorkerName>Olena</WorkerName>
<WorkerSurname>Zelenska</WorkerSurname>
<BirthYear>1978</BirthYear>
</Worker>
</Workers>
</Viddil>
<Viddil id ="7777">
<ViddilName>Viddil_17</ViddilName>
<Workers>
<Worker id="1111">
<WorkerName>SviatoslavNew</WorkerName>
<WorkerSurname>KonderaNew</WorkerSurname>
<BirthYear>2012</BirthYear>
</Worker>
</Workers>
</Viddil>
</Viddils>
</Upravlinnya>
</Upravlinnyas>
</Management>
<Management id="2222">
<ManagementName>Management_2</ManagementName>
<Upravlinnyas>
<Upravlinnya id="2222">
<UpravlinnyaName>Upravlinnya_2</UpravlinnyaName>
<Viddils>
<Viddil id ="2222">
<ViddilName>Viddil_2</ViddilName>
<Workers>
<Worker id="4444">
<WorkerName>Nidia</WorkerName>
<WorkerSurname>Dorofeeva</WorkerSurname>
<BirthYear>2016</BirthYear>
</Worker>
<Worker id="5555">
<WorkerName>Petro</WorkerName>
<WorkerSurname>Poroshenko</WorkerSurname>
<BirthYear>1976</BirthYear>
</Worker>
</Workers>
</Viddil>
</Viddils>
</Upravlinnya>
</Upravlinnyas>
</Management>
<Management id="3333">
<ManagementName>Management_333</ManagementName>
<Upravlinnyas>
<Upravlinnya id="3333">
<UpravlinnyaName>Upravlinnya_222</UpravlinnyaName>
<Viddils>
<Viddil id ="3333">
<ViddilName>Viddil_222</ViddilName>
<Workers>
<Worker id="6666">
<WorkerName>Marsha</WorkerName>
<WorkerSurname>May</WorkerSurname>
<BirthYear>1995</BirthYear>
</Worker>
</Workers>
</Viddil>
<Viddil id ="9999">
<ViddilName>Viddil_212</ViddilName>
<Workers>
<Worker id="1010">
<WorkerName>MarshaNew</WorkerName>
<WorkerSurname>MayNew</WorkerSurname>
<BirthYear>1905</BirthYear>
</Worker>
</Workers>
</Viddil>
</Viddils>
</Upravlinnya>
</Upravlinnyas>
</Management>
</Managements>

问题原因

原有代码中Management和Upravlinnya的rowspan取值用了last(),这个last()对应的是当前viddil下的worker总数,而不是整个Management/Upravlinnya下所有worker的总数。同时判断是否输出上层单元格的条件仅校验了当前worker是所属viddil的第一个员工,不符合上层单元格仅需在所属层级首个员工行输出一次的要求。

修正后的XSLT代码

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Labka -7 Kondera Sviatoslav</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Management Name</th>
<th>Upravlinnya Name</th>
<th>Viddil Name</th>
<th>Name</th>
<th>Surname</th>
<th>Birth Year</th>
</tr>
<xsl:for-each select="Managements/Management">
    <!-- 计算当前Management下所有员工总数 -->
    <xsl:variable name="mgmtWorkerCount" select="count(.//Worker)"/>
    <xsl:for-each select="Upravlinnyas/Upravlinnya">
        <!-- 计算当前Upravlinnya下所有员工总数 -->
        <xsl:variable name="upravWorkerCount" select="count(.//Worker)"/>
        <xsl:for-each select="Viddils/Viddil">
            <xsl:variable name="viddilWorkerCount" select="count(Workers/Worker)"/>
            <xsl:for-each select="Workers/Worker">
                <tr>
                    <!-- 仅当前Management的第一个员工行输出Management单元格 -->
                    <xsl:if test="position() = 1 and not(../preceding-sibling::Viddil) and not(../../preceding-sibling::Upravlinnya)">
                        <td rowspan="{$mgmtWorkerCount}">
                            <xsl:value-of select="ancestor::Management[1]/ManagementName"/>
                        </td>
                    </xsl:if>
                    <!-- 仅当前Upravlinnya的第一个员工行输出Upravlinnya单元格 -->
                    <xsl:if test="position() = 1 and not(../preceding-sibling::Viddil)">
                        <td rowspan="{$upravWorkerCount}">
                            <xsl:value-of select="ancestor::Upravlinnya[1]/UpravlinnyaName"/>
                        </td>
                    </xsl:if>
                    <!-- 仅当前Viddil的第一个员工行输出Viddil单元格 -->
                    <xsl:if test="position() = 1">
                        <td rowspan="{$viddilWorkerCount}">
                            <xsl:value-of select="ancestor::Viddil[1]/ViddilName"/>
                        </td>
                    </xsl:if>
                    <td><xsl:value-of select="WorkerName"/></td>
                    <td><xsl:value-of select="WorkerSurname"/></td>
                    <td><xsl:value-of select="BirthYear"/></td>
                </tr>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:for-each>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

修正说明

  1. 提前计算每个层级(Management/Upravlinnya/Viddil)下的所有员工总数,作为对应单元格的rowspan值
  2. 调整上层单元格的输出判断条件,确保每个层级的单元格只在该层级下第一个员工的行里输出一次,跨对应数量的行展示

内容的提问来源于stack exchange,提问作者Sviatoslavch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 21:36:03