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

XSL 1.0合并XML元素去重模板失效问题及解决方案

解决XSLT 1.0合并双节点集并去重时无法遍历合并结果的问题

问题分析

你遇到的是XSLT 1.0的典型限制:直接合并两个参数传入的节点集时,部分处理器无法将$nodes1 | $nodes2识别为可正常遍历的节点集,但单个节点集参数不存在这个问题。尝试Muenchian方法无效,核心原因是合并后的节点集未被正确解析为可操作的节点集合。

示例代码复现

测试XML

<root>
  <listA>
    <item id="1">Item 1</item>
    <item id="2">Item 2</item>
  </listA>
  <listB>
    <item id="2">Item 2</item>
    <item id="3">Item 3</item>
  </listB>
</root>

故障模板代码

<xsl:template name="merge-and-deduplicate">
  <xsl:param name="nodes1"/>
  <xsl:param name="nodes2"/>
  <xsl:variable name="combined-nodes" select="$nodes1 | $nodes2"/>
  
  <!-- 此处for-each无法正常遍历$combined-nodes -->
  <xsl:for-each select="$combined-nodes">
    <xsl:copy-of select="."/>
  </xsl:for-each>
</xsl:template>

解决方案:node-set扩展函数+Muenchian分组

XSLT 1.0中需要通过node-set()扩展函数,将合并后的临时节点树转换为标准可遍历节点集,再结合Muenchian分组实现去重。

修正后的完整代码

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                exclude-result-prefixes="msxsl">

<!-- 按item的id定义去重键 -->
<xsl:key name="unique-item" match="item" use="@id"/>

<xsl:template name="merge-and-deduplicate">
  <xsl:param name="nodes1"/>
  <xsl:param name="nodes2"/>
  
  <!-- 第一步:将合并的节点集存入临时XML树 -->
  <xsl:variable name="temp-merged">
    <xsl:copy-of select="$nodes1 | $nodes2"/>
  </xsl:variable>
  <!-- 第二步:用node-set转换为可遍历的节点集 -->
  <xsl:variable name="merged-nodes" select="msxsl:node-set($temp-merged)/*"/>
  
  <!-- Muenchian分组去重:只保留每个id对应的第一个节点 -->
  <xsl:for-each select="$merged-nodes[generate-id() = generate-id(key('unique-item', @id)[1])]">
    <xsl:copy-of select="."/>
  </xsl:for-each>
</xsl:template>

<!-- 调用模板的示例 -->
<xsl:template match="/">
  <merged-result>
    <xsl:call-template name="merge-and-deduplicate">
      <xsl:with-param name="nodes1" select="/root/listA/item"/>
      <xsl:with-param name="nodes2" select="/root/listB/item"/>
    </xsl:call-template>
  </merged-result>
</xsl:template>

</xsl:stylesheet>

关键说明

  • node-set()的兼容性:不同处理器的扩展命名空间不同,需对应调整:
    • MSXML/IE:msxsl:node-set()
    • Saxon:saxon:node-set()
    • Xalan:xalan:node-set()
  • 临时树转换的作用:直接合并的节点集在XSLT 1.0中可能被视为“结果树片段”而非节点集,无法遍历;存入临时变量后通过node-set()转换,才能成为可操作的节点集合。
  • Muenchian分组去重:通过generate-id()匹配同id节点的第一个实例,确保每个唯一节点只输出一次。

最终输出

<merged-result>
  <item id="1">Item 1</item>
  <item id="2">Item 2</item>
  <item id="3">Item 3</item>
</merged-result>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 13:21:28