如何通过XSLT保留节点首次出现以移除id属性重复的rf标签
问题原因
你的原有XSLT存在两个核心错误:
- 去重作用对象错误:你直接对
<rfs>根节点做去重判断,没有精准定位到需要去重的<rf>子节点 - 重复判断逻辑错误:
not(. = preceding::node())是对比节点整体文本内容,没有按照需求校验<rf>的id属性值是否重复
可用XSLT代码
版本1:XSLT 1.0兼容版(通用所有XSLT运行环境)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- 身份转换模板:原样复制所有不需要修改的节点和属性 --> <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="node() | @*"/> </xsl:copy> </xsl:template> <!-- 匹配所有存在同id前置兄弟节点的rf,直接不输出 --> <xsl:template match="rf[preceding-sibling::rf/@id = current()/@id]"/> </xsl:stylesheet>
版本2:XSLT 2.0优化版(性能更高,适合大体积XML)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="node() | @*"/> </xsl:copy> </xsl:template> <xsl:template match="rfs"> <xsl:copy> <!-- 按id属性对rf分组,每组仅输出第一个元素 --> <xsl:for-each-group select="rf" group-by="@id"> <xsl:apply-templates select="current-group()[1]"/> </xsl:for-each-group> </xsl:copy> </xsl:template> </xsl:stylesheet>
效果说明
两个版本都完全符合你的需求:
- 相同
id属性的<rf>标签仅保留首次出现的记录 - 无重复的
id对应的<rf>标签不会被误删 - 保留原XML所有其他结构、属性、文本内容不变,输出结果和你预期的完全一致
内容的提问来源于stack exchange,提问作者user13583928
相关产品推荐
相关产品推荐

