XSLT - Assertions and Validation with <xsl:assert> in XSLT 3.0
<xsl:assert> is an XSLT 3.0 instruction used to check whether a particular condition is true during a transformation. If the condition is false, the processor raises a dynamic error. It is especially useful for detecting invalid input, unexpected values, violated business rules, and programming assumptions early in the transformation process. (Saxonica)
Unlike ordinary conditional processing with <xsl:if> or <xsl:choose>, an assertion is intended to state that something must be true. If that requirement is not satisfied, the transformation can be stopped with an informative diagnostic message.
1. Why Assertions Are Useful in XSLT
Consider an XML document containing employee information:
<employees>
<employee>
<name>John</name>
<age>30</age>
</employee>
<employee>
<name>Mary</name>
<age>25</age>
</employee>
</employees>
Suppose your stylesheet assumes that every employee must have an age greater than zero.
Without an assertion, the transformation might continue even if the input contains:
<age>0</age>
or:
<age>-5</age>
This can produce incorrect output.
An assertion allows you to explicitly state the requirement:
<xsl:assert test="$age > 0">
Employee age must be greater than zero.
</xsl:assert>
If $age is valid, processing continues. If it is not, the assertion fails and a dynamic error is generated. (Saxonica)
2. Basic Syntax of <xsl:assert>
The basic syntax is:
<xsl:assert test="condition">
Error message
</xsl:assert>
The test attribute contains an XPath expression.
For example:
<xsl:assert test="$price >= 0">
Price cannot be negative.
</xsl:assert>
Here:
-
$price >= 0is the condition. -
If the condition evaluates to true, processing continues.
-
If it evaluates to false, the assertion fails.
-
The text inside
<xsl:assert>provides information about the failure.
The test attribute is the primary part of the instruction. Saxon's documentation also identifies optional attributes for supplying part of the error message and specifying an error code. (Saxonica)
3. Understanding the test Expression
The test attribute accepts an XPath expression.
For example:
<xsl:assert test="age >= 18">
Employee must be at least 18 years old.
</xsl:assert>
The XML escaping is important here. Since < and > have special meanings in XML, comparison operators may need to be escaped when written in attributes.
For example:
<xsl:assert test="age > 0">
is preferable to writing the comparison directly with an unescaped > in contexts where XML syntax requires escaping.
Assertions can also test strings:
<xsl:assert test="normalize-space(name) != ''">
Employee name cannot be empty.
</xsl:assert>
They can test whether nodes exist:
<xsl:assert test="employee">
At least one employee is required.
</xsl:assert>
They can test multiple conditions:
<xsl:assert test="$age >= 18 and $age <= 65">
Employee age must be between 18 and 65.
</xsl:assert>
4. Simple Example
Consider this source XML:
<product>
<name>Laptop</name>
<price>75000</price>
<quantity>5</quantity>
</product>
An XSLT stylesheet can validate the product information before generating output:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/product">
<xsl:assert test="normalize-space(name) != ''">
Product name is required.
</xsl:assert>
<xsl:assert test="price > 0">
Product price must be greater than zero.
</xsl:assert>
<xsl:assert test="quantity > 0">
Product quantity must be greater than zero.
</xsl:assert>
<result>
<name>
<xsl:value-of select="name"/>
</name>
<price>
<xsl:value-of select="price"/>
</price>
<quantity>
<xsl:value-of select="quantity"/>
</quantity>
</result>
</xsl:template>
</xsl:stylesheet>
If the input contains:
<quantity>0</quantity>
the third assertion fails.
This prevents the stylesheet from silently producing output based on an invalid quantity.
5. Assertions for Business Rules
One of the most useful applications of <xsl:assert> is enforcing business rules.
For example, imagine an order:
<order>
<customer>John</customer>
<amount>5000</amount>
<status>approved</status>
</order>
A business rule might require that an approved order must have a positive amount.
<xsl:assert test="status != 'approved' or amount > 0">
An approved order must have a positive amount.
</xsl:assert>
This expression means:
-
If the status is not
approved, the assertion passes. -
If the status is
approved, the amount must be greater than zero.
This makes assertions useful for enforcing rules that are specific to an application's XML-processing requirements.
6. Assertions with Variables
Assertions can be applied to variables as well.
<xsl:variable name="total"
select="sum(item/price)"/>
<xsl:assert test="$total >= 0">
Calculated total cannot be negative.
</xsl:assert>
Here, the stylesheet calculates the total and then verifies the result.
This is particularly useful when a complex XPath expression performs calculations or transformations.
For example:
<xsl:variable name="discounted-price"
select="$price - ($price * $discount div 100)"/>
<xsl:assert test="$discounted-price >= 0">
Discounted price cannot be negative.
</xsl:assert>
Assertions therefore provide a way to check intermediate results instead of validating only the final output.
7. Assertions and Error Messages
A major advantage of assertions is that they can provide meaningful diagnostic information.
Instead of simply allowing a transformation to fail somewhere later, you can write:
<xsl:assert test="$quantity > 0">
Invalid quantity supplied.
</xsl:assert>
You can also construct messages dynamically.
For example:
<xsl:assert test="$quantity > 0"
select="'Invalid quantity: ' || $quantity"/>
The select attribute can be used to specify part of the error message generated when the assertion fails. (Saxonica)
This can make debugging considerably easier because the error can contain the actual value that caused the problem.
8. Assertions with Custom Error Codes
XSLT 3.0 also allows an assertion to specify an error code.
For example:
<xsl:assert test="$age > 0"
error-code="Q{http://example.com/errors}INVALID-AGE">
Age must be greater than zero.
</xsl:assert>
The error-code attribute identifies the error associated with a failed assertion. (Saxonica)
This is useful in larger applications where different types of transformation errors need to be identified programmatically.
For example, an application could distinguish between:
INVALID-AGE
INVALID-PRICE
INVALID-CUSTOMER
INVALID-ORDER
rather than treating every transformation failure as an unidentified error.
9. Assertions Inside Templates
Assertions can be placed inside template processing.
For example:
<xsl:template match="employee">
<xsl:assert test="name">
Employee name is missing.
</xsl:assert>
<xsl:assert test="salary > 0">
Employee salary must be positive.
</xsl:assert>
<employee>
<xsl:value-of select="name"/>
</employee>
</xsl:template>
Every time an employee element is processed, these conditions are checked.
This is useful when a stylesheet expects a particular structure from its input document.
10. Assertions and <xsl:if> Are Different
It is important not to confuse <xsl:assert> with <xsl:if>.
An <xsl:if> normally controls whether some processing should happen:
<xsl:if test="price > 0">
<valid-product>true</valid-product>
</xsl:if>
If the condition is false, XSLT simply skips the content.
An assertion expresses a requirement:
<xsl:assert test="price > 0">
Price must be greater than zero.
</xsl:assert>
If the condition is false, the assertion fails.
Therefore:
xsl:if
Used for conditional processing.
xsl:assert
Used for enforcing assumptions or requirements.
This distinction is important when designing reliable XSLT transformations.
11. Assertions for Input Validation
Suppose an XML document contains customer data:
<customer>
<id>C1001</id>
<name>John</name>
<email>[email protected]</email>
</customer>
The stylesheet might require all three values:
<xsl:assert test="id">
Customer ID is required.
</xsl:assert>
<xsl:assert test="name">
Customer name is required.
</xsl:assert>
<xsl:assert test="email">
Customer email is required.
</xsl:assert>
Additional validation can be performed:
<xsl:assert test="string-length(normalize-space(id)) > 0">
Customer ID cannot be empty.
</xsl:assert>
This provides an additional layer of protection before the transformation generates the final document.
12. Assertions for Calculations
Assertions are also useful for checking calculations.
Suppose:
<invoice>
<subtotal>1000</subtotal>
<tax>180</tax>
<total>1180</total>
</invoice>
The stylesheet can verify the relationship:
<xsl:assert test="total = subtotal + tax">
Invoice total does not match subtotal plus tax.
</xsl:assert>
If someone changes the XML to:
<total>1200</total>
the assertion fails.
This is valuable when XSLT processes financial documents, invoices, reports, orders, or other structured business data.
13. Assertions for Sequence Validation
XSLT 3.0 works extensively with sequences. Assertions can therefore check sequence-related assumptions.
For example:
<xsl:variable name="values"
select="item/@price"/>
<xsl:assert test="every $value in $values satisfies $value >= 0">
All item prices must be non-negative.
</xsl:assert>
This checks every value in the sequence.
Another example is checking whether at least one value exists:
<xsl:assert test="exists($values)">
At least one item price is required.
</xsl:assert>
This is useful when processing collections of XML nodes or calculated values.
14. Assertions for Development and Debugging
Assertions are particularly useful during development.
Suppose a stylesheet expects a variable to contain a particular value:
<xsl:variable name="status"
select="normalize-space(order/status)"/>
<xsl:assert test="$status = ('pending', 'approved', 'rejected')">
Unexpected order status.
</xsl:assert>
If a new status such as:
<status>processing</status>
appears unexpectedly, the assertion immediately identifies the problem.
This is better than allowing the stylesheet to continue and potentially generate incorrect output.
Assertions can therefore act as safeguards around assumptions made by the stylesheet developer.
15. Assertions Versus XML Schema Validation
Assertions should not be viewed as a complete replacement for XML Schema validation.
XML Schema can define structural and datatype rules for XML documents.
For example, a schema can specify that a particular element should contain an integer.
XSLT assertions, on the other hand, are particularly useful for conditions that arise during transformation or depend on transformation logic.
For example:
<xsl:assert test="end-date > start-date">
End date must be later than start date.
</xsl:assert>
This kind of relationship between values can be conveniently checked during transformation.
Therefore, the two approaches can complement each other:
XML Schema
Validates XML structure and data types.
XSLT assertion
Validates assumptions and transformation-specific conditions.
16. Assertions Do Not Automatically Produce Normal Output
A common misunderstanding is that an assertion will simply display an error message in the generated XML or HTML.
That is not its primary purpose.
For example:
<xsl:assert test="$price > 0">
Invalid price.
</xsl:assert>
If $price is invalid, the assertion causes a dynamic error rather than creating:
<error>Invalid price.</error>
The exact handling of the error depends on the XSLT processor and the surrounding application.
This makes assertions appropriate for detecting invalid states rather than for normal user-facing output.
17. Assertions and <xsl:try> / <xsl:catch>
Assertions can also be considered alongside XSLT 3.0 error handling.
An assertion may generate an error when a condition is false. XSLT 3.0 provides <xsl:try> and <xsl:catch> for handling errors.
Conceptually:
<xsl:try>
<xsl:assert test="$price > 0">
Price must be positive.
</xsl:assert>
<!-- Other processing -->
<xsl:catch>
<!-- Error handling -->
</xsl:catch>
</xsl:try>
This allows a stylesheet to combine validation and controlled error handling.
However, assertions and error handling have different purposes:
xsl:assert
Detects a condition that should be true.
xsl:try / xsl:catch
Handles errors that occur during processing.
Both are part of the broader error-management capabilities available in XSLT 3.0. (Saxonica)
18. Practical Example: Employee Validation
Consider:
<employees>
<employee>
<name>John</name>
<age>30</age>
<salary>50000</salary>
</employee>
<employee>
<name>Mary</name>
<age>25</age>
<salary>45000</salary>
</employee>
</employees>
A stylesheet could validate every employee:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/employees">
<result>
<xsl:for-each select="employee">
<xsl:assert test="normalize-space(name) != ''">
Employee name is required.
</xsl:assert>
<xsl:assert test="age > 0">
Employee age must be greater than zero.
</xsl:assert>
<xsl:assert test="salary > 0">
Employee salary must be greater than zero.
</xsl:assert>
<employee>
<name>
<xsl:value-of select="name"/>
</name>
<age>
<xsl:value-of select="age"/>
</age>
<salary>
<xsl:value-of select="salary"/>
</salary>
</employee>
</xsl:for-each>
</result>
</xsl:template>
</xsl:stylesheet>
The transformation first verifies the assumptions about each employee. Only when the assertions succeed does normal output generation continue.
19. Advantages of <xsl:assert>
The main advantages include:
-
Early error detection
Problems can be detected close to where they occur. -
Improved debugging
Meaningful assertion messages make problems easier to locate. -
Business-rule enforcement
Transformation-specific rules can be explicitly represented. -
Protection against invalid assumptions
Developers can verify that expected conditions are actually true. -
Better maintainability
Assertions document important assumptions directly inside the stylesheet. -
Custom error identification
Error codes can be assigned to different assertion failures. (Saxonica)
20. Important Considerations
<xsl:assert> is an XSLT 3.0 feature, so it requires an XSLT processor with appropriate XSLT 3.0 support. (Saxonica)
Processor behavior can also matter. For example, Saxon's documentation notes that assertions may be disabled by default in certain configurations and provides configuration mechanisms for enabling them. Therefore, when testing an assertion-based stylesheet, you should verify that assertions are enabled in the processor being used. (Saxonica)
It is also important to write useful assertions. An assertion should represent a meaningful condition rather than duplicate every ordinary XML check.
Conclusion
<xsl:assert> provides XSLT 3.0 developers with a direct mechanism for expressing assumptions and validating conditions during transformation. Instead of allowing invalid data or unexpected states to pass silently through a stylesheet, assertions make those conditions explicit and cause a dynamic error when they are violated. (Saxonica)
It is particularly valuable for validating business rules, checking calculated values, verifying required data, detecting unexpected input, and debugging complex transformations. When combined appropriately with XPath expressions and XSLT 3.0 error-handling facilities such as <xsl:try> and <xsl:catch>, it can make XSLT applications considerably more reliable and maintainable. (Saxonica)