XSLT - Controlling Namespace Output with exclude-result-prefixes and xsl:namespace in XSLT
Namespaces are an important part of XML because they prevent naming conflicts between elements and attributes that come from different XML vocabularies. In XSLT, namespaces are used not only while reading source XML but also when generating the result document. Sometimes, however, a stylesheet may contain namespace declarations that are necessary for processing but should not appear in the generated XML. XSLT provides mechanisms such as exclude-result-prefixes and xsl:namespace to control namespace declarations in the output.
1. Understanding Namespace Declarations
Consider the following XML:
<book xmlns="http://example.com/book">
<title>Learning XSLT</title>
</book>
The declaration:
xmlns="http://example.com/book"
associates the book vocabulary with a namespace.
A namespace can also use a prefix:
<b:book xmlns:b="http://example.com/book">
<b:title>Learning XSLT</b:title>
</b:book>
Here, b is the namespace prefix and:
http://example.com/book
is the namespace URI.
In an XSLT stylesheet, namespaces are frequently declared for purposes such as XPath expressions, extension instructions, or XSLT-specific processing.
2. The Problem of Unwanted Namespace Declarations
Consider this stylesheet:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:book="http://example.com/book">
<xsl:template match="/">
<result>
<xsl:value-of select="/book:book/book:title"/>
</result>
</xsl:template>
</xsl:stylesheet>
The book namespace is required by the XPath expression:
/book:book/book:title
However, the namespace might not be required in the generated <result> element.
Depending on the stylesheet and processor, namespace declarations used by the stylesheet can potentially appear in the result tree when they are associated with literal result elements.
For example, an unwanted namespace declaration could result in output resembling:
<result xmlns:book="http://example.com/book">
Learning XSLT
</result>
Although this is valid XML, the book namespace is unnecessary because <result> does not use it.
This is where exclude-result-prefixes becomes useful.
3. What Is exclude-result-prefixes?
exclude-result-prefixes is an attribute used on an xsl:stylesheet, xsl:transform, or certain stylesheet elements to specify namespace prefixes that should not normally be copied into the result tree.
Basic syntax:
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:book="http://example.com/book"
exclude-result-prefixes="book">
The important part is:
exclude-result-prefixes="book"
It tells the XSLT processor that the book namespace prefix is used by the stylesheet but should not be unnecessarily copied into the result.
4. Example of exclude-result-prefixes
Consider:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:book="http://example.com/book"
exclude-result-prefixes="book">
<xsl:template match="/">
<result>
<xsl:value-of select="/book:book/book:title"/>
</result>
</xsl:template>
</xsl:stylesheet>
Suppose the input is:
<book xmlns="http://example.com/book">
<title>Learning XSLT</title>
</book>
The result can be:
<result>Learning XSLT</result>
The book namespace does not need to appear on <result> because it is only being used by the stylesheet to navigate the source document.
5. Why Namespace Exclusion Is Useful
Namespace exclusion is useful when you want clean and readable output XML.
Without appropriate namespace control, a generated document can contain namespace declarations that are technically valid but unnecessary.
For example:
<result
xmlns:book="http://example.com/book"
xmlns:util="http://example.com/util">
Learning XSLT
</result>
If neither book nor util is actually used in the result, these declarations provide no benefit.
With namespace control, the output can be reduced to:
<result>Learning XSLT</result>
This makes the generated XML easier to read and can also make it easier for other systems to consume.
6. Namespace Exclusion Does Not Change the Source XML
An important point is that exclude-result-prefixes does not remove namespaces from the source document.
Suppose the source is:
<book xmlns="http://example.com/book">
<title>Learning XSLT</title>
</book>
The source namespace remains unchanged.
The XSLT processor still understands:
http://example.com/book
when evaluating XPath expressions.
exclude-result-prefixes only controls namespace declarations associated with the result tree.
Therefore, it is primarily an output-control mechanism rather than a source-document modification mechanism.
7. Prefixes and Namespace URIs
It is important to understand that a prefix is only an abbreviation.
For example:
xmlns:b="http://example.com/book"
associates:
b
with:
http://example.com/book
The namespace identity is determined by the URI, not by the prefix.
For example:
xmlns:b="http://example.com/book"
and:
xmlns:book="http://example.com/book"
refer to the same namespace.
Therefore, when controlling namespaces, you are dealing with namespace bindings rather than merely strings used as prefixes.
8. #all with exclude-result-prefixes
XSLT also provides a convenient option:
exclude-result-prefixes="#all"
This requests that all namespace prefixes declared in the stylesheet be excluded from the result where possible.
For example:
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:book="http://example.com/book"
xmlns:util="http://example.com/util"
exclude-result-prefixes="#all">
This can be useful when a stylesheet has many namespaces that are only required internally.
However, it should be used carefully because a namespace that is actually needed by a result element cannot simply disappear.
9. When a Namespace Cannot Be Excluded
Consider:
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:book="http://example.com/book"
exclude-result-prefixes="book">
<xsl:template match="/">
<book:catalog>
<book:title>Learning XSLT</book:title>
</book:catalog>
</xsl:template>
</xsl:stylesheet>
Here, the book namespace is actually required by the generated elements:
<book:catalog>
and:
<book:title>
The processor therefore needs to preserve the namespace binding in the result.
The output will need to contain something equivalent to:
<book:catalog xmlns:book="http://example.com/book">
<book:title>Learning XSLT</book:title>
</book:catalog>
This demonstrates an important principle:
Namespace exclusion cannot remove a namespace that is required to correctly identify a result element or attribute.
10. Understanding xsl:namespace
xsl:namespace is an XSLT instruction used to create a namespace node dynamically in the result tree.
Its basic form is:
<xsl:namespace name="prefix" select="'namespace-uri'"/>
For example:
<xsl:namespace name="b" select="'http://example.com/book'"/>
This creates a namespace binding equivalent to:
xmlns:b="http://example.com/book"
The major difference is that xsl:namespace allows the namespace information to be constructed dynamically.
11. Basic xsl:namespace Example
Consider:
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<result>
<xsl:namespace
name="book"
select="'http://example.com/book'"/>
</result>
</xsl:template>
</xsl:stylesheet>
The result can contain:
<result xmlns:book="http://example.com/book"/>
The namespace was created by the XSLT instruction rather than being directly written as a literal namespace declaration on the result element.
12. Dynamic Namespace Creation
The real advantage of xsl:namespace becomes apparent when the prefix or namespace URI comes from a variable or expression.
For example:
<xsl:variable name="prefix" select="'book'"/>
<xsl:variable name="uri"
select="'http://example.com/book'"/>
<result>
<xsl:namespace
name="{$prefix}"
select="$uri"/>
</result>
The generated result can contain:
<result xmlns:book="http://example.com/book"/>
This approach is useful when namespace information is determined dynamically during the transformation.
13. Creating Namespaces from Source Data
Suppose an input document contains:
<configuration>
<prefix>prod</prefix>
<uri>http://example.com/product</uri>
</configuration>
An XSLT stylesheet could use those values:
<xsl:template match="/configuration">
<output>
<xsl:namespace
name="{prefix}"
select="uri"/>
</output>
</xsl:template>
The resulting document could contain:
<output xmlns:prod="http://example.com/product"/>
This is one of the situations where xsl:namespace is more flexible than simply writing:
xmlns:prod="http://example.com/product"
because the values can be determined dynamically.
14. exclude-result-prefixes vs xsl:namespace
These two features solve different problems.
| Feature | Main purpose |
|---|---|
exclude-result-prefixes |
Prevent unnecessary stylesheet namespace bindings from appearing in the result |
xsl:namespace |
Create namespace bindings dynamically in the result |
exclude-result-prefixes |
Primarily output cleanup |
xsl:namespace |
Primarily dynamic namespace construction |
For example, if you have:
xmlns:book="http://example.com/book"
only because you need it for XPath processing, you may use:
exclude-result-prefixes="book"
On the other hand, if the namespace URI must be generated dynamically, you can use:
<xsl:namespace
name="{$prefix}"
select="$uri"/>
15. Namespace Aliasing and Output Namespaces
Namespace handling becomes particularly important when an XSLT transformation generates another XSLT stylesheet or another XML vocabulary.
For example, an XSLT stylesheet may need to produce:
<xsl:template>
as output rather than execute it as an XSLT instruction during the current transformation.
In such situations, namespace-related features such as namespace aliasing can become relevant.
However, namespace aliasing and exclude-result-prefixes solve different problems.
exclude-result-prefixes controls unnecessary namespace declarations, whereas namespace aliasing controls how stylesheet namespaces are represented in the result.
This distinction is important when designing complex XSLT transformations.
16. Namespace Control with Literal Result Elements
Consider:
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:product="http://example.com/product">
<xsl:template match="/">
<result>
<product:name>
Laptop
</product:name>
</result>
</xsl:template>
</xsl:stylesheet>
Because:
<product:name>
belongs to the product namespace, the generated result must preserve the namespace binding.
The output could be:
<result xmlns:product="http://example.com/product">
<product:name>Laptop</product:name>
</result>
Trying to exclude product would not make sense because the result actually uses that namespace.
17. Namespace Nodes and Result Trees
To understand namespace control properly, it helps to understand the concept of a result tree.
XSLT does not simply perform text replacement. It constructs a tree containing:
-
Elements
-
Attributes
-
Text nodes
-
Comments
-
Processing instructions
-
Namespace nodes or namespace bindings
When the result tree is serialized as XML, namespace bindings are written using declarations such as:
xmlns:book="http://example.com/book"
Therefore, namespace control is fundamentally about controlling the namespace information associated with nodes in the result tree.
18. Common Mistakes
Mistake 1: Thinking exclude-result-prefixes removes namespaces from input
It does not.
It only affects namespace declarations in the result.
Mistake 2: Trying to exclude a namespace used by output elements
For example:
<book:item>
requires the book namespace.
The namespace cannot simply be eliminated from the serialized result.
Mistake 3: Confusing a prefix with a namespace
The prefix:
book
is not the namespace itself.
The namespace is:
http://example.com/book
Mistake 4: Using dynamic namespace creation unnecessarily
If the namespace is known at stylesheet design time, a normal namespace declaration is generally simpler.
xsl:namespace is particularly valuable when the namespace must be constructed dynamically.
Mistake 5: Expecting exact prefix preservation
XML processors can sometimes use different prefixes while preserving the same namespace URI. Applications should generally care about namespace URI and expanded names rather than relying on a particular prefix.
19. Practical Example
Suppose the source XML is:
<catalog xmlns="http://example.com/catalog">
<product>
<name>Notebook</name>
<price>50000</price>
</product>
</catalog>
The stylesheet can declare the source namespace:
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="http://example.com/catalog"
exclude-result-prefixes="c">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<products>
<xsl:for-each select="/c:catalog/c:product">
<product>
<name>
<xsl:value-of select="c:name"/>
</name>
<price>
<xsl:value-of select="c:price"/>
</price>
</product>
</xsl:for-each>
</products>
</xsl:template>
</xsl:stylesheet>
The namespace prefix c is required by XPath:
/c:catalog/c:product
But it is not required by the output.
The result can therefore be:
<products>
<product>
<name>Notebook</name>
<price>50000</price>
</product>
</products>
This is a practical example of using exclude-result-prefixes to keep the output clean while still using namespaces internally.
20. When to Use These Features
Use exclude-result-prefixes when:
-
A namespace is required by XPath expressions but not by the output.
-
You want cleaner generated XML.
-
The stylesheet contains several internal namespaces.
-
You want to prevent unnecessary namespace declarations in literal result elements.
Use xsl:namespace when:
-
A namespace must be created dynamically.
-
The namespace URI comes from a variable or source document.
-
The prefix needs to be generated dynamically.
-
The transformation creates XML vocabularies whose namespace information is determined at runtime.
Conclusion
exclude-result-prefixes and xsl:namespace provide two different approaches to namespace management in XSLT. exclude-result-prefixes is primarily used to prevent unnecessary namespace declarations from appearing in the result document when those namespaces are needed only internally by the stylesheet. In contrast, xsl:namespace allows namespace bindings to be constructed dynamically during transformation.
Understanding these features is especially important when working with large XML vocabularies, dynamically generated XML, multiple namespaces, or transformations that must produce clean and precisely structured output. Proper namespace management ensures that the result remains both valid and semantically correct while avoiding unnecessary namespace declarations.