Skip to content

Commit

Permalink
More work on datatyping usnistgov#436 including now in JSON Schema
Browse files Browse the repository at this point in the history
  • Loading branch information
wendellpiez committed Jul 18, 2019
1 parent 47f5949 commit dab89fb
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 39 deletions.
85 changes: 78 additions & 7 deletions build/metaschema/json/json-schema-metamap.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@
<string key="type">object</string>
</xsl:template>

<xsl:template match="define-field | define-flag" mode="object-type">
<xsl:template match="define-field[empty(flag)] | define-flag" mode="object-type">
<string key="type">string</string>
</xsl:template>

Expand All @@ -341,7 +341,9 @@
<xsl:when test="exists(key('definition-by-name',@ref)/@as-type)">
<xsl:apply-templates mode="#current" select="key('definition-by-name',@ref)"/>
</xsl:when>
<xsl:otherwise>string</xsl:otherwise>
<xsl:otherwise>
<string key="type">string</string>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

Expand All @@ -351,20 +353,89 @@

<xsl:template priority="2" match="*[@as-type='integer']" mode="object-type">
<string key="type">integer</string>
<number key="multipleOf">1.0</number>
</xsl:template>

<xsl:template priority="2" match="*[@as-type='positiveInteger']" mode="object-type">
<string key="type">integer</string>
<number key="multipleOf">1.0</number>
<number key="minimum">1</number>
</xsl:template>

<xsl:template priority="2" match="*[@as-type='nonNegativeInteger']" mode="object-type">
<string key="type">integer</string>
<number key="multipleOf">1.0</number>
<number key="minimum">0</number>
</xsl:template>

<!-- Types are listed in ../xml/produce-xsl.xsl and ../xml/oscal-datatypes -->
<!-- Types are listed in ../xml/produce-xsd.xsl and ../xml/oscal-datatypes.xsd -->

<xsl:variable name="numeric-types" as="element()*">
<type>decimal</type>
<type>float</type>
<type>double</type>
<type>percent</type>
</xsl:variable>

</xsl:variable>

<xsl:template priority="2" match="*[@as-type=$numeric-types]" mode="object-type">
<string key="type">number</string>
</xsl:template>

<xsl:template priority="3" match="*[@as-type = $datatypes/*/@key]" mode="object-type">
<xsl:copy-of select="key('datatypes-by-name',@as-type,$datatypes)/*"/>
</xsl:template>

<xsl:template match="prose" name="prose"/>


<xsl:key name="datatypes-by-name" xpath-default-namespace="http://www.w3.org/2005/xpath-functions"
match="map" use="@key"/>

<xsl:variable name="datatypes" expand-text="false">
<map key="date-with-timezone">
<string key="type">string</string>
<string key="format">date</string>
<!--The xs:date with a required timezone.-->
<string key="pattern">.+[:Z].*</string>
</map>
<map key="dateTime-with-timezone">
<string key="type">string</string>
<string key="format">date-time</string>
<!--The xs:dateTime with a required timezone.-->
<string key="pattern">.+T.+(Z|[+-].+)</string>
</map>
<map key="email">
<string key="type">string</string>
<string key="format">email</string>
<!---->
<string key="pattern">.+@.+</string>
</map>
<map key="ip-v4-address">
<string key="type">string</string>
<string key="format">ipv4</string>
<!--The ip-v4-address type specifies an IPv4 address in dot decimal notation.-->
<string key="pattern">((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]).){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])</string>
</map>
<map key="ip-v6-address">
<string key="type">string</string>
<string key="format">ipv6</string>
<!--The ip-v6-address type specifies an IPv6 address represented in 8 hextets separated by colons.This is based on the pattern provided here: https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses with some customizations.-->
<string key="pattern">(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|[fF][eE]80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::([fF]{4}(:0{1,4}){0,1}:){0,1}((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]).){3,3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]).){3,3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]))</string>
</map>
<map key="hostname">
<string key="type">string</string>
<string key="format">idn-hostname</string>
<!---->
<string key="pattern">.+</string>
</map>
<map key="uri">
<string key="type">string</string>
<string key="format">uri</string>
<!---->
</map>
<map key="uri-reference">
<string key="type">string</string>
<string key="format">uri-reference</string>
<!---->
</map>
</xsl:variable>

</xsl:stylesheet>
11 changes: 8 additions & 3 deletions build/metaschema/lib/metaschema.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -398,20 +398,24 @@
<xs:enumeration value="boolean" />
<xs:enumeration value="string" />
<xs:enumeration value="NCName" />
<xs:enumeration value="decimal" />
<xs:enumeration value="float" />
<xs:enumeration value="double" />
<xs:enumeration value="integer" />
<xs:enumeration value="IDREF"/>
<xs:enumeration value="nonNegativeInteger"/>
<xs:enumeration value="positiveInteger"/>

<!-- specialized datatypes -->
<xs:enumeration value="ip-v4-address"/>
<xs:enumeration value="ip-v6-address"/>
<xs:enumeration value="dateTime-with-timezone"/>
<xs:enumeration value="date-with-timezone"/>
<!--<xs:enumeration value="percent"/>-->
<xs:enumeration value="email"/>
<xs:enumeration value="hostname"/>
<xs:enumeration value="ip-v4-address"/>
<xs:enumeration value="ip-v6-address"/>
<xs:enumeration value="uri"/>
<xs:enumeration value="uri-reference"/>
<xs:enumeration value="base64"/>
</xs:restriction>
</xs:simpleType>

Expand All @@ -420,6 +424,7 @@
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="ID" />
<xs:enumeration value="IDREF"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
Expand Down
15 changes: 5 additions & 10 deletions build/metaschema/xml/oscal-datatypes.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,6 @@
</xs:restriction>
</xs:simpleType>

<xs:simpleType name="percent">
<xs:annotation>
<xs:documentation>The percent type specifies a percentage from 0 to 100.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="100"/>
</xs:restriction>
</xs:simpleType>

<xs:simpleType name="email">
<xs:annotation>
<xs:documentation></xs:documentation>
Expand Down Expand Up @@ -89,6 +79,11 @@
</xs:annotation>
<xs:restriction base="xs:anyURI">
<xs:whiteSpace value="collapse"/>
<xs:pattern value="\p{L}[\p{L}\d+\-\.]*:.+">
<xs:annotation>
<xs:documentation>Requires a scheme with colon per RFC 3986</xs:documentation>
</xs:annotation>
</xs:pattern>
</xs:restriction>
</xs:simpleType>

Expand Down
71 changes: 52 additions & 19 deletions build/metaschema/xml/produce-xsd.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,14 @@
<xs:simpleType name="boolean"/>
<xs:simpleType name="string"/>
<xs:simpleType name="NCName"/>
<xs:simpleType name="decimal"/>
<xs:simpleType name="float"/>
<xs:simpleType name="double"/>
<xs:simpleType name="integer"/>
<xs:simpleType name="nonNegativeInteger"/>
<xs:simpleType name="positiveInteger"/>
<xs:simpleType name="IDREF"/>
<xs:simpleType name="ID"/>
</xsl:variable>

<xsl:template match="namespace"/>
Expand All @@ -122,26 +127,48 @@
<!--<xsl:template match="define-field[@as-type='markup-multiline'][false() (: xml wrap is not on so we get no element :)]"/>-->

<xsl:template match="define-field">
<xs:element name="{@name }">
<xsl:apply-templates select="." mode="annotated"/>
<xs:complexType mixed="true">
<xsl:apply-templates select="key | flag"/>
</xs:complexType>
</xs:element>
</xsl:template>

<xsl:template priority="5" match="define-field[@as-type='empty']">
<xs:element name="{@name }">
<xsl:apply-templates select="." mode="annotated"/>
<xs:complexType>
<xsl:if test="not(@as-type='empty')">
<xsl:attribute name="mixed">true</xsl:attribute>
</xsl:if>
<xsl:if test="@as-type='markup-line'">
<xs:group ref="{$declaration-prefix}:everything-inline"/>
</xsl:if>
<xsl:if test="@as-type='markup-multiline'">
<xs:group ref="{$declaration-prefix}:prose"/>
</xsl:if>
<xsl:apply-templates select="key | flag"/>
</xs:complexType>
</xs:element>
</xsl:template>

<xsl:template priority="5" match="define-field[@as-type='markup-line']">
<xs:element name="{@name }">
<xsl:apply-templates select="." mode="annotated"/>
<xs:complexType mixed="true">
<xs:group ref="{$declaration-prefix}:everything-inline"/>
<xsl:apply-templates select="key | flag"/>
</xs:complexType>
</xs:element>
</xsl:template>

<xsl:template priority="5" match="define-field[@as-type='markup-multiline']">
<xs:element name="{@name }">
<xsl:apply-templates select="." mode="annotated"/>
<xs:complexType mixed="true">
<xs:group ref="{$declaration-prefix}:prose"/>
<xsl:apply-templates select="key | flag"/>
</xs:complexType>
</xs:element>
</xsl:template>

<xsl:template match="define-field[@as-type='boolean']">
<xs:element name="{@name }" type="xs:boolean">
<xsl:template priority="3" match="define-field[exists(@as-type)]">
<xs:element name="{@name }">
<xsl:call-template name="assign-type">
<xsl:with-param name="datatype" select="@as-type"/>
</xsl:call-template>
<xsl:apply-templates select="." mode="annotated"/>
</xs:element>
</xsl:template>
Expand Down Expand Up @@ -210,8 +237,6 @@
<xs:group ref="{$declaration-prefix}:prose" maxOccurs="unbounded" minOccurs="0"/>
</xsl:template>



<xsl:template match="flag | key">
<xsl:variable name="datatype" select="(@as-type,key('definition-by-name',@ref)/@as-type)[1]"/>
<xsl:variable name="value-list" select="(valid-values,key('definition-by-name',@ref)/valid-values)[1]"/>
Expand All @@ -223,12 +248,9 @@
<!-- annotate as datatype or string unless an exclusive value-list is given -->
<xsl:if test="empty($value-list)">
<!-- overriding string datatype on attribute -->
<xsl:for-each select="$datatype[.=$available-custom-types/@name]">
<xsl:attribute name="type" expand-text="true" select="concat($declaration-prefix,':',.)"/>
</xsl:for-each>
<xsl:for-each select="$datatype[.=$built-in-types/@name]">
<xsl:attribute name="type" expand-text="true" select="concat('xs:',.)"/>
</xsl:for-each>
<xsl:call-template name="assign-type">
<xsl:with-param name="datatype" select="$datatype"/>
</xsl:call-template>
</xsl:if>

<xsl:apply-templates select=".[exists(@name)] | key('definition-by-name',@ref)" mode="annotated"/>
Expand All @@ -237,6 +259,17 @@
</xsl:apply-templates>
</xs:attribute>
</xsl:template>

<xsl:template name="assign-type">
<xsl:param name="datatype"/>
<xsl:for-each select="$datatype[. = $available-custom-types/@name]">
<xsl:attribute name="type" expand-text="true"
select="concat($declaration-prefix, ':', .)"/>
</xsl:for-each>
<xsl:for-each select="$datatype[. = $built-in-types/@name]">
<xsl:attribute name="type" expand-text="true" select="concat('xs:', .)"/>
</xsl:for-each>
</xsl:template>

<!-- When allow-other=yes, we union the enumeration with the declared datatype -->
<xsl:template match="valid-values[@allow-other='yes']">
Expand Down

0 comments on commit dab89fb

Please sign in to comment.