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

基于XSLT恒等变换实现新增分组表头记录的技术求助

Solution for XSLT Identity Transform with Dynamic Header Insertion

Let's break this down with a concrete example—since abstract requirements can be tricky to map to code. First, I'll assume a sample input XML structure, then show you the XSLT that handles the header insertion when a target element's value changes across sibling records.

Sample Input XML

Suppose we have a list of order records, and we need to insert a header whenever the CustomerID value changes:

<Orders>
  <Order>
    <CustomerID>ALFKI</CustomerID>
    <OrderID>10643</OrderID>
    <Product>Chai</Product>
  </Order>
  <Order>
    <CustomerID>ALFKI</CustomerID>
    <OrderID>10692</OrderID>
    <Product>Chang</Product>
  </Order>
  <Order>
    <CustomerID>ANATR</CustomerID>
    <OrderID>10308</OrderID>
    <Product>Aniseed Syrup</Product>
  </Order>
  <Order>
    <CustomerID>ANATR</CustomerID>
    <OrderID>10625</OrderID>
    <Product>Chef Anton's Cajun Seasoning</Product>
  </Order>
</Orders>

XSLT Solution (2.0+)

This uses the identity transform as the base, plus <xsl:for-each-group> to group records by the target element (CustomerID here). We'll insert a modified header at the start of each group:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- Identity transform: copy all nodes/attributes by default -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- Override the Orders element to handle grouping -->
  <xsl:template match="Orders">
    <xsl:copy>
      <!-- Group Order records by CustomerID -->
      <xsl:for-each-group select="Order" group-by="CustomerID">
        <!-- Insert modified header: use first group's Order as base, tweak content -->
        <Order>
          <CustomerID>HEADER: <xsl:value-of select="current-grouping-key()"/></CustomerID>
          <OrderID>---</OrderID>
          <Product>Customer Orders</Product>
        </Order>
        <!-- Output all records in the current group -->
        <xsl:apply-templates select="current-group()"/>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

What This Does

  • Identity Transform Base: The first template ensures all existing nodes are copied exactly unless we override them—this preserves your original XML structure for everything except the grouped records.
  • Grouping Logic: The <xsl:for-each-group> clause groups all Order siblings by CustomerID. Whenever the CustomerID changes, a new group starts.
  • Header Insertion: For each group, we first create a modified Order node (matching the sibling record format) as the header. Here, we prepend "HEADER:" to the CustomerID, set OrderID to "---", and change Product to a label—adjust these modifications to fit your specific needs.
  • Output Group Records: After inserting the header, we apply the identity transform to output all records in the current group.

If You're Stuck on XSLT 1.0

If you can't use XSLT 2.0+, you'll need Muenchian grouping instead. Here's a quick adaptation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="orders-by-customer" match="Order" use="CustomerID"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Orders">
    <xsl:copy>
      <!-- Process each unique CustomerID group -->
      <xsl:for-each select="Order[generate-id() = generate-id(key('orders-by-customer', CustomerID)[1])]">
        <!-- Insert header -->
        <Order>
          <CustomerID>HEADER: <xsl:value-of select="CustomerID"/></CustomerID>
          <OrderID>---</OrderID>
          <Product>Customer Orders</Product>
        </Order>
        <!-- Output all orders in this customer's group -->
        <xsl:apply-templates select="key('orders-by-customer', CustomerID)"/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Key Notes for Your Specific Use Case

  • Replace CustomerID with the actual element you're checking for value changes.
  • Adjust the header modifications to match your requirements (e.g., change different elements, add new attributes, etc.).
  • If your sibling records are nested under a different parent element, update the template match (instead of Orders, match your parent element).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:33:39