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

基于XSLT 2.0合并两个XML文件并去除重复邮箱

XSLT 2.0 合并XML文件并去除重复邮箱解决方案

问题核心

你当前使用<xsl:copy-of>直接复制加载的外部文件节点,这种方式会跳过XSLT的模板匹配流程,导致针对<users>的替换模板无法生效。另外手动添加<userlist>节点也属于冗余操作,可直接在XSLT中主动加载并处理两个文件。

完整解决方案代码

以下是XSLT 2.0实现代码,完成文件合并、格式统一及邮箱去重:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- 加载两个目标XML文件 -->
    <xsl:variable name="user-file" select="doc('user-list.xml')"/>
    <xsl:variable name="mail-file" select="doc('mailing-list.xml')"/>

    <!-- 提取所有唯一邮箱地址 -->
    <xsl:variable name="unique-emails" select="distinct-values(
        $user-file//email/text() | $mail-file//@email
    )"/>

    <!-- 生成合并后的根节点 -->
    <xsl:template match="/">
        <combined-users>
            <!-- 处理第一个文件的用户数据 -->
            <xsl:for-each select="$user-file//user[email = $unique-emails]">
                <user>
                    <forename><xsl:value-of select="forename"/></forename>
                    <surname><xsl:value-of select="surname"/></surname>
                    <email><xsl:value-of select="email"/></email>
                </user>
            </xsl:for-each>
            <!-- 处理第二个文件的订阅者数据,转换为统一格式 -->
            <xsl:for-each select="$mail-file//subscriber[@email = $unique-emails]">
                <user>
                    <forename><xsl:value-of select="@givenname"/></forename>
                    <surname><xsl:value-of select="@familyname"/></surname>
                    <email><xsl:value-of select="@email"/></email>
                </user>
            </xsl:for-each>
        </combined-users>
    </xsl:template>
</xsl:stylesheet>

关键知识点说明

  • 替换copy-of为apply-templates:若需修改加载文件的节点结构,必须用apply-templates触发模板匹配,而非直接复制。比如你原本想替换<users>为<list>,可修改为:
    <xsl:template match="userlist">
        <xsl:apply-templates select="$userlist"/>
    </xsl:template>
    
    <xsl:template match="users">
        <list>
            <xsl:apply-templates/>
        </list>
    </xsl:template>
    
  • 邮箱去重:利用XSLT 2.0自带的distinct-values()函数,直接提取两个文件中所有不重复的邮箱地址,再以此为依据过滤重复条目。
  • 无需手动修改原始XML:通过doc()函数直接加载目标文件,无需在原始XML中插入额外的<userlist>节点。

原始问题相关代码与文件片段

当前使用的加载代码

<!-- Load in the 2nd file, user-list.xml -->
<xsl:variable name="userlist" select="doc('user-list.xml')"/>

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

<xsl:template match="userlist">
    <xsl:copy-of select="$userlist"/>
</xsl:template>

合并后输出片段

</entry>
   <entry>
      <firstname>Endeavour</firstname>
      <lastname>Morse</lastname>
      <email>morse@tvalley.co.uk</email>
   </entry>
   <users>
      <user>
         <forename>Joe</forename>
         <surname>Bloggs</surname>
         <email>j.bloggs@sample.co.uk</email>
      </user>
      <user>

无效的模板代码

<!-- swap the word 'users' for the word 'list' - doesn't work -->
<xsl:template match="users">
    <list>
        <xsl:apply-templates />
    </list>
</xsl:template>

原始XML文件

文件1(user-list.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE users SYSTEM "user-list.dtd">
<users>
    <user>
        <forename>Joe</forename>
        <surname>Bloggs</surname>
        <email>j.bloggs@sample.co.uk</email>
    </user>
    <user>
        <forename>Winston</forename>
        <surname>Smith</surname>
        <email>w.smith@airstripOne.gov</email>
    </user>
</users>

文件2(mailing-list.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mailingList SYSTEM "mailing-list.dtd">
<mailingList>
    <subscriber familyname="Smith"
                givenname="John"
                email="j.s@somewhere.com"/>
    <subscriber givenname="Luke"
                familyname="Skyw"
                email="sov@tatooine.com"/>
<userlist/>
</mailingList>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 21:25:38