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

如何用XSLT v2.0将扁平XML转换为嵌套XML?

XSLT 2.0 实现扁平XML转嵌套XML的分组去重与二级嵌套

问题

将扁平XML转换为嵌套XML时遇到以下问题:

  • 无法对相同EmployeeID元素进行分组去重
  • 不清楚如何使用for-each-group实现二级嵌套
  • 现有代码无法将Location数据纳入输出结构

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<!--XML document created Oct 28, 2022 9:43:47 AM-->
<dataroot>
  <CTMS_Simple>
    <EmployeeID>EmployeeID 1</EmployeeID>
    <DEPT_REFERENCE>DEPT 1</DEPT_REFERENCE>
    <DEPT_CODE>DEPTCC 1</DEPT_CODE>
    <DEPT_NAME>DEPTDN 1</DEPT_NAME>
    <LocationID>Location 1</LocationID>
  </CTMS_Simple>
  <CTMS_Simple>
    <EmployeeID>EmployeeID 1</EmployeeID>
    <DEPT_REFERENCE>DEPT 1</DEPT_REFERENCE>
    <DEPT_CODE>DEPTCC 1</DEPT_CODE>
    <DEPT_NAME>DEPTDN 1</DEPT_NAME>
    <LocationID>Location 2</LocationID>
  </CTMS_Simple>
  <CTMS_Simple>
    <EmployeeID>EmployeeID 2</EmployeeID>
    <DEPT_REFERENCE>DEPT 1</DEPT_REFERENCE>
    <DEPT_CODE>DEPTCC 1</DEPT_CODE>
    <DEPT_NAME>DEPTDN 3</DEPT_NAME>
    <LocationID>Location 1</LocationID>
  </CTMS_Simple>
  <CTMS_Simple>
    <EmployeeID>EmployeeID 3</EmployeeID>
    <DEPT_REFERENCE>DEPT 2</DEPT_REFERENCE>
    <DEPT_CODE>DEPTCC 2</DEPT_CODE>
    <DEPT_NAME>DEPTDN 2</DEPT_NAME>
    <LocationID>Location 4</LocationID>
  </CTMS_Simple>
</dataroot>

现有XSLT 2.0代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs xsi xsl">

    <xsl:template match="/">
        <xsl:for-each-group select="/dataroot/CTMS_Simple"
            group-by="DEPT_REFERENCE">
            <Department>
                <DEPTID><xsl:value-of select="DEPT_REFERENCE" /></DEPTID>
                <DEPTCODE><xsl:value-of select="DEPT_CODE" /></DEPTCODE>
                <DeptName><xsl:value-of select="DEVELOPMENT_NAME" /></DeptName>
                <xsl:for-each select="/dataroot/CTMS_Simple/EmployeeID[../DEPT_REFERENCE=current-grouping-key()]">
                    <Employee>
                                             <EmployeeID>
                        <xsl:value-of select="." />
                                             </EmployeeID>
                    </Employee>
                </xsl:for-each>
            </Department>
        </xsl:for-each-group>

    </xsl:template>
</xsl:stylesheet>

当前输出

<Department>
   <DEPTID>DEPT 1</DEPTID>
   <DEPTCODE>DEPTCC 1</DEPTCODE>
   <DeptName/>
   <Employee>
      <EmployeeID>EmployeeID 1</EmployeeID>
   </Employee>
   <Employee>
      <EmployeeID>EmployeeID 1</EmployeeID>
   </Employee>
   <Employee>
      <EmployeeID>EmployeeID 2</EmployeeID>
   </Employee>
</Department>
<Department>
   <DEPTID>DEPT 2</DEPTID>
   <DEPTCODE>DEPTCC 2</DEPTCODE>
   <DeptName/>
   <Employee>
      <EmployeeID>EmployeeID 3</EmployeeID>
   </Employee>
</Department>

期望输出

<Department>
   <DEPTID>DEPT 1</DEPTID>
   <DEPTCODE>DEPTCC 1</DEPTCODE>
   <DeptName/>
   <Employee>
      <EmployeeID>EmployeeID 1</EmployeeID>
<Location>
    <LocationID>Location 1</LocationID>
    <LocationID>Location 2</LocationID>
</Location>
   </Employee>
   <Employee>
      <EmployeeID>EmployeeID 2</EmployeeID>
<Location>
    <LocationID>Location 1</LocationID>
</Location>
   </Employee>
</Department>
<Department>
   <DEPTID>DEPT 2</DEPTID>
   <DEPTCODE>DEPTCC 2</DEPTCODE>
   <DeptName/>
   <Employee>
      <EmployeeID>EmployeeID 3</EmployeeID>
<Location>
    <LocationID>Location 4</LocationID>
</Location>
   </Employee>
</Department>

修正后的XSLT 2.0代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs xsi xsl">

    <xsl:template match="/">
        <!-- 第一层:按部门分组 -->
        <xsl:for-each-group select="/dataroot/CTMS_Simple" group-by="DEPT_REFERENCE">
            <Department>
                <DEPTID><xsl:value-of select="DEPT_REFERENCE"/></DEPTID>
                <DEPTCODE><xsl:value-of select="DEPT_CODE"/></DEPTCODE>
                <!-- 修正字段名错误:DEVELOPMENT_NAME改为DEPT_NAME -->
                <DeptName><xsl:value-of select="DEPT_NAME"/></DeptName>
                
                <!-- 第二层:在当前部门组内,按员工ID分组 -->
                <xsl:for-each-group select="current-group()" group-by="EmployeeID">
                    <Employee>
                        <EmployeeID><xsl:value-of select="current-grouping-key()"/></EmployeeID>
                        <!-- 收集当前员工的所有Location -->
                        <Location>
                            <xsl:for-each select="current-group()">
                                <LocationID><xsl:value-of select="LocationID"/></LocationID>
                            </xsl:for-each>
                        </Location>
                    </Employee>
                </xsl:for-each-group>
            </Department>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

代码说明

  1. 第一层分组:使用for-each-group按DEPT_REFERENCE对所有CTMS_Simple节点分组,生成对应的Department节点。
  2. 修正字段错误:将原代码中错误的DEVELOPMENT_NAME改为输入XML中的实际字段名DEPT_NAME。
  3. 二级嵌套分组:在每个部门的分组内,再次使用for-each-group按EmployeeID分组,实现员工节点的去重。
  4. Location数据处理:在每个员工的分组内,遍历当前组的所有节点,提取并输出对应的LocationID,嵌套在Location节点下。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 19:25:18