How Does the XSLT Select Attribute Work?

The select attribute in XSLT serves as the primary bridge between an XSL stylesheet and XPath expressions, dictating which nodes, atomic values, or computational results an element should process. While its universal purpose is to evaluate an XPath expression against the current context node, its behavior, required data type, and output vary significantly depending on the parent element. This guide breaks down how the select attribute operates across major XSLT elements, covering node navigation, value extraction, loop iteration, variable assignment, and sorting.

Extracting Data with xsl:value-of

When used inside xsl:value-of, the select attribute evaluates an XPath expression and converts the result into a string to insert into the result tree.

In XSLT 1.0, if the expression evaluates to a node-set, xsl:value-of extracts the string-value of only the first node in document order. In XSLT 2.0 and later versions, selecting a sequence of nodes or items will output all item values separated by a space (or a custom delimiter defined by the separator attribute).

<!-- Selects and outputs the text value of the title element -->
<xsl:value-of select="book/title" />

Delegating Processing with xsl:apply-templates

In xsl:apply-templates, the select attribute specifies a node-set (or sequence) to which the processor should apply matching templates.

If the select attribute is omitted, the processor defaults to selecting all child nodes of the current context node (select="node()"). Supplying a specific XPath expression narrows the processing scope, filters out unwanted elements, or sorts the matched nodes before processing begins.

<!-- Applies templates only to active employee elements -->
<xsl:apply-templates select="department/employee[@status='active']" />

Iterating Over Node-Sets with xsl:for-each

The select attribute in xsl:for-each defines the collection of nodes over which a loop executes.

During each iteration, the processor updates the context node to the individual node currently being evaluated. This changes the baseline for any relative XPath expressions executed inside the body of the xsl:for-each block.

<xsl:for-each select="catalog/item">
  <!-- The context node is now 'item' -->
  <li><xsl:value-of select="name" /></li>
</xsl:for-each>

Assigning Data with xsl:variable and xsl:param

Within xsl:variable and xsl:param, the select attribute determines the value and data type bound to the variable name.

Using the select attribute assigns native XPath data types such as node-sets, booleans, numbers, or strings:

<xsl:variable name="itemCount" select="count(catalog/item)" />
<xsl:variable name="selectedNodes" select="catalog/item[@featured='true']" />

If the select attribute is omitted and content is provided inside the element body, XSLT constructs a Result Tree Fragment (in XSLT 1.0) or a document node containing text (in XSLT 2.0+), which consumes more memory and behaves differently than a direct node reference.

Deep Copying with xsl:copy-of

Unlike xsl:value-of, which flattens selected nodes into a string, xsl:copy-of uses its select attribute to perform a deep copy of the selected node-set, preserving all child elements, attributes, and text nodes into the result tree unchanged.

<!-- Copies the entire metadata subtree into the output -->
<xsl:copy-of select="document/metadata" />

Ordering Output with xsl:sort

When placed inside xsl:apply-templates or xsl:for-each, xsl:sort uses its select attribute to determine the sorting key for the surrounding node collection. The XPath expression is evaluated relative to each individual node in the collection being iterated or processed.

<xsl:for-each select="catalog/item">
  <xsl:sort select="price" data-type="number" order="ascending" />
  <p><xsl:value-of select="name" />: <xsl:value-of select="price" /></p>
</xsl:for-each>

Understanding Context Evaluation

Across all elements, the evaluation of the select attribute depends entirely on the current context: