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

求助:使用Muenchian方法实现学生层级嵌套分组的XSL问题

Fixing Nested Grouping Issues in XSLT 1.0 for Student Hierarchy

The core issue with your current XSLT is that your grouping keys are global—they match all students across the entire document, not just those within the parent group context. For example, when grouping by level, you're pulling every student with that level regardless of which college they belong to, which causes undergrads to leak into grad groups and duplicate concentrations.

To fix this, we need to create composite keys that include all parent group identifiers. This ensures each nested grouping is scoped to its parent level (e.g., levels are grouped under a specific college, departments under a specific college+level, etc.).

Corrected XSLT 1.0 Code

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- Composite keys for nested grouping -->
    <xsl:key name="college-group" match="student" use="college"/>
    <xsl:key name="level-group" match="student" use="concat(college, '|', level)"/>
    <xsl:key name="dept-group" match="student" use="concat(college, '|', level, '|', department)"/>
    <xsl:key name="chair-group" match="student" use="concat(college, '|', level, '|', department, '|', chair)"/>
    <xsl:key name="concentration-group" match="student" use="concat(college, '|', level, '|', department, '|', chair, '|', concentration)"/>

    <xsl:template match="/dataroot">
        <Root>
            <!-- Level 1: Group by College -->
            <xsl:for-each select="student[generate-id() = generate-id(key('college-group', college)[1])]">
                <xsl:sort select="college" order="ascending"/>
                <college><xsl:value-of select="college"/></college>
                
                <!-- Level 2: Group by Level (scoped to current college) -->
                <xsl:for-each select="key('college-group', college)[generate-id() = generate-id(key('level-group', concat(college, '|', level))[1])]">
                    <xsl:sort select="level" order="ascending"/>
                    <!-- Map "Undergrad" to "Undergraduate" as per your desired output -->
                    <level>
                        <xsl:choose>
                            <xsl:when test="level = 'Undergrad'">Undergraduate</xsl:when>
                            <xsl:otherwise><xsl:value-of select="level"/></xsl:otherwise>
                        </xsl:choose>
                    </level>
                    
                    <!-- Level 3: Group by Department (scoped to current college+level) -->
                    <xsl:for-each select="key('level-group', concat(college, '|', level))[generate-id() = generate-id(key('dept-group', concat(college, '|', level, '|', department))[1])]">
                        <xsl:sort select="department" order="ascending"/>
                        <department><xsl:value-of select="department"/></department>
                        
                        <!-- Level 4: Group by Chair (scoped to current college+level+department) -->
                        <xsl:for-each select="key('dept-group', concat(college, '|', level, '|', department))[generate-id() = generate-id(key('chair-group', concat(college, '|', level, '|', department, '|', chair))[1])]">
                            <xsl:sort select="chair" order="ascending"/>
                            <chair><xsl:value-of select="chair"/></chair>
                            
                            <!-- Level 5: Group by Concentration (scoped to current college+level+department+chair) -->
                            <xsl:for-each select="key('chair-group', concat(college, '|', level, '|', department, '|', chair))[generate-id() = generate-id(key('concentration-group', concat(college, '|', level, '|', department, '|', chair, '|', concentration))[1])]">
                                <xsl:sort select="concentration" order="ascending"/>
                                <concentration><xsl:value-of select="concentration"/></concentration>
                                
                                <!-- List students in this concentration -->
                                <xsl:for-each select="key('concentration-group', concat(college, '|', level, '|', department, '|', chair, '|', concentration))">
                                    <xsl:sort select="name_sort" order="ascending"/>
                                    <student>
                                        <name><xsl:value-of select="name"/></name>
                                    </student>
                                </xsl:for-each>
                            </xsl:for-each>
                        </xsl:for-each>
                    </xsl:for-each>
                </xsl:for-each>
            </xsl:for-each>
        </Root>
    </xsl:template>
</xsl:stylesheet>

Key Changes Explained

  1. Composite Keys: Each key combines parent group values (e.g., concat(college, '|', level)). The | is a delimiter that ensures unique combinations (adjust if your data contains pipes).
  2. Scoped Grouping: Each nested for-each uses the composite key to only select students within the current parent group, eliminating cross-group leaks.
  3. Level Mapping: Added logic to convert "Undergrad" to "Undergraduate" to match your desired output.
  4. Cleaner Structure: Removed unnecessary line breaks (&#xd;)—XSLT will preserve whitespace appropriately, but you can add them back if needed for formatting.

Output with Your Sample XML

When run against your input, this will produce exactly the structure you requested:

<Root>
    <college>College 1</college>
    <level>Undergraduate</level>
    <department>Department 1</department>
    <chair>Chair Name</chair>
    <concentration>Studio Art</concentration>
    <student>
        <name>John Doe</name>
    </student>
    <student>
        <name>Lisa James</name>
    </student>
</Root>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:56:47