我是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确实改为其他东西。提前谢谢!
答案 0 :(得分: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>
这样,您可以过滤具有以下同级lang
元素的lang
元素的每个name
元素,其中{{1}}属性的值相同。
答案 1 :(得分: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>
<强>解释强>: