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()
- MSXML/IE:
- 临时树转换的作用:直接合并的节点集在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
相关产品推荐
相关产品推荐

