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

使用XSLT实现行转列并关联对应值的问题求助

解决方案:XSLT转XML为CSV(解决重复值+空值填0)

核心思路

要实现XML转置生成CSV,需分两步处理:

  1. 提取所有唯一组件类型作为CSV表头
  2. 遍历每个数据项,匹配对应组件值,无对应组件则填充0

假设示例XML结构

<root>
  <item>
    <name>Item1</name>
    <components>
      <component>
        <type>CompA</type>
        <value>5</value>
      </component>
      <component>
        <type>CompB</type>
        <value>3</value>
      </component>
    </components>
  </item>
  <item>
    <name>Item2</name>
    <components>
      <component>
        <type>CompA</type>
        <value>2</value>
      </component>
      <component>
        <type>CompC</type>
        <value>7</value>
      </component>
    </components>
  </item>
</root>

方案1:XSLT 2.0+(简洁版)

利用distinct-values直接获取唯一组件类型,代码更简洁:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8"/>
  
  <!-- 全局变量:所有不重复的组件类型 -->
  <xsl:variable name="allComponents" select="distinct-values(/root/item/components/component/type)"/>
  
  <!-- 生成CSV表头 + 遍历数据行 -->
  <xsl:template match="/">
    <!-- 表头第一列:Item名称 -->
    <xsl:text>Item Name</xsl:text>
    <!-- 追加所有组件类型为表头列 -->
    <xsl:for-each select="$allComponents">
      <xsl:text>,</xsl:text>
      <xsl:value-of select="."/>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text> <!-- 换行 -->
    
    <!-- 处理每个数据项 -->
    <xsl:apply-templates select="/root/item"/>
  </xsl:template>
  
  <!-- 单个数据项处理逻辑 -->
  <xsl:template match="item">
    <!-- 输出Item名称 -->
    <xsl:value-of select="name"/>
    <!-- 遍历所有组件类型,匹配当前Item的对应值 -->
    <xsl:for-each select="$allComponents">
      <xsl:text>,</xsl:text>
      <!-- 存在则取value,不存在填0 -->
      <xsl:value-of select="if (components/component/type = current()) then components/component[type = current()]/value else '0'"/>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text> <!-- 换行 -->
  </xsl:template>
</xsl:stylesheet>

方案2:XSLT 1.0(兼容旧环境)

XSLT 1.0无distinct-values,需用key+generate-id实现去重:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8"/>
  
  <!-- 定义组件类型的key,用于去重 -->
  <xsl:key name="componentType" match="component/type" use="."/>
  
  <!-- 全局变量:所有不重复的组件类型 -->
  <xsl:variable name="allComponents" select="/root/item/components/component/type[generate-id() = generate-id(key('componentType', .)[1])]"/>
  
  <!-- 生成CSV表头 + 遍历数据行 -->
  <xsl:template match="/">
    <xsl:text>Item Name</xsl:text>
    <xsl:for-each select="$allComponents">
      <xsl:text>,</xsl:text>
      <xsl:value-of select="."/>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
    
    <xsl:apply-templates select="/root/item"/>
  </xsl:template>
  
  <!-- 单个数据项处理逻辑 -->
  <xsl:template match="item">
    <xsl:value-of select="name"/>
    <xsl:for-each select="$allComponents">
      <xsl:text>,</xsl:text>
      <xsl:variable name="currentType" select="."/>
      <xsl:choose>
        <xsl:when test="components/component/type = $currentType">
          <xsl:value-of select="components/component[type = $currentType]/value"/>
        </xsl:when>
        <xsl:otherwise>0</xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

输出结果示例

Item Name,CompA,CompB,CompC
Item1,5,3,0
Item2,2,0,7

问题根源说明

你之前的代码出现重复值,大概率是没有针对每个Item独立查找组件值,而是直接全局获取了第一个Item的组件值,导致所有行复用同一组数据。上述方案通过全局提取组件类型+逐Item匹配的方式,彻底解决了重复问题,同时实现了空值填0的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 00:15:56