XML转Excel布局异常:XSLT重复值问题排查求助
问题分析与解决方案
你的XSLT代码核心问题是没有按DATA-S01、DATA-S02这类分组前缀来关联同组的TYPE、LINK、VER值,反而分别全局遍历所有TYPE、所有VER、所有LINK,导致每个TYPE都会和所有VER、LINK组合输出,这就是你看到的重复值问题。
具体错误点:
- 嵌套的
//VAR[contains(@NAME, 'VER')]和//VAR[contains(@NAME, 'LINK')]是全局路径查询,会返回XML里所有的VER和LINK值,而不是当前TYPE所属分组的对应值。 - 没有提取每个
VAR的分组标识(比如DATA-S01),无法把同组的三个属性关联到同一行。
修正后的XSLT代码
我们用Muenchian分组法(XSLT1.0的标准分组方案)来按分组前缀聚合数据,确保每组的三个属性输出到同一行:
<xsl:stylesheet version="1.0" xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:my-scripts" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <!-- 1. 定义分组键:按VAR的分组前缀(比如DATA-S01)分组 --> <xsl:key name="group-by-prefix" match="VAR" use="substring-before(@NAME, '-')"/> <xsl:template match="/"> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <xsl:apply-templates/> </Workbook> </xsl:template> <xsl:template match="FILE"> <Worksheet> <xsl:attribute name="ss:Name">Sheet1</xsl:attribute> <!-- 可以自定义工作表名 --> <Table x:FullColumns="1" x:FullRows="1"> <!-- 2. 先输出表头(可选,根据你的预期输出可以添加) --> <Row> <Cell><Data ss:Type="String">TYPE</Data></Cell> <Cell><Data ss:Type="String">VER</Data></Cell> <Cell><Data ss:Type="String">LINK</Data></Cell> </Row> <!-- 3. 遍历所有唯一的分组前缀 --> <xsl:for-each select="VAR[contains(@NAME, '-TYPE')]"> <xsl:variable name="current-prefix" select="substring-before(@NAME, '-TYPE')"/> <Row> <!-- 输出当前分组的TYPE值 --> <Cell><Data ss:Type="String"><xsl:value-of select="@VALUE"/></Data></Cell> <!-- 输出当前分组的VER值 --> <Cell><Data ss:Type="String"><xsl:value-of select="key('group-by-prefix', $current-prefix)[contains(@NAME, '-VER')]/@VALUE"/></Data></Cell> <!-- 输出当前分组的LINK值 --> <Cell><Data ss:Type="String"><xsl:value-of select="key('group-by-prefix', $current-prefix)[contains(@NAME, '-LINK')]/@VALUE"/></Data></Cell> </Row> </xsl:for-each> </Table> </Worksheet> </xsl:template> </xsl:stylesheet>
修正逻辑说明:
- 定义分组键:用
xsl:key把所有VAR按NAME中-之前的前缀(比如DATA-S01)分组,这样同组的三个VAR会被关联到一起。 - 遍历分组:通过
VAR[contains(@NAME, '-TYPE')]拿到所有分组的入口(每个分组都有一个TYPE),然后提取当前分组的前缀。 - 关联同组属性:用
key('group-by-prefix', $current-prefix)找到当前分组下的所有VAR,再分别筛选出-VER和-LINK对应的VALUE,输出到同一行。
这样转换后,就能得到你预期的每行对应一组DATA-S0x的TYPE、VER、LINK值的Excel输出了。
内容的提问来源于stack exchange,提问作者codex
相关产品推荐
相关产品推荐

