XSLT Reference
exactly-one()
Asserts that the sequence contains exactly one item; raises a dynamic error if the sequence has zero or more than one item.
exactly-one(sequence)Description
exactly-one() is a cardinality assertion function. It returns its argument unchanged if the sequence contains exactly one item, and raises a dynamic error (FORG0005) if the sequence is empty or contains more than one item.
Use exactly-one() to make cardinality assumptions explicit in your stylesheets. Rather than silently processing zero or multiple nodes when you expect exactly one, the function causes a clear error with a meaningful location. This is particularly valuable for enforcing schema-like constraints when schema validation is not available.
The function is purely an assertion; it performs no transformation of the data and has no effect on correct input.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
sequence | item()* | Yes | The sequence that must contain exactly one item. |
Return value
item() — the single item from the sequence, unchanged. Raises FORG0005 if the sequence does not contain exactly one item.
Examples
Asserting a unique key lookup
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<employee id="E001"><name>Alice</name></employee>
<employee id="E002"><name>Bob</name></employee>
</employees>
Stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/employees">
<result>
<xsl:variable name="emp" select="exactly-one(employee[@id='E001'])"/>
<found><xsl:value-of select="$emp/name"/></found>
</result>
</xsl:template>
</xsl:stylesheet>
Output:
<result>
<found>Alice</found>
</result>
Catching the error with try/catch (XSLT 3.0)
Stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:err="http://www.w3.org/2005/xqt-errors">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/employees">
<result>
<xsl:try>
<xsl:variable name="emp" select="exactly-one(employee[@id='UNKNOWN'])"/>
<found><xsl:value-of select="$emp/name"/></found>
<xsl:catch errors="*">
<error>No unique employee found: <xsl:value-of select="$err:description"/></error>
</xsl:catch>
</xsl:try>
</result>
</xsl:template>
</xsl:stylesheet>
Output:
<result>
<error>No unique employee found: ...</error>
</result>
Notes
- The error code raised is
err:FORG0005defined in the XPath/XQuery Functions and Operators specification. exactly-one()is equivalent to writing$seq[1][last() = 1]as a guard, but is cleaner and raises a standard error code.- In XSLT 2.0 function signatures, the
item()return type implicitly asserts exactly one item;exactly-one()makes that same assertion in an expression context. - For sequences that may be empty, use
zero-or-one()instead; for sequences that must be non-empty, useone-or-more().