i'm trying to transform a list to a distinct values list using XSLT.
Input:
<object name="obj1"/>
<object name="obj2"/>
<object name="obj1"/>
Desired output:
<object>obj1</object>
<object>obj2</object>
Somebody an idea how to get it done either in XSLT 1.0 or 2.0?
THX
The fn:distinct-values function returns a sequence of unique atomic values from $arg . Values are compared based on their typed value. Values of different numeric types may be equal, for example the xs:integer value 1 is equal to the xs:decimal value 1.0, so the function only returns one of these values.
The <xsl:attribute> element creates an attribute in the output document, using any values that can be accessed from the stylesheet. The element must be defined before any other output document element inside the output document element for which it establishes attribute values.
Specifies the format pattern. Here are some of the characters used in the formatting pattern: 0 (Digit)
Definition and Usage. The <xsl:text> element is used to write literal text to the output. Tip: This element may contain literal text, entity references, and #PCDATA.
For 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>
What is happening here:
<xsl:key name="index1" match="*" use="@name" />
you define an index for key()
function named index1
. It must be outside of xsl:template
declaration.match="*"
you define that it is suitable for all elements.use="@name"
you define a search criteria for index1
.key("index1","obj1")
will return an array consists of nodes where attribute @name
equals "obj1"
: [<object name="obj1" id="id1"/>
,<object name="obj1" id="id3"/>
].generate-id()
function that generates unique ID for a given node.<object name="obj1" id="id1"/>
) will return something like "id0xfffffffff6ddca80obj1"
.generate-id()
will return an ID for a current node.xsl:for-each
cycle for all elements //*
with condition that generate-id()
of current node must be equal to generate-id()
of a first node from key('index1',@name)
result. Which means it must be the first node itself.@name
value with xsl:value-of
. Since it happens only for a first element of key('index1',@name)
result, it will be printed only once.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With