基于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
相关产品推荐
相关产品推荐

