Project

Profile

Help

Bug #6654 » test.xsl

Michael Kay, 2025-01-17 17:25

 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:t="t">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:namespace-alias stylesheet-prefix="t" result-prefix="xsl"/>
<xsl:template match="/">
<xsl:apply-templates select="//xsl:record-type"/>
</xsl:template>

<xsl:template match="xsl:record-type">
<t:function name="{@name}"
as="{@name}"
visibility="{(@visibility otherwise 'private')}">
<!-- if the record type is extensible, choose a name for the options parameter -->
<xsl:variable name="options-param" as="xs:string?">
<xsl:if test="normalize-space(@extensible) = ('yes', 'true', 'a')"
then="('options', (1 to count(xsl:field)) ! `options{.}`)
[not(. = current()/xsl:field/@name)][1]"/>
</xsl:variable>
<!-- declare the parameters -->
<xsl:for-each select="xsl:field">
<t:param name="{@name}"
required="{@required otherwise 'yes'}">
<xsl:attribute name="as">
<xsl:variable name="as"
select="normalize-space(@as otherwise 'item()*')"/>
<xsl:variable name="optional"
select="normalize-space(@required) = ('no', 'false', '0')"/>
<xsl:choose>
<xsl:when test="not($optional)" select="$as"/>
<!-- for optional fields, amend the required type to allow () -->
<xsl:when test="matches($as, '[?*]$')" select="$as"/>
<xsl:when test="matches($as, '\+$')" select="replace($as, '\+$', '*')"/>
<xsl:otherwise select="$as || '?'"/>
</xsl:choose>
</xsl:attribute>
<xsl:if test="@default">
<xsl:attribute name="select" select="@default"/>
</xsl:if>
</t:param>
</xsl:for-each>
<!-- for an extensible record type, declare the options parameter -->
<xsl:if test="exists($options-param)">
<t:param name="{$options-param}" as="map(*)" required="no" select="{}"/>
</xsl:if>
<!-- function body: construct a map -->
<t:map on-duplicates="fn($first, $second){{$first}}">
<xsl:for-each select="xsl:field">
<xsl:variable name="optional"
select="normalize-space(@required) = ('no', 'false', '0')"/>
<xsl:choose>
<xsl:when test="$optional and not(@default)">
<!-- omit map entries for optional fields if no value is supplied -->
<t:if test="exists(${@name})">
<t:map-entry key="'{@name}'" select="${@name}"/>
</t:if>
</xsl:when>
<xsl:otherwise>
<t:map-entry key="'{@name}'" select="${@name}"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<!-- if the record type is extensible,
add entries from the options parameter -->
<xsl:if test="exists($options-param)">
<t:sequence select="${$options-param}"/>
</xsl:if>

</t:map>
</t:function>
</xsl:template>
</xsl:stylesheet>
(1-1/2)