Functions are values in XSLT 3.0: an xsl:function can return a closure (an inline function that remembers $pct), maps index data by key, and system-property() tells the stylesheet where it runs. Run xslt3 -s:booknest-catalog.xml -xsl:hof.xsl:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:bn="urn:booknest:fn"
xmlns:map="http://www.w3.org/2005/xpath-functions/map" expand-text="yes">
<xsl:output method="text"/>
<xsl:function name="bn:discounter" as="function(xs:decimal) as xs:decimal">
<xsl:param name="pct" as="xs:decimal"/>
<xsl:sequence select="function($p) { round($p * (100 - $pct) div 100, 2) }"/>
</xsl:function>
<xsl:template match="/catalog">
<xsl:variable name="prices" as="map(xs:string, xs:decimal)"
select="map:merge(book ! map { string(@id): xs:decimal(.//price) })"/>
<xsl:variable name="sale" select="bn:discounter(20)"/>
<xsl:text>From $20: {map:keys($prices)[$prices(.) ge 20] => sort()} </xsl:text>
<xsl:text>Sale total: {sum($prices?* ! $sale(.))} </xsl:text>
<xsl:text>{('xsl:product-name', 'xsl:product-version', 'xsl:supports-streaming')
! system-property(.)} </xsl:text>
</xsl:template>
</xsl:stylesheet>Output
From $20: b2 b3 b6 Sale total: 107.79 SAXON HE 12.10 no
$prices?* returns the map's values. Feature tests such as system-property('xsl:supports-streaming') and function-available() in use-when let one stylesheet adapt to each processor.
Other Built in Functions
document(), json-to-xml(), xml-to-json()
document() is equivalent to doc():| <xsl:value-of select="document('zoo.xml')"/> |
| <xsl:value-of select="doc('zoo.xml')"/> |
Both instructions are equivalent.
json-to-xml() converts a JSON string into an XML representation using the http://www.w3.org/2013/XSL/json namespace:| json-to-xml('{"x": 1, "y": [3,4,5]}') |
| <map xmlns="http://www.w3.org/2013/XSL/json"> <number key="x">1</number> <array key="y"> <number>3</number> <number>4</number> <number>5</number> </array> </map> |
Result of the call above.
xml-to-json() performs the reverse conversion, and has two signatures:- xml-to-json($input as node()) as xs:string
- xml-to-json($input as node(), $options as map(*)) as xs:string
element-available(), function-available(), type-available()
These functions test, at run time, whether a given instruction, function or type is supported by the processor. The example below tests <xsl:for-each>, substring() and xs:string.<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xsl:template match="/">
<xsl:value-of select="element-available('xsl:for-each')"/>
<xsl:value-of select="function-available('substring')"/>
<xsl:value-of select="type-available('xs:string')"/>
</xsl:template>
</xsl:stylesheet>
Output
<?xml version="1.0" encoding="UTF-8"?>truetruetrue
current(), system-property(), unparsed-entity-public-id(), unparsed-entity-uri(), snapshot()
current() refers to the context item that was current when the containing expression began evaluating, which is not necessarily the same as a bare, optional leading dot ('.'):| <xsl:apply-templates select="//glossary/entry[@name=current()/@ref]"/> |
| <xsl:apply-templates select="//glossary/entry[@name=./@ref]"/> |
In the first line, current() refers to the outer context item. In the second line, the dot is simply optional, and @ref belongs to the entry elements being tested — the two expressions are not equivalent.
system-property($property) returns the value of a system property; $property can be one of: 'xsl:version', 'xsl:vendor', 'xsl:vendor-url', 'xsl:product-name', 'xsl:product-version', 'xsl:is-schema-aware', 'xsl:supports-serialization', 'xsl:supports-backwards-compatibility', 'xsl:supports-namespace-axis', 'xsl:supports-streaming', 'xsl:supports-dynamic-evaluation'.unparsed-entity-public-id($entity) returns the public identifier of the unparsed entity named by the string $entity.
unparsed-entity-uri($entity) returns the URI (system identifier) of the unparsed entity named by the string $entity.
snapshot($nodes) returns a copy of a node together with its ancestors and descendants, and their attributes and namespaces.