使用属性选择唯一值的XSLT select distinct语句

9
我正在尝试使用XSLT将一个列表转换为不同值的列表。
输入:
<object name="obj1"/>
<object name="obj2"/>
<object name="obj1"/>

期望输出:
<object>obj1</object>
<object>obj2</object>

有人知道如何使用XSLT 1.0或2.0完成这个任务吗?
谢谢。
2个回答

19

使用XSLT 2.0

<xsl:for-each select="distinct-values(//object/@name)">
  <object><xsl:value-of select="."/></object>
</xsl:for-each>
或者
<xsl:for-each-group select="//object" group-by="@name">
  <object><xsl:value-of select="current-grouping-key()"/></object>
</xsl:for-each-group>

1
对我来说,出现了这个错误:'distinct-values()'是未知的XSLT函数。 - shanmugharaj
1
你需要使用XSLT 2处理器来运行那段代码。 - Martin Honnen
请问您能告诉我如何做到这一点吗?我正在使用C#。 - shanmugharaj
我从你的 回答 中得到了一个链接。谢谢! - shanmugharaj
@MartinHonnen distinct-values() 返回的是 xs:anyAtomicType。但如果我有一个返回类型为 attribute()* 的函数,并且我想返回去重后的属性,该怎么办? - Martynas Jusevičius
1
@MartynasJusevičius,我认为你应该将其作为一个单独的问题提出来,不清楚你是想根据节点ID还是属性值去重。但是使用<for-each-group select="$attribute-sequence" group-by="."><xsl:sequence select="."/></xsl:for-each-group>可以根据属性值进行去重。对于节点ID,使用$attribute-sequence/.即可。 - Martin Honnen

3

针对XSLT 1.0版本

objects.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="objects.xsl"?>
<objects>
  <object id="id1" name="obj1"/>
  <object id="id2" name="obj2"/>
  <object id="id3" name="obj1"/>
</objects>

objects.xsl:

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

    <xsl:key name="index1" match="*" use="@name" />

    <xsl:template match="/">
        <objects>
        <xsl:for-each select="//*[generate-id() = generate-id(key('index1',@name)[1])]">
            <object><xsl:value-of select="@name"/></object>
        </xsl:for-each>
        </objects>
    </xsl:template>

</xsl:stylesheet>

这里发生了什么:
1.通过<xsl:key name="index1" match="*" use="@name" />,定义了一个名为index1的索引用于 key() 函数。它必须在xsl:template声明之外。
2.使用match="*",定义所有元素都适用。
3.使用use="@name",定义index1的搜索条件。
4.现在,key("index1","obj1")将返回由属性@name等于"obj1"的节点组成的数组:[<object name="obj1" id="id1"/>,<object name="obj1" id="id3"/>]。
5.你需要使用generate-id()函数来为给定节点生成唯一ID。
6.带参数调用generate-id(<object name="obj1" id="id1"/>)将返回类似于"id0xfffffffff6ddca80obj1"的内容。
7.不带参数调用,generate-id()将返回当前节点的ID。
8.你开始循环 //* 的所有元素,并且当前节点的generate-id()必须等于从 key('index1',@name) 结果中选取的第一个节点的generate-id()。这意味着它必须是第一个节点本身。
9.你使用 xsl:value-of 输出当前的 @name 值。由于它仅在 key('index1',@name) 结果的第一个元素中发生,因此只会输出一次。

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