XSLT - Using the generate-id() Function in XSLT
The generate-id() function in XSLT is used to generate a unique identifier for a particular node in an XML document. It is especially useful when you need to identify a node uniquely and create relationships between different parts of an XML document or between source nodes and generated output.
The function is commonly used in situations where you need to determine whether two variables or node references point to the same node, create links to specific XML nodes, or assign unique identifiers to dynamically generated HTML elements.
1. What is generate-id()?
generate-id() is an XSLT function that returns a string representing a unique identifier for a node.
The basic syntax is:
generate-id(node)
For example:
generate-id(book)
If the XML contains a <book> node, the function might return a value such as:
d1e5
The exact identifier is generated by the XSLT processor, so you should not depend on a particular value such as d1e5.
The important point is that the identifier can be used to distinguish one node from another.
2. Basic Example
Consider the following XML:
<library>
<book>
<title>Learning XML</title>
<author>John</author>
</book>
<book>
<title>Mastering XSLT</title>
<author>David</author>
</book>
</library>
An XSLT stylesheet can generate an ID for each book:
<xsl:for-each select="library/book">
<book-id>
<xsl:value-of select="generate-id(.)"/>
</book-id>
</xsl:for-each>
The output could look similar to:
<book-id>d1e3</book-id>
<book-id>d1e6</book-id>
The exact values depend on the XSLT processor.
3. Why Is generate-id() Useful?
XML documents often contain many nodes of the same type. For example, a document may contain hundreds of <book>, <employee>, or <product> elements.
Simply using the element name does not uniquely identify a particular node.
For example:
book
book
book
All three nodes have the same name.
generate-id() allows the processor to provide a unique identifier for each node.
Conceptually:
book 1 → ID A
book 2 → ID B
book 3 → ID C
This makes it possible to distinguish between nodes even when they have identical element names.
4. Using generate-id() with the Current Node
The period (.) represents the current context node.
For example:
<xsl:value-of select="generate-id(.)"/>
Here, generate-id(.) generates an identifier for the current node.
Inside:
<xsl:for-each select="library/book">
the current node changes to each <book> element.
Therefore:
<xsl:for-each select="library/book">
<xsl:value-of select="generate-id(.)"/>
</xsl:for-each>
generates a different identifier for each book node.
5. Comparing Two Nodes Using generate-id()
One important use of generate-id() is comparing node identities.
Suppose you have two node references:
<xsl:variable name="firstBook" select="library/book[1]"/>
<xsl:variable name="anotherBook" select="library/book[1]"/>
Both variables refer to the same XML node.
You can compare their generated IDs:
<xsl:if test="generate-id($firstBook) = generate-id($anotherBook)">
<same-node>Yes</same-node>
</xsl:if>
Since both variables point to the same node, their generated IDs will be the same.
This allows XSLT to determine whether two references identify the same node.
6. Different Nodes Have Different IDs
Consider:
<xsl:variable name="firstBook" select="library/book[1]"/>
<xsl:variable name="secondBook" select="library/book[2]"/>
Now the variables point to different nodes.
You can test them with:
<xsl:if test="generate-id($firstBook) != generate-id($secondBook)">
<different-node>Yes</different-node>
</xsl:if>
The generated IDs will be different because the nodes are different.
7. Creating HTML Links
One practical application is generating internal links in HTML.
Suppose the XML contains:
<library>
<book>
<title>Learning XML</title>
</book>
<book>
<title>Mastering XSLT</title>
</book>
</library>
An XSLT stylesheet can generate a link for every book:
<xsl:for-each select="library/book">
<a href="#{generate-id(.)}">
<xsl:value-of select="title"/>
</a>
</xsl:for-each>
The generated HTML may look conceptually like:
<a href="#d1e3">Learning XML</a>
<a href="#d1e6">Mastering XSLT</a>
The generated IDs can then be used as targets.
8. Creating Matching HTML Anchors
The same generated ID can be assigned to an HTML element.
For example:
<xsl:for-each select="library/book">
<div id="{generate-id(.)}">
<h2>
<xsl:value-of select="title"/>
</h2>
</div>
</xsl:for-each>
The result could resemble:
<div id="d1e3">
<h2>Learning XML</h2>
</div>
<div id="d1e6">
<h2>Mastering XSLT</h2>
</div>
The important advantage is that the IDs are generated automatically rather than manually assigning different values to every node.
9. Using generate-id() with Variables
Variables are frequently used with generate-id().
Example:
<xsl:variable name="selectedBook" select="library/book[1]"/>
<book-id>
<xsl:value-of select="generate-id($selectedBook)"/>
</book-id>
Here, $selectedBook contains a reference to the first <book> node.
The function:
generate-id($selectedBook)
returns an identifier for that particular node.
This can be useful when the same node needs to be referenced multiple times during a transformation.
10. Identifying the First Node
A common pattern is to determine whether the current node is the first node in a particular node set.
For example:
<xsl:variable name="firstBook" select="library/book[1]"/>
<xsl:for-each select="library/book">
<xsl:if test="generate-id(.) = generate-id($firstBook)">
<first>First Book</first>
</xsl:if>
</xsl:for-each>
The first <book> node has the same generated ID as $firstBook.
Therefore, the condition becomes true only for that node.
11. Understanding Node Identity
It is important to understand that generate-id() is concerned with node identity, not simply node content.
Consider:
<book>
<title>XML</title>
</book>
<book>
<title>XML</title>
</book>
The two books have exactly the same content.
However, they are two separate nodes.
Therefore:
Book 1 → different generated ID
Book 2 → different generated ID
Even though their contents are identical, their identities are different.
This is one of the major reasons why generate-id() is useful.
12. generate-id() Does Not Generate Business IDs
A common misunderstanding is that generate-id() can be used to create permanent application IDs.
For example, it should not normally be treated as a replacement for:
<product-id>P1001</product-id>
or:
<employee-id>E1025</employee-id>
Those are meaningful business identifiers.
generate-id() instead provides an identifier associated with a node during XSLT processing.
Therefore, it is better suited for transformation-related tasks such as node comparison and linking.
13. Important Characteristics
There are several important characteristics to remember.
First, the returned value is a string.
Second, the exact format of the generated ID is determined by the XSLT processor.
Third, the generated identifier is associated with a node rather than the textual content of that node.
Fourth, two different nodes should not receive the same generated ID within the same transformation.
Fifth, the identifier should not be assumed to have a particular format.
14. Example with Employee Data
Consider:
<employees>
<employee>
<name>Rahul</name>
<department>Sales</department>
</employee>
<employee>
<name>Anita</name>
<department>Finance</department>
</employee>
</employees>
An XSLT stylesheet can generate an HTML list:
<xsl:for-each select="employees/employee">
<div id="{generate-id(.)}">
<h2>
<xsl:value-of select="name"/>
</h2>
<p>
<xsl:value-of select="department"/>
</p>
</div>
</xsl:for-each>
Each employee receives a different generated ID.
This can be especially useful when creating HTML pages containing navigation links, sections, or references to individual records.
15. generate-id() and Node References
Suppose one part of an XSLT transformation needs to refer to a node selected somewhere else.
You can store the node in a variable:
<xsl:variable name="target" select="employees/employee[2]"/>
Then obtain its ID:
<xsl:value-of select="generate-id($target)"/>
Another part of the generated HTML can use the same expression:
<a href="#{generate-id($target)}">
View Employee
</a>
And the target element can use:
<div id="{generate-id($target)}">
...
</div>
Both expressions refer to the same source node, so they produce the same identifier.
16. Difference Between Node Value and Node Identity
This distinction is very important.
Suppose:
<employee>
<name>Rahul</name>
</employee>
The value of the <name> node is:
Rahul
But:
generate-id(employee)
returns an identifier associated with the <employee> node itself.
Therefore, these concepts are different:
Node value → Rahul
Node name → employee
Node identity → generated ID
Understanding this distinction helps avoid incorrect use of the function.
17. When Should You Use generate-id()?
The function is useful when you need to:
-
Identify a particular XML node.
-
Compare whether two references point to the same node.
-
Generate unique HTML IDs.
-
Create internal HTML links.
-
Connect one generated output section with another.
-
Identify selected nodes dynamically.
-
Avoid manually creating identifiers for transformation output.
-
Determine whether the current node is the same as a node stored in a variable.
18. Important Limitation
The generated ID should not be treated as a permanent identifier for the original XML data.
If the source document or transformation environment changes, the generated identifier may also change.
For example, you should not design an external database around an ID returned by:
generate-id()
Instead, use an actual identifier stored in the source XML when a persistent identifier is required.
19. Summary
The generate-id() function provides a convenient way to obtain a unique identifier for an XML node during an XSLT transformation. It is particularly valuable when working with node identity rather than node content.
The basic syntax is:
generate-id(node)
For the current node:
generate-id(.)
For a node stored in a variable:
generate-id($variable)
The function is useful for comparing node references, generating unique HTML element IDs, creating internal links, and connecting different parts of transformation output. The actual ID value is generated by the XSLT processor, so applications should not depend on its exact format.
The key concept to remember is that generate-id() identifies a node, not its textual value. Two nodes containing identical data can still have different generated IDs because they are separate nodes.