9

我正在尝试使用 XSLT 将列表转换为不同的值列表。

输入:

<object name="obj1"/>
<object name="obj2"/>
<object name="obj1"/>

期望的输出:

<object>obj1</object>
<object>obj2</object>

有人知道如何在 XSLT 1.0 或 2.0 中完成它吗?

谢谢

4

2 回答 2

18

使用 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>
于 2013-10-10T10:10:57.657 回答
3

对于 XSLT 1.0

对象.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>

对象.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" />的函数定义索引。它必须在声明之外。key()index1xsl: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. 您为所有元素启动xsl:for-each循环//*,条件是generate-id()当前节点必须等于结果generate-id()中的第一个节点key('index1',@name)。这意味着它必须是第一个节点本身。
  9. 您使用 打印当前@namexsl:value-of。因为它只发生在key('index1',@name)结果的第一个元素上,所以它只会被打印一次。
于 2018-09-02T19:27:41.280 回答