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

如何用XSLT 2.0拆分含detail元素的大型XML文件?

可以用XSLT 2.0实现该拆分需求

完全可以通过XSLT 2.0配合Saxon工具实现这个XML拆分需求。以下是具体实现方案:

核心XSLT代码

这段XSLT会遍历每个<item>,将其下的<detail>按指定数量分组,每个分组生成一个独立的XML文件,保留原<item>的所有非<detail>结构,仅替换对应分组的<detail>元素:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- 可配置参数:每个文件包含的detail数量,默认2 -->
    <xsl:param name="detail-per-file" select="2"/>

    <!-- 匹配根节点,启动处理流程 -->
    <xsl:template match="/">
        <xsl:apply-templates select="payment/item"/>
    </xsl:template>

    <!-- 处理每个item元素 -->
    <xsl:template match="item">
        <!-- 获取当前item的所有detail元素(无论嵌套层级) -->
        <xsl:variable name="all-details" select=".//detail"/>
        <xsl:variable name="item-id" select="id"/>
        <xsl:variable name="item-name" select="name"/>

        <!-- 如果当前item没有detail,直接生成一个文件 -->
        <xsl:if test="not($all-details)">
            <xsl:result-document href="item-{$item-id}-0.xml" method="xml" indent="yes">
                <xsl:copy-of select="."/>
            </xsl:result-document>
            <xsl:continue/>
        </xsl:if>

        <!-- 对detail进行分组,每组$detail-per-file个 -->
        <xsl:for-each-group select="$all-details" group-adjacent="floor((position()-1) div $detail-per-file)">
            <xsl:variable name="group-index" select="current-grouping-key() + 1"/>
            <!-- 生成输出文件,命名规则:item-<id>-<分组序号>.xml -->
            <xsl:result-document href="item-{$item-id}-{$group-index}.xml" method="xml" indent="yes">
                <item>
                    <!-- 复制item下所有非detail的节点,递归处理时替换detail为当前分组的内容 -->
                    <xsl:apply-templates select="parent::*/.." mode="copy-with-grouped-details">
                        <xsl:with-param name="current-group" select="current-group()"/>
                    </xsl:apply-templates>
                </item>
            </xsl:result-document>
        </xsl:for-each-group>
    </xsl:template>

    <!-- 递归复制节点,遇到detail时替换为当前分组的对应元素 -->
    <xsl:template match="node() | @*" mode="copy-with-grouped-details">
        <xsl:param name="current-group"/>
        <xsl:copy>
            <xsl:apply-templates select="@*" mode="copy-with-grouped-details">
                <xsl:with-param name="current-group" select="$current-group"/>
            </xsl:apply-templates>
            <!-- 匹配detail节点,只保留当前分组中的对应元素 -->
            <xsl:if test="not(local-name()='detail')">
                <xsl:apply-templates select="node()" mode="copy-with-grouped-details">
                    <xsl:with-param name="current-group" select="$current-group"/>
                </xsl:apply-templates>
            </xsl:if>
            <!-- 插入当前分组的detail到原位置 -->
            <xsl:if test="local-name()='header'">
                <xsl:copy-of select="$current-group[parent::header is current()]"/>
            </xsl:if>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Java调用Saxon执行XSLT的示例代码

使用Saxon HE/PE/EE版本(需确保版本支持XSLT 2.0,推荐9.9及以上),通过Java API执行上述XSLT:

import net.sf.saxon.s9api.*;
import java.io.File;

public class XmlSplitter {
    public static void main(String[] args) throws Exception {
        // 初始化Saxon处理器
        Processor processor = new Processor(false);
        XsltCompiler compiler = processor.newXsltCompiler();

        // 加载XSLT文件
        XsltExecutable executable = compiler.compile(new File("splitter.xsl"));
        XsltTransformer transformer = executable.load();

        // 设置输入XML文件
        DocumentBuilder builder = processor.newDocumentBuilder();
        XdmNode input = builder.build(new File("input.xml"));
        transformer.setInitialContextNode(input);

        // 设置参数:每个文件包含2个detail
        transformer.setParameter(new QName("detail-per-file"), new XdmAtomicValue(2));

        // 执行转换(输出文件由XSLT中的xsl:result-document自动生成)
        transformer.transform();
    }
}

关键说明

  • 参数配置:通过$detail-per-file参数可以灵活调整每个文件中的<detail>数量,无需修改XSLT核心逻辑
  • 文件命名:采用item-<id>-<分组序号>.xml的命名规则,避免文件覆盖,同时方便溯源原数据
  • 嵌套处理:递归模板会自动处理<detail>在不同嵌套层级的情况(比如<type_a>/<header>或<type_b>/<header>下的<detail>)
  • 空情况处理:如果<item>下没有<detail>,会直接生成一个包含完整<item>的文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:30:03