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

Repairs and new features for schema and converter generators #119

Merged
merged 1 commit into from
Mar 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,40 @@
"description" : "Has a global definition",
"type" : "string" },
"local-field" :
{ "local-field" :
{ "title" : "Field defined locally",
"description" : "Has a local definition",
"$id" : "#/definitions/local-field",
"type" : "string" } },
{ "title" : "Field defined locally",
"description" : "Has a local definition",
"type" : "string" },
"global-field" :
{ "$ref" : "#/definitions/global-field" },
"local-assembly" :
{ "local-assembly" :
{ "title" : "Assembly defined locally",
"description" : "Has a local definition",
"$id" : "#/definitions/local-assembly",
"type" : "object",
"properties" :
{ "local-field2" :
"local-assemblies" :
{ "anyOf" :
[
{ "title" : "Assembly defined locally",
"description" : "Has a local definition",
"type" : "object",
"properties" :
{ "local-field2" :
{ "title" : "Field defined locally",
"description" : "Has a local definition",
"$id" : "#/definitions/local-field2",
"type" : "string" } },
"global-field" :
{ "$ref" : "#/definitions/global-field" } },
"additionalProperties" : false } },
"type" : "string" },
"global-field" :
{ "$ref" : "#/definitions/global-field" } },
"additionalProperties" : false },

{ "type" : "array",
"minItems" : 1,
"items" :
{ "title" : "Assembly defined locally",
"description" : "Has a local definition",
"type" : "object",
"properties" :
{ "local-field2" :
{ "title" : "Field defined locally",
"description" : "Has a local definition",
"type" : "string" },
"global-field" :
{ "$ref" : "#/definitions/global-field" } },
"additionalProperties" : false } } ] },
"global-assembly" :
{ "$ref" : "#/definitions/global-assembly" } },
"additionalProperties" : false },
Expand All @@ -57,11 +68,9 @@
"type" : "object",
"properties" :
{ "local-field2" :
{ "local-field2" :
{ "title" : "Field defined locally",
"description" : "Has a local definition",
"$id" : "#/definitions/local-field2",
"type" : "string" } },
{ "title" : "Field defined locally",
"description" : "Has a local definition",
"type" : "string" },
"global-field" :
{ "$ref" : "#/definitions/global-field" } },
"additionalProperties" : false } },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="../../../toolchains/xslt-M4/validate/metaschema-check.sch" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<!--<?xml-model href="../../../toolchains/xslt-M4/validate/metaschema-check.sch" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>-->
<!-- OSCAL CATALOG METASCHEMA -->
<!-- validate with XSD and Schematron (linked) -->
<METASCHEMA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://csrc.nist.gov/ns/oscal/metaschema/1.0"
xsi:schemaLocation="../../../toolchains/xslt-M4/validate/metaschema.xsd">
xsi:schemaLocation="http://csrc.nist.gov/ns/oscal/metaschema/1.0 ../../../toolchains/xslt-M4/validate/metaschema.xsd"
xmlns="http://csrc.nist.gov/ns/oscal/metaschema/1.0">
<schema-name>Metaschema Unit Test: group-as</schema-name>
<schema-version>1.0-milestone1</schema-version>
<short-name>metaschema-group-as</short-name>
Expand All @@ -24,9 +24,10 @@
<description>Has a local definition</description>
</define-field>
<field ref="global-field"/>
<define-assembly name="local-assembly">
<define-assembly name="local-assembly" max-occurs="unbounded">
<formal-name>Assembly defined locally</formal-name>
<description>Has a local definition</description>
<group-as name="local-assemblies"/>
<model>
<define-field name="local-field2" as-type="string">
<formal-name>Field defined locally</formal-name>
Expand Down
185 changes: 165 additions & 20 deletions toolchains/xslt-M4/converter-gen/produce-xml-converter.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

<!-- Interface template for override -->
<xsl:template match="*" mode="make-match" as="xs:string">
<xsl:apply-templates select="." mode="make-xml-match"/>
<xsl:value-of>
<xsl:apply-templates select="." mode="make-xml-match"/>
</xsl:value-of>
</xsl:template>

<!-- Interface template for override -->
Expand Down Expand Up @@ -52,26 +54,58 @@
<!-\-<XSLT:output-character character="&#xE0000;" string="\"/>-\->
</XSLT:character-map>-->

<!-- first we produce templates for (each) of the global definitions
and for any flags thereon.-->
<xsl:for-each-group select="//*[@scope = 'global'][not(@recursive='true')]/( . | child::flag )"
group-by="string-join((local-name(), @name), ':')">
<!-- These are all the same so we do only one, but we pass in the group to construct the match -->
<!-- first we produce templates for (each) of the global definitions in their combinations
(definition name and name-in-use) -->

<!--XXX refactor all this for legibility -->
<xsl:for-each-group select=".//assembly[@scope = 'global'][not(@recursive='true')]"
group-by="@gi">
<xsl:variable name="aliased" select="count(distinct-values(current-group()/@name)) gt 1"/>
<xsl:for-each-group select="current-group()" group-by="@name">
<!-- but we also break by type name since we have aliases (different type, same use-name) -->
<xsl:apply-templates select="current-group()[1]" mode="make-template">
<xsl:with-param name="team" tunnel="true" select="current-group()"/>
<xsl:with-param name="aliased" tunnel="true" select="$aliased"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:for-each-group>
<xsl:for-each-group select=".//field[@scope = 'global']"
group-by="@gi">
<xsl:variable name="aliased" select="count(distinct-values(current-group()/@name)) gt 1"/>
<xsl:for-each-group select="current-group()" group-by="@name">
<!-- but we also break by type name since we have aliases (different type, same use-name) -->
<xsl:apply-templates select="current-group()[1]" mode="make-template">
<xsl:with-param name="team" tunnel="true" select="current-group()"/>
<xsl:with-param name="aliased" tunnel="true" select="$aliased"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:for-each-group>

<!-- again, this time for (all) flags, also discriminating by data type -->
<xsl:for-each-group select=".//flag" group-by="string-join((@name, @as-type, @gi), ':')">
<xsl:apply-templates select="current-group()[1]" mode="make-template">
<xsl:with-param name="team" tunnel="true" select="current-group()"/>
</xsl:apply-templates>
</xsl:for-each-group>

<!-- next we produce templates for local definitions - a receiving template
filters out the globals ... -->
<xsl:apply-templates select=".//assembly | .//field | .//flag" mode="make-template-for-local"/>
<xsl:apply-templates select=".//assembly | .//field" mode="make-template-for-inline-definition"/>

<!--finally, if needed, a template for copying prose across, stripping ns -->
<xsl:call-template name="for-this-converter"/>

</XSLT:stylesheet>
</xsl:template>

<!-- For any combination of node type (assembly or field), @name, @gi we make a template, plus
another for any that are recursive ... we have to specify them so that templates matching these
do not collapse on each other when they have the same element names -->
<xsl:template name="make-templates-for-type">


</xsl:template>


<xsl:template name="xpath-namespace">
<xsl:attribute name="xpath-default-namespace" select="$source-namespace"/>
Expand Down Expand Up @@ -109,11 +143,9 @@
</xsl:if>
</xsl:template>

<xsl:template match="*[@scope='global']" mode="make-template-for-local"/>

<xsl:template priority="1" match="*[@scope='global']/flag" mode="make-template-for-local"/>
<xsl:template match="*[@scope='global']" mode="make-template-for-inline-definition"/>

<xsl:template match="*" mode="make-template-for-local">
<xsl:template match="*" mode="make-template-for-inline-definition">
<xsl:apply-templates select="." mode="make-template"/>
</xsl:template>

Expand All @@ -122,6 +154,7 @@

<!--Invoke by name when we wish to override mode 'template-for-global' -->
<xsl:template match="*" mode="make-template" name="make-template">
<xsl:param name="team" tunnel="true" select="."/>
<xsl:variable name="matching">
<xsl:apply-templates select="." mode="make-match"/>
</xsl:variable>
Expand All @@ -141,10 +174,10 @@
<xsl:if test="self::field[empty(flag[not(@key=$json-key-flag-name)])]">
<xsl:attribute name="in-json">SCALAR</xsl:attribute>
</xsl:if>
<xsl:if test="exists(@key)">
<xsl:if test="exists($team/@key)">
<XSLT:if test="$with-key">
<XSLT:attribute name="key">
<xsl:value-of select="@key"/>
<xsl:value-of select="($team/@key)[1]"/>
</XSLT:attribute>
</XSLT:if>
</xsl:if>
Expand All @@ -164,7 +197,8 @@
<XSLT:template match="{ $matching}">
<xsl:if test="not((.|..)/@scope='global')">
<xsl:attribute name="priority" select="count(ancestor-or-self::*)"/>
</xsl:if><xsl:call-template name="comment-template"/>
</xsl:if>
<xsl:call-template name="comment-template"/>
<flag in-json="string">
<xsl:copy-of select="@* except @scope"/>
<!-- rewriting in-json where necessary -->
Expand All @@ -177,14 +211,24 @@
<!-- In the XML, even a flag designated as a key is an attribute, so it will be produced without explicit instruction. -->
<xsl:template match="*" mode="make-key-flag"/>



<xsl:template priority="11" match="flag" mode="make-xml-match">
<xsl:param name="team" tunnel="true" select="."/>
<xsl:variable name="me" select="."/>
<xsl:variable name="team-matches" as="xs:string*">
<xsl:for-each select="$team">
<xsl:value-of>
<xsl:apply-templates select=".." mode="make-xml-match"/>
<xsl:text>/@</xsl:text>
<xsl:value-of select="@gi"/>
<!-- when the parent recurses, its match comes back with a '|' which we have to break out -->
<xsl:variable name="parent-match">
<xsl:apply-templates select=".." mode="make-xml-match"/>
</xsl:variable>
<xsl:for-each select="tokenize($parent-match,'\s*\|\s*')">
<xsl:if test="position() gt 1"> | </xsl:if>
<xsl:sequence select="."/>
<xsl:text>/</xsl:text>
<xsl:apply-templates select="$me" mode="make-xml-step"/>
</xsl:for-each>
</xsl:value-of>
</xsl:for-each>
</xsl:variable>
Expand All @@ -194,11 +238,112 @@
<xsl:template priority="11" match="flag" mode="make-xml-step">
<xsl:value-of select="'@' || @gi"/>
</xsl:template>

<!--<xsl:template priority="20" match="*[@recursive='true']" mode="make-xml-match">
<xsl:variable name="r">
<xsl:apply-templates select="ancestor::*[@name = current()/@name][1]"
mode="make-xml-match"/>
<xsl:text expand-text="true">//</xsl:text>
<xsl:next-match/>
</xsl:variable>
<xsl:message expand-text="true">{ $r }</xsl:message>
<xsl:sequence select="$r"/>
</xsl:template>-->

<xsl:template priority="10" match="*[@scope='global'] | group[*/@scope='global']" mode="make-xml-match make-xml-step">
<xsl:value-of select="@gi"/>

<!--a a//a

b1/a b1/a//a
b2/a b2/a//a
b3/a (when a does not recurse inside b3)-->


<xsl:template priority="10" match="*[@scope = 'global'] | group[*/@scope = 'global']" mode="make-xml-match">
<xsl:param name="aliased" tunnel="true" select="false()"/>
<xsl:param name="team" tunnel="true" select="."/>
<xsl:variable name="me" select="."/>

<xsl:choose>
<xsl:when test="$aliased">
<xsl:for-each select="$team/ancestor::*[exists(@gi)][1]">
<xsl:if test="position() gt 1"> | </xsl:if>
<xsl:call-template name="make-recurring-match">
<xsl:with-param name="me" select="$me"/>
<xsl:with-param name="prepend">
<xsl:apply-templates mode="make-xml-step" select="."/>
<xsl:text>/</xsl:text>
</xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="make-recurring-match">
<xsl:with-param name="me" select="$me"/>
</xsl:call-template>
</xsl:otherwise>

</xsl:choose>

<!--<xsl:variable name="contexts" as="xs:string+">
<xsl:choose>
<xsl:when test="$aliased">
<xsl:for-each-group select="$team/ancestor::*[exists(@gi)][1]" group-by="@gi">
<xsl:value-of>
<xsl:value-of select="current-grouping-key()"/>
<xs:text>/</xs:text>
<xsl:apply-templates mode="make-xml-step" select="$me"/>
</xsl:value-of>
</xsl:for-each-group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates mode="make-xml-step" select="$me"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:for-each select="$contexts">
<xsl:if test="position() gt 1"> | </xsl:if>
<xsl:sequence select="."/>
<xsl:if test=""
</xsl:for-each>-->

</xsl:template>

<xsl:template name="make-recurring-match">
<xsl:param name="me"/>
<xsl:param name="prepend"/>
<xsl:sequence select="$prepend"/>
<xsl:apply-templates mode="make-xml-step" select="$me"/>
<xsl:if test="$me/@name = $me/descendant::*[@recursive = 'true']/@name">
<xsl:text> | </xsl:text>
<xsl:sequence select="$prepend"/>
<xsl:apply-templates mode="make-xml-step" select="$me"/>
<xsl:text>/</xsl:text>
<xsl:if test="$me/@name = $me/child::*/descendant::*[@recursive = 'true']/@name"
>/</xsl:if>
<xsl:apply-templates mode="make-xml-step" select="$me"/>
</xsl:if>
</xsl:template>

<!--<xsl:template priority="10" match="*[@scope = 'global'] | group[*/@scope = 'global']" mode="make-xml-step">
<xsl:param name="aliased" tunnel="true" select="false()"/>
<xsl:param name="team" tunnel="true" select="."/>
<xsl:variable name="me" select="."/>
<xsl:choose>
<!-\- when an assembly or field definition has an alias, we must distinguish which ones we want -\->
<xsl:when test="$aliased">
<xsl:for-each-group select="$team/ancestor::*[exists(@gi)][1]" group-by="@gi">
<xsl:if test="position() gt 1"> | </xsl:if>
<xsl:value-of select="current-grouping-key()"/>
<xs:text>/</xs:text>
<xsl:value-of select="$me/@gi"/>
</xsl:for-each-group>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@gi"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>-->

<xsl:template match="*[exists(@gi)]" mode="make-xml-step">
<xsl:value-of select="@gi"/>
</xsl:template>
Expand Down
12 changes: 1 addition & 11 deletions toolchains/xslt-M4/converter-gen/supermodel-to-json.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
<xsl:element name="{(@in-json[matches(.,'\S')],'string')[1]}"
namespace="http://www.w3.org/2005/xpath-functions">
<xsl:copy-of
select="(../flag[@key=$key-flag-name],parent::field[@in-json = 'SCALAR']/@key, @key)[1]"/>
select="((../flag[@key=$key-flag-name],parent::field[@in-json = 'SCALAR'])/@key, @key)[1]"/>
<xsl:apply-templates select="." mode="cast-data"/>
</xsl:element>
</xsl:template>
Expand Down Expand Up @@ -171,16 +171,6 @@
<xsl:value-of select="$lines/self::* => string-join('&#xA;')"/>
</xsl:template>

<!--<xsl:template match="value[@as-type='markup-multiline']/*" mode="md" priority="100">
<xsl:variable name="mine">
<xsl:next-match/>
</xsl:variable>
<xsl:if test="empty($mine/*) or true()">
<xsl:message expand-text="true">{ local-name() }</xsl:message>

</xsl:if>
<xsl:sequence select="$mine"/>
</xsl:template>-->

<xsl:template name="conditional-lf">
<xsl:variable name="predecessor"
Expand Down
Loading