Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue468 metaschema enhancements #484

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
131c37c
Removed unnecessary metaschema check on json-value-key
wendellpiez Sep 3, 2019
ea2d351
Now implementing in-xml="with-wrapper | unwrapped" on markup multilin…
wendellpiez Sep 3, 2019
ef08974
Updating catalog and profile schemas for (prose) unwrapping behavior
wendellpiez Sep 4, 2019
8401f5b
Renamed 'json-behavior' in Metaschema to 'in-json' for consistency wi…
wendellpiez Sep 4, 2019
eac7b5b
Updating syntax in metaschemas 'in-json' for 'json-behavior'
wendellpiez Sep 4, 2019
9602ca1
Updating json converter generator to provide in-xml behavior 'GROUPED'
wendellpiez Sep 4, 2019
576665c
Refining json converter production from Metaschema
wendellpiez Sep 4, 2019
b1643a4
Repairing egregious syntax error
wendellpiez Sep 4, 2019
3649249
Rectify bug introduced with new feature
wendellpiez Sep 4, 2019
e1a3ea1
Adding support for 'date' and 'dateTime' datatypes, with no time zone…
wendellpiez Sep 5, 2019
3ba6cb3
Improvements and corrections to datatypes docs
wendellpiez Sep 6, 2019
aa0ead1
More small repairs on datatypes descriptions (table markup)
wendellpiez Sep 6, 2019
5ada681
Built out validations of allowed (enumerated) values, including Metas…
wendellpiez Sep 10, 2019
66e21f0
Straightening kinks in datatype metaschema meta-validation
wendellpiez Sep 10, 2019
6c48038
More special handling of recalcitrant datatypes, this time 'NMTOKENS'…
wendellpiez Sep 10, 2019
a54cc4f
Addressing #463, adding `id`, `class` and `title` to `group` in profi…
wendellpiez Sep 11, 2019
46d6a92
Schematron improvements; documentation revisions (removing references…
wendellpiez Sep 12, 2019
34f18e1
New Schematron for SP800-53-style catalogs
wendellpiez Sep 12, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build/ci-cd/validate-metaschema.sh
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ if [ $cmd_exitcode -ne 0 ]; then
fi
# the following is needed by the compiled template
cp "${metaschema_lib}/metaschema-compose.xsl" "${SCRATCH_DIR}"
cp "${metaschema_lib}/oscal-datatypes-check.xsl" "${SCRATCH_DIR}"

exitcode=0
shopt -s nullglob
Expand Down
55 changes: 34 additions & 21 deletions build/metaschema/json/json-schema-metamap.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -302,32 +302,37 @@
<xsl:if test="empty(formal-name | description)">
<xsl:apply-templates select="key('definition-by-name',@ref)/(formal-name | description)"/>
</xsl:if>
<xsl:apply-templates select="(valid-values,key('definition-by-name',@ref)/valid-values)[1]"/>
<xsl:apply-templates select="(allowed-values,key('definition-by-name',@ref)/allowed-values)[1]"/>
</map>
</xsl:template>

<!-- No restriction is introduced when allow others is 'yes' -->
<xsl:template match="valid-values[@allow-other='yes']"/>
<xsl:template match="allowed-values[@allow-other='yes']"/>

<xsl:template match="valid-values">
<xsl:template match="allowed-values">
<xsl:param name="datatype" as="xs:string">string</xsl:param>
<array key="enum">
<xsl:apply-templates/>
</array>
</xsl:template>

<xsl:template match="valid-values/value">
<string>
<xsl:apply-templates select="@name"/>
</string>
<xsl:template match="allowed-values/enum">
<!-- since the JSON must show enumerated values consistent with the base type notation -->
<xsl:variable name="type-declaration">
<xsl:apply-templates select="../.." mode="object-type"/>
</xsl:variable>
<xsl:variable name="base-type" select="$type-declaration/*[@key='type']"/>
<xsl:element namespace="http://www.w3.org/2005/xpath-functions" name="{$base-type}">
<xsl:apply-templates select="@value"/>
</xsl:element>
</xsl:template>

<!-- irrespective of min-occurs and max-occurs, assemblies and fields designated
with key flags are represented as objects, never arrays, as the key
flag serves as a label -->
<xsl:template mode="declaration" priority="5"
match="assembly[group-as/@json-behavior='BY_KEY'][exists(key('definition-by-name',@ref)/json-key)] |
field[group-as/@json-behavior='BY_KEY'][exists(key('definition-by-name',@ref)/json-key)]">
match="assembly[group-as/@in-json='BY_KEY'][exists(key('definition-by-name',@ref)/json-key)] |
field[group-as/@in-json='BY_KEY'][exists(key('definition-by-name',@ref)/json-key)]">
<xsl:variable name="group-name" select="group-as/@name"/>
<map key="{ $group-name }">
<string key="type">object</string>
Expand Down Expand Up @@ -361,7 +366,7 @@
<!-- Otherwise, always an array when min-occurs is greater than 1 or whenever so designated -->
<xsl:template mode="declaration" priority="3" expand-text="yes"
match="assembly[number(@min-occurs) &gt; 1 ] | field[number(@min-occurs) &gt; 1 ] |
assembly[group-as/@json-behavior='ARRAY'] | field[group-as/@json-behavior='ARRAY']">
assembly[group-as/@in-json='ARRAY'] | field[group-as/@in-json='ARRAY']">
<map key="{ group-as/@name }">
<string key="type">array</string>
<!-- despite @min-occurs = 0, we have a minimum of 1 since the array itself is optional -->
Expand All @@ -377,7 +382,7 @@
</xsl:template>

<!-- Now matching when min-occurs is 1 or less, max-occurs is more than 1,
and group-as/@json-behavior is not 'BY-KEY' or 'ARRAY' ... -->
and group-as/@in-json is not 'BY-KEY' or 'ARRAY' ... -->
<xsl:template mode="declaration" match="assembly | field">
<map key="{ group-as/@name }">
<array key="anyOf">
Expand Down Expand Up @@ -467,7 +472,7 @@
<number key="minimum">0</number>
</xsl:template>

<!--Not supporting float and double-->
<!--Not supporting float or double-->

<xsl:template priority="2.1" match="*[@as-type = $datatypes/*/@key]" mode="object-type">
<xsl:copy-of select="key('datatypes-by-name',@as-type,$datatypes)/*"/>
Expand All @@ -479,44 +484,52 @@
<xsl:variable name="datatypes" expand-text="false">
<map key="decimal">
<string key="type">number</string>
<string key="pattern">(\+|-)?([0-9]+(\.[0-9]*)?|\.[0-9]+)</string>
<string key="pattern">^(\+|-)?([0-9]+(\.[0-9]*)?|\.[0-9]+)$</string>
</map>
<map key="date">
<string key="type">string</string>
<!--<string key="format">date</string> JQ 'date' implementation does not permit time zone -->
<string key="pattern">^((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))(Z|[+-][0-9]{2}:[0-9]{2})?$</string>
</map>
<map key="dateTime">
<string key="type">string</string>
<!--<string key="format">date-time</string> JQ 'date-time' implementation requires time zone -->
<string key="pattern">^((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})?$</string>
</map>

<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">((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))(Z|[+-][0-9]{2}:[0-9]{2})</string>
<string key="pattern">^((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))(Z|[+-][0-9]{2}:[0-9]{2})$</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">((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})</string>
<string key="pattern">^((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$</string>
</map>
<map key="email">
<string key="type">string</string>
<string key="format">email</string>
<!---->
<string key="pattern">.+@.+</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>
<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>
<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>
<string key="pattern">^.+$</string>
</map>
<map key="uri">
<string key="type">string</string>
Expand Down
32 changes: 23 additions & 9 deletions build/metaschema/json/produce-json-converter.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<xsl:import href="../lib/metaschema-compose.xsl"/>

<xsl:template match="/">
<!--<xsl:apply-templates select="METASCHEMA"/>-->
<xsl:apply-templates select="$composed-metaschema/METASCHEMA"/>
</xsl:template>

Expand Down Expand Up @@ -128,14 +129,22 @@
<!-- 'any' keyword not handled -->
<xsl:template match="any" priority="10"/>

<xsl:template match="model | choice" priority="2">
<xsl:template match="model | choice" priority="3">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="model//*">
<XSLT:apply-templates mode="#current" select="*[@key=({string-join((@ref/('''' || . || ''''),group-as/@name/('''' || . || '''')),', ')})]"/>
</xsl:template>

<xsl:template priority="2" match="model//*[group-as/@in-xml='GROUPED']">
<XSLT:for-each-group group-by="true()" select="*[@key=({string-join((@ref/('''' || . || ''''),group-as/@name/('''' || . || '''')),', ')})]">
<XSLT:element name="{group-as/@name}" namespace="{$target-namespace}">
<XSLT:apply-templates mode="#current" select="current-group()"/>
</XSLT:element>
</XSLT:for-each-group>
</xsl:template>

<!--<xsl:template match="model/prose" priority="2">
<XSLT:apply-templates mode="#current" select="*[@key='prose']"/>
</xsl:template>-->
Expand Down Expand Up @@ -168,7 +177,16 @@

<xsl:comment expand-text="yes">{ $field-match }</xsl:comment>
<XSLT:template match="{$field-match}" priority="5" mode="json2xml">
<xsl:apply-templates select="." mode="field-text"/>
<xsl:choose>
<xsl:when test="key('references-by-name',@name)/@in-xml='UNWRAPPED'">
<xsl:apply-templates select="." mode="field-text"/>
</xsl:when>
<xsl:otherwise>
<XSLT:element name="{@name}" namespace="{$target-namespace}">
<xsl:apply-templates select="." mode="field-text"/>
</XSLT:element>
</xsl:otherwise>
</xsl:choose>
</XSLT:template>
<xsl:for-each select="json-key | json-value-key">
<xsl:message expand-text="yes">{ local-name()} is ignored on field { ../@name } of type 'markup-multiline' </xsl:message>"
Expand Down Expand Up @@ -240,8 +258,6 @@
mode="json2xml">
<XSLT:apply-templates/>
</XSLT:template>



<!-- Now, a template to match where we want attributes - flags not reserved for the value key ... -->
<XSLT:template
Expand Down Expand Up @@ -366,13 +382,11 @@
</XSLT:template>

<xsl:if test="exists($group-names)">
<xsl:variable name="group-name-seq" select="string-join($group-names ! ('''' || . || ''''),', ')"/>
<xsl:for-each select="child::json-key">
<xsl:comment> Mapping object with key to element with attribute </xsl:comment>
<xsl:variable name="group-name-seq" select="string-join($group-names ! ('''' || . || ''''),', ')"/>
<XSLT:template match="map[@key=({ $group-name-seq })]" priority="5" mode="json2xml">
<XSLT:apply-templates mode="json2xml"/>
<XSLT:apply-templates mode="json2xml"/>
</XSLT:template>

<XSLT:template priority="2" match="map[@key=({ $group-name-seq })]/*/@key" mode="as-attribute">
<XSLT:attribute name="{@flag-name}">
<XSLT:value-of select="."/>
Expand All @@ -387,7 +401,7 @@
</xsl:if>
<!--<xsl:call-template name="drop-address"/>-->
</xsl:template>

<xsl:template name="furniture">

<XSLT:output indent="yes"/>
Expand Down
Loading