How to Dynamically Create Namespaces in XSLT?
In XSLT 2.0 and later versions, the
<xsl:namespace> instruction allows developers to
dynamically construct namespace nodes and bind them to result elements
during transformation. This article explains the syntax, attributes,
rules, and practical examples of <xsl:namespace>,
demonstrating how to create namespace prefixes and URI bindings computed
at runtime from source data, parameters, or expressions.
The Need for Dynamic Namespaces
In XSLT 1.0, generating namespace declarations dynamically was
difficult. Namespaces were typically inherited from the stylesheet or
created implicitly by generating elements or attributes with prefixed
names. When dynamic mapping required prefixes or URIs determined at
runtime, developers often had to resort to cumbersome workarounds, such
as using disable-output-escaping or creating temporary
nodes.
XSLT 2.0 resolved this limitation by introducing the
<xsl:namespace> element, giving fine-grained control
over namespace node creation on the current element in the output
tree.
Syntax and Core Attributes
The <xsl:namespace> element creates a namespace
node on the currently enclosing result element. It supports two primary
attributes:
name: Specifies the namespace prefix to declare. It accepts an Attribute Value Template (AVT), allowing the prefix to be evaluated dynamically at runtime. If omitted or evaluated to an empty string, it declares a default namespace (an unbound prefix).select: An optional XPath expression that evaluates to the namespace URI. If omitted, the string value of the element's content template forms the namespace URI.
The basic structure follows this format:
<xsl:namespace name="{$prefixVariable}" select="$uriVariable"/>Alternatively, the URI can be provided as the content of the instruction:
<xsl:namespace name="{$prefixVariable}">
<xsl:value-of select="$uriVariable"/>
</xsl:namespace>Practical Example: Dynamic Mapping from Source XML
Consider an input document containing dynamic mappings for prefixes and namespaces that must be applied to an output document:
<!-- Source XML -->
<config>
<mapping prefix="app" uri="http://example.com/app"/>
<mapping prefix="data" uri="http://example.com/data"/>
</config>An XSLT 2.0 or 3.0 stylesheet can iterate over these configuration nodes and attach the corresponding namespace definitions to the root element:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/config">
<root>
<xsl:for-each select="mapping">
<xsl:namespace name="{@prefix}" select="@uri"/>
</xsl:for-each>
<content>Namespaces dynamically declared on root.</content>
</root>
</xsl:template>
</xsl:stylesheet>When transformed, the resulting XML document contains the dynamically injected namespace declarations:
<root xmlns:app="http://example.com/app"
xmlns:data="http://example.com/data">
<content>Namespaces dynamically declared on root.</content>
</root>Declaring a Default Namespace
To declare or override a default namespace (an unprefixed namespace)
dynamically, provide an empty string for the name
attribute:
<xsl:template match="/">
<root>
<xsl:namespace name="" select="'http://example.com/default'"/>
<child>Item</child>
</root>
</xsl:template>Usage Rules and Constraints
When working with <xsl:namespace>, several
processor rules apply:
- Placement:
<xsl:namespace>must be evaluated immediately after creating an element, before any child elements, text nodes, or other non-attribute/non-namespace content are added to that element. - Reserved Prefixes: Attempting to use
xmlorxmlnsas the value for thenameattribute will produce a dynamic error. - Valid NCName: The computed
nameattribute must be a valid XML non-colonized name (NCName) or an empty string. - Valid URI String: The evaluated content or
selectattribute must produce a valid xs:anyURI string. - Conflict Resolution: If multiple namespace nodes with the same prefix are generated for a single element, the last one created wins, replacing earlier declarations.