基于属性的唯一xml节点

时间:2010-02-12 09:10:36

标签: xml xslt

我想使用XSLT将一组文档转换为一个结构。我有正确的转换工作来连接文档。但是,我不知道文件中是否有重复的条目,我需要将其删除。

我需要知道如何通过id属性删除这些重复项(如果存在)。所有重复项都具有相同的ID。我知道它与key和generate-id函数有关。

<root>
    <item id="1001">A</item>
    <item id="1003">C</item>
    <item id="1004">D</item>
    <item id="1002">B</item>
    <item id="1001">A</item>
    <item id="1003">C</item>
    <item id="1004">D</item>
    <item id="1005">E</item>
</root>

我需要针对上述内容进行XSLT 1.0转换,基于以下内容......

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

                                  

另外,有人能够向我解释它是如何运作的吗?一点菜鸟......

提前致谢...

2 个答案:

答案 0 :(得分:3)

通常使用generate-id()来提供解决方案,但我个人更喜欢不使用generate-id的稍微不同的变体: -

<xsl:key name="items" match="item" use="@id" />

<xsl:template match="root">
    <root>
        <xsl:copy-of select="item[count(key('items',@id)[1]|.)=1]" />
    </root>
</xsl:template>

首先,使用id属性作为查找键创建一个包含所有item元素的键。 key生成一个有效的索引,可用于查找项目。

该技术依赖于以下事实:使用|运算符创建节点集时,您将获得一组唯一的节点。换句话说,如果在|运算符的两侧找到相同的节点,它只会出现在结果集中一次。

表达式: -

 key('items',@id)

将返回具有特定ID的项目节点集。所以: -

 key('items',@id)[1]

将只返回找到的具有该特定ID且可重复的节点之一(重复使用此表达式始终返回相同的节点)。

因此表达式: -

 count(key('items',@id)[1]|.)=1

对于具有特定id值的item节点只能为true。

copy-of因此仅对具有不同ID的一个项目节点进行深层复制。

答案 1 :(得分:3)

这是@AnthonyWJones提到的generate-id()方式。我觉得这个人在人脑中更容易。结果没有区别,选择你最喜欢的。

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:key name="kItemById" match="item" use="@id" />

  <xsl:template match="root">
    <copy>
      <xsl:copy-of select="
        item[generate-id() = generate-id(key('kItemById', @id)[1])]
      " />
    </copy>
  </xsl:template>
</xsl:stylesheet>

简而言之:

item[generate-id() = generate-id(key('kItemById', @id)[1])]

表示:“所有<item> s,其唯一ID等于第一个项目的唯一ID,具有相同的@id值。”