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

求助:如何用XSLT按每5个JournalEntry节点拆分XML文档

XSLT 2.0实现按每5个JournalEntry拆分XML文档

需求概述

需要将输入XML中的JournalEntry节点按每5个一组拆分,每个分组生成完整的JournalFileData结构(包含原AccountingData下的所有公共节点,如Locked、Company等),最终所有分组包裹在FileList的File节点中。

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<JournalFileData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:js="urn:com.journal/JournalSource" js:Add="false">
<AccountingData>
    <Locked>0</Locked>
    <Company js:type="Organization_Reference_ID">Some Company</Company>
    <Currency>USD</Currency>
    <Ledger>ACTUALS</Ledger>
    <Date>12-15-2021</Date>
    <Journal>Manual</Journal>
    <JournalEntry>
        <LineCompany js:type="Company">Widget Company</LineCompany>
        <LedgerAccount js:type="Ledger_Account_ID">1000</LedgerAccount>
        <CreditAmount>100</CreditAmount>
        <Currency>USD</Currency>
    </JournalEntry>
    <JournalEntry>
        <LineCompany js:type="Organization">Global Company</LineCompany>
        <LedgerAccount js:type="Ledger_Account_ID">9999</LedgerAccount>
        <DebitAmount>100</DebitAmount>
        <Currency>USD</Currency>
    </JournalEntry>
    <JournalEntry>
        <LineCompany js:type="Company">JAG Company</LineCompany>
        <LedgerAccount js:type="Ledger_Account_ID">1000</LedgerAccount>
        <DebitAmount>100</DebitAmount>
        <Currency>USD</Currency>
    </JournalEntry>
    <JournalEntry>
        <LineCompany js:type="Organization">Resource Company</LineCompany>
        <LedgerAccount js:type="Ledger_Account_ID">9999</LedgerAccount>
        <DebitAmount>100</DebitAmount>
        <Currency>USD</Currency>
    </JournalEntry>
    <JournalEntry>
        <LineCompany js:type="Organization">Supply Company</LineCompany>
        <LedgerAccount js:type="Ledger_Account_ID">9999</LedgerAccount>
        <DebitAmount>100</DebitAmount>
        <Currency>USD</Currency>
    </JournalEntry>
    <JournalEntry>
        <LineCompany js:type="Company">Plain Company</LineCompany>
        <LedgerAccount js:type="Ledger_Account_ID">1000</LedgerAccount>
        <DebitAmount>100</DebitAmount>
        <Currency>USD</Currency>
    </JournalEntry>
    <JournalEntry>
        <LineCompany js:type="Organization">Gnome Company</LineCompany>
        <LedgerAccount js:type="Ledger_Account_ID">9999</LedgerAccount>
        <DebitAmount>100</DebitAmount>
        <Currency>USD</Currency>
    </JournalEntry>
</AccountingData>
</JournalFileData>

期望输出XML

<?xml version="1.0" encoding="UTF-8"?>
<FileList>
<File>
    <JournalFileData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:js="urn:com.journal/JournalSource" js:Add="false">
        <AccountingData>
            <Locked>0</Locked>
            <Company js:type="Organization_Reference_ID">Some Company</Company>
            <Currency>USD</Currency>
            <Ledger>ACTUALS</Ledger>
            <Date>12-15-2021</Date>
            <Journal>Manual</Journal>
            <JournalEntry>
                <LineCompany js:type="Company">Widget Company</LineCompany>
                <LedgerAccount js:type="Ledger_Account_ID">1000</LedgerAccount>
                <CreditAmount>100</CreditAmount>
                <Currency>USD</Currency>
            </JournalEntry>
            <JournalEntry>
                <LineCompany js:type="Organization">Global Company</LineCompany>
                <LedgerAccount js:type="Ledger_Account_ID">9999</LedgerAccount>
                <DebitAmount>100</DebitAmount>
                <Currency>USD</Currency>
            </JournalEntry>
            <JournalEntry>
                <LineCompany js:type="Company">JAG Company</LineCompany>
                <LedgerAccount js:type="Ledger_Account_ID">1000</LedgerAccount>
                <DebitAmount>100</DebitAmount>
                <Currency>USD</Currency>
            </JournalEntry>
            <JournalEntry>
                <LineCompany js:type="Organization">Resource Company</LineCompany>
                <LedgerAccount js:type="Ledger_Account_ID">9999</LedgerAccount>
                <DebitAmount>100</DebitAmount>
                <Currency>USD</Currency>
            </JournalEntry>
        </AccountingData>
    </JournalFileData>
</File>
<File>
    <JournalFileData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:js="urn:com.journal/JournalSource" js:Add="false">
        <AccountingData>
            <Locked>0</Locked>
            <Company js:type="Organization_Reference_ID">Some Company</Company>
            <Currency>USD</Currency>
            <Ledger>ACTUALS</Ledger>
            <Date>12-15-2021</Date>
            <Journal>Manual</Journal>
            <JournalEntry>
                <LineCompany js:type="Company">Plain Company</LineCompany>
                <LedgerAccount js:type="Ledger_Account_ID">1000</LedgerAccount>
                <DebitAmount>100</DebitAmount>
                <Currency>USD</Currency>
            </JournalEntry>
            <JournalEntry>
                <LineCompany js:type="Organization">Gnome Company</LineCompany>
                <LedgerAccount js:type="Ledger_Account_ID">9999</LedgerAccount>
                <DebitAmount>100</DebitAmount>
                <Currency>USD</Currency>
            </JournalEntry>
        </AccountingData>
    </JournalFileData>
</File>
</FileList>

原代码问题分析

原XSLT存在以下问题:

  1. 错误将AccountingData节点复制到FileList内部,不符合输出结构要求;
  2. 未复制AccountingData下除JournalEntry外的公共节点,导致每个分组缺少必要上下文信息;
  3. 手动编写JournalFileData的命名空间和属性,易出错且灵活性差。

修正后的XSLT代码

<?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:js="urn:com.journal/JournalSource"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs">

    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

    <!-- 匹配根节点JournalFileData -->
    <xsl:template match="/JournalFileData">
        <FileList>
            <!-- 按每5个JournalEntry分组 -->
            <xsl:for-each-group select="AccountingData/JournalEntry" group-adjacent="(position() - 1) idiv 5">
                <File>
                    <!-- 复制原JournalFileData的所有属性和命名空间 -->
                    <JournalFileData>
                        <xsl:copy-of select="@*"/>
                        <AccountingData>
                            <!-- 复制AccountingData下所有非JournalEntry的子节点 -->
                            <xsl:copy-of select="../*[not(local-name()='JournalEntry')]"/>
                            <!-- 复制当前组的JournalEntry节点 -->
                            <xsl:copy-of select="current-group()"/>
                        </AccountingData>
                    </JournalFileData>
                </File>
            </xsl:for-each-group>
        </FileList>
    </xsl:template>

    <!-- 忽略默认模板,避免输出多余内容 -->
    <xsl:template match="text()|@*"/>
</xsl:stylesheet>

代码说明

  1. 根节点匹配:直接匹配JournalFileData,确保从整个文档结构开始处理;
  2. 分组逻辑:使用group-adjacent="(position() - 1) idiv 5"实现每5个JournalEntry一组的拆分;
  3. 节点复制:
    • 用<xsl:copy-of select="@*"/>复制JournalFileData的所有属性和命名空间,保证结构一致性;
    • 用<xsl:copy-of select="../*[not(local-name()='JournalEntry')]"/>复制AccountingData下的公共节点;
    • 用current-group()获取当前分组的JournalEntry节点并复制;
  4. 默认模板抑制:添加<xsl:template match="text()|@*"/>避免输出原文档中未匹配的多余内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:25:24