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

如何用XSL Muenchian分组实现多级别嵌套XML结构转换

Fixing XSL with Muenchian Grouping for Trailer-Output Record Association

Let's walk through how to adjust your XSL to achieve the nested structure you need—grouping first by compartment code, then by converted unit name (K → KG), all linked to the correct trailer via its ID.

First, here's a sample input XML to reference:

<root>
  <output>
    <record trailerId="T1" compartmentCode="C1" unitName="K" capacity="1000"/>
    <record trailerId="T1" compartmentCode="C1" unitName="K" capacity="1500"/>
    <record trailerId="T1" compartmentCode="C2" unitName="L" capacity="2000"/>
    <record trailerId="T2" compartmentCode="C1" unitName="K" capacity="800"/>
  </output>
  <trailer id="T1" type="Refrigerated"/>
  <trailer id="T2" type="DryVan"/>
</root>

Corrected XSL with Muenchian Grouping

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- Key 1: Group records by trailer ID + compartment code -->
  <xsl:key name="compartment-group" match="record" use="concat(@trailerId, '|', @compartmentCode)"/>
  <!-- Key 2: Group records by trailer ID + compartment code + converted unit name (K → KG) -->
  <xsl:key name="capacity-group" match="record" use="concat(@trailerId, '|', @compartmentCode, '|', translate(@unitName, 'K', 'KG'))"/>

  <xsl:template match="/root">
    <trailers>
      <!-- Loop through each trailer in the input -->
      <xsl:for-each select="trailer">
        <xsl:variable name="trailer-id" select="@id"/>
        <trailer id="{$trailer-id}" type="{@type}">
          <configurations>
            <!-- Group records by compartment code for the current trailer -->
            <xsl:for-each select="../output/record[@trailerId = $trailer-id][count(. | key('compartment-group', concat($trailer-id, '|', @compartmentCode))[1]) = 1]">
              <xsl:variable name="compartment-code" select="@compartmentCode"/>
              <compartment code="{$compartment-code}">
                <!-- Group records by converted unit name within the current compartment -->
                <xsl:for-each select="key('compartment-group', concat($trailer-id, '|', $compartment-code))[count(. | key('capacity-group', concat($trailer-id, '|', $compartment-code, '|', translate(@unitName, 'K', 'KG')))[1]) = 1]">
                  <xsl:variable name="converted-unit" select="translate(@unitName, 'K', 'KG')"/>
                  <capacity unit="{$converted-unit}">
                    <!-- Optional: Sum all capacities for this unit, or just take the first value -->
                    <xsl:value-of select="sum(key('capacity-group', concat($trailer-id, '|', $compartment-code, '|', $converted-unit))/@capacity)"/>
                  </capacity>
                </xsl:for-each>
              </compartment>
            </xsl:for-each>
          </configurations>
        </trailer>
      </xsl:for-each>
    </trailers>
  </xsl:template>
</xsl:stylesheet>

How This Works

Let's break down the key parts:

  • Muenchian Grouping Keys:
    • compartment-group ensures we only create one <compartment> per trailer-compartment pair. The concat() avoids conflicts between different trailers with the same compartment code.
    • capacity-group builds on that, adding the converted unit name (using translate() to swap K for KG) so we group records by the standardized unit.
  • Trailer-Record Association:
    We store the current trailer's ID in a variable, then filter <record> nodes to only those matching that ID.
  • Nested Grouping:
    • First, we loop through unique compartment groups for the trailer. The count(. | key(...)[1]) = 1 check identifies the first record in each group (the "group leader"), so we only create one <compartment> per group.
    • Inside each compartment, we repeat the pattern for capacity units—using the second key to group by converted unit, then creating a <capacity> node for each unique unit.
  • Capacity Handling:
    The example uses sum() to total all capacities for the same unit in a compartment. If you just need to list individual capacities instead of summing, replace the sum() call with <xsl:value-of select="@capacity"/> and adjust the loop to iterate all records in the capacity group.

Sample Output

For the input above, the output will look like this:

<trailers>
  <trailer id="T1" type="Refrigerated">
    <configurations>
      <compartment code="C1">
        <capacity unit="KG">2500</capacity>
      </compartment>
      <compartment code="C2">
        <capacity unit="L">2000</capacity>
      </compartment>
    </configurations>
  </trailer>
  <trailer id="T2" type="DryVan">
    <configurations>
      <compartment code="C1">
        <capacity unit="KG">800</capacity>
      </compartment>
    </configurations>
  </trailer>
</trailers>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:49:22