|
<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>
|