使用XSLT在简单的XML文件中删除重复条目

3

我是XSLT的新手,正在尝试从一个简单的XML文件中删除重复元素,但一直无法得到正确的结果。我花了很多时间尝试,但始终无法解决问题。以下是源文件:

<?xml version="1.0" encoding="UTF-16"?>
<language>
    <lang name="welcome">welcom</lang>
    <lang name="open">Open</lang>
    <lang name="close">Close</lang>
    <lang name="welcome">Welcome</lang>
    <lang name="copy">Copy</lang>
</language>

期望的输出如下所示:
<?xml version="1.0" encoding="UTF-16"?>
<language>
    <lang name="open">Open</lang>
    <lang name="close">Close</lang>
    <lang name="welcome">Welcome</lang>
    <lang name="copy">Copy</lang>
</language>

实际文件比这要大得多,"lang"和"name"在文件后面可能会改变,我只想保留最后一个重复的。基本上,如果标签和属性是重复的,只保留最后一个条目。我希望这可以用XSLT 1.0实现。如果不行,如果lang更改为其他内容,我总是可以使用多个脚本。提前感谢您!

您在问题中提到了属性。您的 lang 元素上是否可以有多个属性,还是只能有一个 name 属性? - Tim C
可能会有更多的属性,但标签和名称属性是我需要比较的唯一属性。如果出现其他属性,也将是相同的。 - CosmicDan
2个回答

5
以下 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>
    <xsl:template match="lang[@name=following-sibling::lang/@name]"/>
</xsl:stylesheet>

通过这种方式,您可以过滤每个具有相同 name 属性值的后续同级 lang 元素。


1

比目前被接受的答案的平方时间复杂度(O(N^2))更为普遍和高效的线性解决方案。这在处理大型XML文档时尤为重要,因为OP已经告诉我们实际文档是如此。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kLangByName" match="lang" use="@name"/>

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

 <xsl:template match=
 "lang[not(generate-id()
      =
       generate-id(key('kLangByName', @name)[last()]))]"/>
</xsl:stylesheet>

当应用此转换到提供的 XML 文档时:

<language>
    <lang name="welcome">welcom</lang>
    <lang name="open">Open</lang>
    <lang name="close">Close</lang>
    <lang name="welcome">Welcome</lang>
    <lang name="copy">Copy</lang>
</language>

所需的正确结果已生成

<language>
   <lang name="open">Open</lang>
   <lang name="close">Close</lang>
   <lang name="welcome">Welcome</lang>
   <lang name="copy">Copy</lang>
</language>
解释:

使用 Muenchian 分组方法


1
嘿,谢谢你。是的,那是一大批数据,但不算巨大,并且不需要定期运行。但我明白你的意思,所以感谢你为将来提供的提示 :) - CosmicDan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接