Static analysis rejects errors before data is read: unknown functions (XPST0017), impossible types, code excluded by use-when. At run time, xsl:analyze-string splits text with a regular expression into matching and non-matching parts, xsl:assert checks an invariant, and xsl:evaluate compiles an XPath expression supplied as a string, here from a parameter:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" expand-text="yes">
<xsl:output method="text"/>
<xsl:param name="filter" as="xs:string" select="'true()'"/>
<xsl:template match="/catalog">
<xsl:assert test="header/records = count(book)">record count differs</xsl:assert>
<xsl:variable name="hits" as="element(book)*">
<xsl:evaluate xpath="'book[' || $filter || ']'" context-item="."/>
</xsl:variable>
<xsl:text>{count($hits)} match {$filter}: {$hits/@id} </xsl:text>
<xsl:analyze-string select="book[3]/summary" regex="from (\w+) to (\w+)">
<xsl:matching-substring>{regex-group(1)} to {regex-group(2)}</xsl:matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>xslt3 -s:booknest-catalog.xml -xsl:analysis.xsl 'filter=pages > 300'; echo
sed 's#<records>6#<records>7#' booknest-catalog.xml > seven.xml
xslt3 -ea:on -s:seven.xml -xsl:analysis.xsl 2>&1 | head -n 1Output
3 match pages > 300: b1 b2 b5 Kerala to Zanzibar record count differs
Saxon 726,956 skips xsl:assert unless you pass -ea:on. A malformed filter (filter=pages >) fails with XTDE3160 at run time, when the string is compiled. Treat xsl:evaluate like SQL built from strings: no untrusted input.
Analysis
<xsl:analyze-string>, <xsl:matching-substring>, <xsl:non-matching-substring>, <xsl:fallback>
<xsl:analyze-string> matches a string against a regular expression, processing the matched and non-matched portions separately with <xsl:matching-substring> and <xsl:non-matching-substring>; <xsl:fallback> supplies fallback content for processors that do not support the instruction. The example below matches the regex ^(a.)(..) against the string 'abcdef': the match itself is "abcd", with capturing group 1 = "ab" and group 2 = "cd"; the matched portion outputs group 2 via regex-group(2), while the unmatched remainder ("ef") is wrapped in parentheses.<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:analyze-string select="'abcdef'" regex="^(a.)(..)"
flags="msix">
<xsl:matching-substring>
<xsl:value-of select="regex-group(2)"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
(<xsl:value-of select="."/>)
</xsl:non-matching-substring>
<xsl:fallback>
Your processor does not support this feature.
</xsl:fallback>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>
Output
<?xml version="1.0" encoding="UTF-8"?>cd
(ef)
<xsl:assert>, <xsl:evaluate>
<xsl:assert> tests a condition and outputs its content as a diagnostic message only when the condition is false, without affecting the result if it is true. <xsl:evaluate> dynamically evaluates an XPath expression supplied as a string. The example below asserts that 101 ge 100 (true, so nothing is emitted), reports a message via <xsl:message select="10 ge 10"/>, and dynamically evaluates the string expression "(9*9)||''".<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:assert test="101 ge 100">
Is smaller than 100.
</xsl:assert>
<xsl:message select="10 ge 10">
Is greater than or equals 10
</xsl:message>
<xsl:evaluate xpath="(9*9)||''"/>
</xsl:template>
</xsl:stylesheet>
Output
(The processor reports the message 'true. Is greater than or equals 10'.) <?xml version="1.0" encoding="UTF-8"?>81
<xsl:message> can have the following attributes: terminate ({"yes" | "no"}), error-code ({eqname}).
<xsl:evaluate> can have the following attributes: as (sequence-type), base-uri ({uri}), with-params (expression), context-item (expression), namespace-context (expression), schema-aware ({"yes" | "no"}). The required item type of its xpath attribute is xs:string.