Skip to content

Commit

Permalink
Updated to new design (usnistgov#436): Metaschema schema, Schematron,…
Browse files Browse the repository at this point in the history
… metaschema update XSLT - will break the build for now
  • Loading branch information
wendellpiez authored and david-waltermire committed Aug 16, 2019
1 parent ca76229 commit 7c4186b
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 79 deletions.
1 change: 0 additions & 1 deletion build/metaschema/json/json-schema-metamap.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,6 @@
match="assembly[exists(key('definition-by-name',@ref)/key)] |
field[exists(key('definition-by-name',@ref)/key)]">
<xsl:variable name="group-name" select="key('definition-by-name',@ref)/@group-as"/>
<xsl:message expand-text="yes">{ $group-name }</xsl:message>
<map key="{ $group-name }">
<string key="type">object</string>
<map key="additionalProperties">
Expand Down
32 changes: 15 additions & 17 deletions build/metaschema/lib/metaschema-check.sch
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

<xsl:import href="metaschema-compose.xsl"/>

<!-- grouping name can't be the same as the name
group-as is present whenever not(@max-occurs = 1) -->
<sch:pattern>

<sch:rule context="m:define-assembly | m:define-field | m:define-flag">
Expand All @@ -38,25 +40,14 @@
<sch:assert test="exists(m:description)">description missing from <sch:name/></sch:assert>
<sch:assert test="empty(self::m:define-assembly) or exists(m:model)">model missing from <sch:name/></sch:assert>
<sch:report test="@name=$prose-names">Can't use name '<sch:value-of select="@name"/>': it's reserved for prose.</sch:report>
<!--<sch:assert test="count( key('definition-by-name',@name) | key('definition-by-name',@name,$imported-schemas) ) ge 1">Not a distinct definition</sch:assert>-->
<!--FIX:<sch:report test="@name = ../*/@group-as">Clashing name with group name: <sch:value-of select="@name"/></sch:report>-->
<!--FIX:<sch:report test="@group-as = ../*/@name">Clashing group name with name: <sch:value-of select="@name"/></sch:report>-->
<sch:assert test="empty(@address) or m:flag/@name=@address">Definition set to address by '<sch:value-of select="@address"/>', but no flag with that name is declared.</sch:assert>
<!--FIX:<sch:assert test="matches(@group-as,'\S') or empty(self::m:define-assembly) or empty($composed-metaschema//m:assembly[exists(@max-occurs) and string(@max-occurs) != '0'][@ref=current()/@name])">Assembly can appear multiply but has no grouping name (@group-as). See definition(s) for <xsl:value-of separator=", " select="$composed-metaschema//m:assembly[exists(@max-occurs) and string(@max-occurs) != '0'][@ref=current()/@name]/ancestor::m:define-assembly/@name"/></sch:assert>-->
<!--FIX:<sch:assert test="matches(@group-as,'\S') or empty(self::m:define-field) or empty($composed-metaschema//m:field[exists(@max-occurs) and string(@max-occurs) != '0'][@ref=current()/@name])">Field can appear multiply but has no grouping name (@group-as). See definition(s) for <xsl:value-of separator=", " select="$composed-metaschema//m:field[exists(@max-occurs) and string(@max-occurs) != '0'][@ref=current()/@name]/ancestor::m:define-assembly/@name"/></sch:assert>-->
<sch:assert test="not(@as='boolean') or empty(m:flag)">Property defined as boolean may not have flags.</sch:assert>
<sch:assert test="not(@as-type='boolean') or empty(m:flag)">Property defined as boolean may not have flags.</sch:assert>
</sch:rule>

<!--<sch:rule context="define-field[@address-by='id']/*">
<sch:assert test="empty(*)">Line defined as string may not have attributes</sch:assert>
</sch:rule>-->


<sch:rule context="m:key">
<sch:rule context="m:json-key">
<sch:let name="decl" value="key('definition-by-name',@ref,$composed-metaschema)"/>
<sch:assert test="exists(@name|@ref)">Flag declaration must have 'name' or 'ref'</sch:assert>
<sch:assert test="count(@name|@ref) eq 1">Flag declaration may be by name or reference, not both (remove @name or @ref)</sch:assert>

<sch:assert test="count(../*[(@name|@ref) = current()/(@name|@ref)]) eq 1">Only one flag (or key) may be named
<sch:value-of select="@name"/>
</sch:assert>
Expand All @@ -76,6 +67,7 @@
<sch:assert test="not(@name = preceding-sibling::*/@name)">Value '<sch:value-of select="@name"/>' may only be
specified once for flag '<sch:value-of select="../../@name"/>'.</sch:assert>
</sch:rule>

<sch:rule context="m:flag">
<sch:let name="decl" value="key('definition-by-name',@ref,$composed-metaschema)"/>
<sch:assert test="exists(@name|@ref)">Flag declaration must have 'name' or 'ref'</sch:assert>
Expand All @@ -94,18 +86,25 @@
<sch:rule context="m:prose">
<sch:assert test="count(../m:prose) eq 1">Prose may not appear in more than once in a model</sch:assert>
</sch:rule>

<!-- 'choice' is not subjected to rules for other elements inside 'model' -->
<sch:rule context="m:choice"/>

<sch:rule context="m:field | m:assembly">
<sch:let name="decl" value="key('definition-by-name',@ref,$composed-metaschema)"/>
<sch:assert test="exists($decl)">No definition found for '<sch:value-of select="@ref"/>' <sch:value-of select="local-name()"/></sch:assert>
<sch:assert role="warning" test="empty($decl) or exists(self::m:field|self::m:assembly) or exists($decl/@group-as)">Reference is made to <sch:value-of select="local-name()"/> '<sch:value-of select="@ref"/>', but their definition does not give a group name.</sch:assert>

<sch:report test="@ref = ../(* except current())/@ref">Everything named the same must appear together</sch:report>
<sch:report test="@ref = ../*/@group-as">Clashing name with group name: <sch:value-of select="@ref"/></sch:report>
<sch:report test="@group-as = ../*/@ref">Clashing group name with name: <sch:value-of select="@ref"/></sch:report>
<sch:report test="@ref = group-as/@name">Clashing name with group name: <sch:value-of select="@ref"/></sch:report>
</sch:rule>


<sch:rule context="m:group-as">
<sch:let name="name" value="@name"/>
<sch:assert test="count(../../*/(. | m:group-as)[(@name|@ref) = $name]) eq 1">Name clash on '<sch:value-of select="@name"/>'</sch:assert>
<sch:report test="../@max-occurs/number() = 1">Grouping name is given but max-occurs is 1.</sch:report>
</sch:rule>

<sch:rule context="m:example/m:description | m:example/m:remarks"/>

<sch:rule context="m:example/*">
Expand All @@ -114,7 +113,6 @@
</sch:rule>
</sch:pattern>


<sch:pattern>
<sch:rule context="/m:METASCHEMA">
<sch:assert test="@root=*/@name">METASCHEMA/@root should be one of <sch:value-of select="string-join(*/@name,', ')"/></sch:assert>
Expand Down
33 changes: 32 additions & 1 deletion build/metaschema/lib/metaschema-update.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@

<xsl:output indent="yes"/>

<xsl:strip-space elements="*"/>

<xsl:preserve-space elements="formal-name description p pre"/>

<xsl:mode on-no-match="shallow-copy"/>

<xsl:key name="definition-by-name" match="define-assembly | define-field | define-flag" use="@name"/>

<xsl:template match="/comment() | /processing-instruction() | /*">
<xsl:text>&#xA;</xsl:text>
<xsl:next-match/>
Expand All @@ -34,7 +40,7 @@

<xsl:template match="define-assembly | define-field |define-flag">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="formal-name | description"/>
<xsl:apply-templates select="* except (formal-name | description | remarks | example)"/>
<xsl:apply-templates select="remarks | example"/>
Expand All @@ -46,25 +52,50 @@
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="min-occurs">1</xsl:attribute>
<xsl:apply-templates select="." mode="group-as"/>
</xsl:copy>
</xsl:template>

<xsl:template match="*" mode="group-as">
<xsl:for-each select="key('definition-by-name',(@named|@ref))/@group-as">
<group-as name="{ . }"/>
</xsl:for-each>
</xsl:template>

<xsl:template match="fields">
<field>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="max-occurs">unbounded</xsl:attribute>
<xsl:apply-templates select="." mode="group-as"/>
</field>
</xsl:template>

<xsl:template match="assemblies">
<assembly>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="max-occurs">unbounded</xsl:attribute>
<xsl:apply-templates select="." mode="group-as"/>
</assembly>
</xsl:template>

<xsl:template match="field | assembly">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
<xsl:apply-templates select="." mode="group-as"/>
</xsl:copy>
</xsl:template>

<xsl:template match="define-field/@group-as | define-assembly/@group-as"/>

<xsl:template match="field/@required | fields/@required | assembly/@required | assemblies/@required">
<xsl:attribute name="min-occurs">1</xsl:attribute>
</xsl:template>

<xsl:template match="key">
<json-key>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</json-key>
</xsl:template>

</xsl:stylesheet>
82 changes: 50 additions & 32 deletions build/metaschema/lib/metaschema.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,7 @@
<xs:element minOccurs="0" maxOccurs="unbounded" ref="m:example"
/>
</xs:sequence>
<xs:attribute name="datatype">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="boolean"/>
<xs:enumeration value="empty"/>
<xs:enumeration value="string"/>
<xs:enumeration value="mixed"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="as-type" type="m:field-types"/>
<xs:attribute name="collapsible" type="xs:NCName"/>
<xs:attribute name="name" use="required" type="xs:NCName"/>
<xs:attribute name="module" type="xs:anyURI"/>
Expand All @@ -113,7 +104,7 @@
<xs:element minOccurs="0" ref="m:description"/>
<xs:element minOccurs="0" ref="m:remarks"/>
</xs:sequence>
<xs:attribute name="datatype" type="xs:NCName"/>
<xs:attribute name="as-type" type="m:flag-types"/>
<!-- should Schematron check uniqueness among siblings irrespective of datatype -->
<xs:attribute name="name" type="xs:NCName"/>
<xs:attribute name="ref" type="xs:NCName"/>
Expand Down Expand Up @@ -198,7 +189,7 @@
</xs:sequence>
<xs:attribute name="name" use="required" type="xs:NCName"/>
<!-- datatype should default to 'string' -->
<xs:attribute name="datatype" type="xs:NCName"/>
<xs:attribute name="as-type" type="m:flag-types"/>
<!-- defined for composed (compiled) metaschemas -->
<xs:attribute name="module" type="xs:anyURI"/>
</xs:complexType>
Expand Down Expand Up @@ -358,31 +349,13 @@
<xs:element minOccurs="0" ref="m:remarks"/>
<xs:element minOccurs="0" ref="m:valid-values"/>
</xs:sequence>
<xs:attribute name="datatype" type="xs:NCName"/>
<xs:attribute name="as-type" type="m:flag-types"/>
<xs:attribute name="name" type="xs:NCName"/>
<xs:attribute name="ref" type="xs:NCName"/>
<xs:attribute name="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
<!--<xs:complexType name="local-flag-definition">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="m:value-key"/>
<xs:element minOccurs="0" ref="m:formal-name"/>
<xs:element minOccurs="0" ref="m:description"/>
<xs:element minOccurs="0" ref="m:remarks"/>
<xs:element minOccurs="0" ref="m:valid-values"/>
</xs:sequence>
<xs:attribute name="datatype" type="xs:NCName"/>
<xs:attribute name="name" type="xs:NCName" use="required"/>
<xs:attribute name="required" type="xs:NCName"/>
</xs:complexType>
<xs:complexType name="flag-reference">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="m:value-key"/>
</xs:sequence>
<xs:attribute name="ref" type="xs:NCName" use="required"/>
</xs:complexType>-->


<xs:element name="choice">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
Expand Down Expand Up @@ -419,4 +392,49 @@
<xs:attribute name="name" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>

<xs:simpleType name="simple-datatypes">
<xs:restriction base="xs:string">
<xs:enumeration value="boolean" />
<xs:enumeration value="string" />
<xs:enumeration value="NCName" />
<xs:enumeration value="double" />
<xs:enumeration value="integer" />
<xs:enumeration value="IDREF"/>

<!-- 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="uri"/>
<xs:enumeration value="uri-reference"/>
</xs:restriction>
</xs:simpleType>

<xs:simpleType name="flag-types">
<xs:union memberTypes="m:simple-datatypes">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="ID" />
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>

<xs:simpleType name="field-types">
<xs:union memberTypes="m:simple-datatypes">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="empty" />
<xs:enumeration value="markup-line"/>
<xs:enumeration value="markup-multiline"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>

</xs:schema>
4 changes: 3 additions & 1 deletion build/metaschema/unit-testing/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ while IFS= read -d $'\0' -r dir ; do
fi
fi

# diff the generated schema with the expected schema
# diff the generated JSON schema with the expected JSON schema
expected_schema="$path/${base}_json-schema.json"
# Only perform this check if an expected schema exists
if [ -f "$expected_schema" ]; then
Expand Down Expand Up @@ -145,3 +145,5 @@ while IFS= read -d $'\0' -r dir ; do
done < <(find "$dir" -name "${base}_test_*.json" -mindepth 1 -maxdepth 1 -type f -print0)
done < <(find "$dir" -name "*_metaschema.xml" -mindepth 1 -maxdepth 1 -type f -print0)
done < <(find "$TEST_DIR" -mindepth 1 -maxdepth 1 -type d -print0)

exit $exitcode
Loading

0 comments on commit 7c4186b

Please sign in to comment.