Skip to content

Commit

Permalink
Initial cut at XSLT to produce XML->supermodel converter XSLT see usn…
Browse files Browse the repository at this point in the history
…istgov#51; also more worked examples / problem cases
  • Loading branch information
wendellpiez committed Jun 11, 2020
1 parent 94c7c0d commit 74a7d6d
Show file tree
Hide file tree
Showing 14 changed files with 373 additions and 55 deletions.
66 changes: 66 additions & 0 deletions support/lib/metaschema-supermodel.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://csrc.nist.gov/ns/oscal/metaschema/1.0" xmlns:metaschema="http://csrc.nist.gov/ns/oscal/metaschema/1.0">
<xs:element name="map">
<xs:complexType>
<xs:sequence>
<xs:element ref="metaschema:assembly"/>
</xs:sequence>
<xs:attribute name="namespace" use="required" type="xs:anyURI"/>
<xs:attribute name="prefix" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
<xs:element name="assembly">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="metaschema:assembly"/>
<xs:element ref="metaschema:field"/>
<xs:element ref="metaschema:flag"/>
<xs:element ref="metaschema:group"/>
</xs:choice>
<xs:attribute name="gi" use="required" type="xs:NCName"/>
<xs:attribute name="group-xml" type="xs:NCName"/>
<xs:attribute name="json-key-flag" type="xs:NCName"/>
<xs:attribute name="key" type="xs:NCName"/>
<xs:attribute name="scope" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
<xs:element name="group">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" ref="metaschema:assembly"/>
<xs:element minOccurs="0" ref="metaschema:field"/>
</xs:sequence>
<xs:attribute name="gi" type="xs:NCName"/>
<xs:attribute name="json-key-flag" type="xs:NCName"/>
<xs:attribute name="key" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
<xs:element name="flag">
<xs:complexType>
<xs:attribute name="as-type" use="required" type="xs:NCName"/>
<xs:attribute name="gi" use="required" type="xs:NCName"/>
<xs:attribute name="key" use="required" type="xs:NCName"/>
<xs:attribute name="scope" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
<xs:element name="field">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" ref="metaschema:flag"/>
<xs:element ref="metaschema:value"/>
</xs:sequence>
<xs:attribute name="gi" use="required" type="xs:NCName"/>
<xs:attribute name="group-xml" type="xs:NCName"/>
<xs:attribute name="json-key-flag" type="xs:NCName"/>
<xs:attribute name="key" type="xs:NCName"/>
<xs:attribute name="scope" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
<xs:element name="value">
<xs:complexType mixed="true">
<xs:attribute name="as-type" use="required" type="xs:NCName"/>
<xs:attribute name="key" type="xs:NCName"/>
<xs:attribute name="key-flag" type="xs:NCName"/>
</xs:complexType>
</xs:element>
</xs:schema>
20 changes: 8 additions & 12 deletions test-suite/broken/allowed-values-confusion-metaschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,14 @@
<enum value="Ö">o umlaut</enum>
<enum value="Ü">u umlaut</enum>
</allowed-values>
<!--
This rule overrides not the global definition but a local
(doesn't it?) - implement when we have path resolution support
<allowed-values target=".//subsequence//item" extends="yes">
<!-\- which nodes will this rule apply to? Any? note that subsequence/item is defined locally.
If this rule applies, what are the respective sets for subsequence/item[@type='color']-\->
<enum value="pink">a umlaut</enum>
<enum value="orange">o umlaut</enum>
<enum value="purple">u umlaut</enum>
</allowed-values>-->

<allowed-values target=".//subsequence//item" extends="yes">
<!-- which 'allowed-values' will this extend? Any? note that subsequence/item is defined locally.
If this rule applies, what are the respective sets for subsequence/item[@type='color']-->
<enum value="pink">pink</enum>
<enum value="orange">orange</enum>
<enum value="purple">purple</enum>
</allowed-values>
</constraint>
</define-assembly>

Expand Down Expand Up @@ -112,7 +109,6 @@
</model>
</define-assembly>


<define-flag name="type">
<formal-name>Item type</formal-name>
<description>Characterizes the type of item</description>
Expand Down
19 changes: 19 additions & 0 deletions test-suite/broken/allowed-values-confusion-metaschema_METATRON.sch
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@
<ns prefix="m" uri="http://csrc.nist.gov/ns/oscal/metaschema/1.0"/>
<ns prefix="anthology" uri="http://csrc.nist.gov/metaschema/ns/test"/>
<let name="silence-warnings" value="true()"/>
<!-- INDEX DEFINITIONS AS KEY DECLARATIONS -->
<xsl:key name="item-uniqueness" match="anthology:item" use="@id"/>
<!-- RULES -->
<pattern>
<rule context="anthology:item">
<!-- when @type='hex', should match regex '[\dabcdef]+'-->
<assert test="not(@type='hex') or matches(., '^[\dabcdef]+$')">Where @type='hex', <name/> is expected to match regular expression '^[\dabcdef]+$'
</assert>
</rule>
<rule context="anthology:sequence//anthology:item">
<!-- when exists(self::anthology:item[@type='number']), allowed-values on .//anthology:item[@type='number']: 1, 2, 3-->
<assert test="not(exists(self::anthology:item[@type='number'])) or ($silence-warnings or . = ( '1', '2', '3' ))"
Expand All @@ -19,6 +27,11 @@
<assert test="not(exists(self::anthology:item[@type='german'])) or (. = ( 'Ä', 'Ö', 'Ü' ))">Where exists(self::anthology:item[@type='german']), <name/> is expected to be (one of) 'Ä', 'Ö', 'Ü', not '<value-of select="."/>'
</assert>
</rule>
<rule context="anthology:sequence//anthology:subsequence//anthology:item">
<!-- when exists(self::anthology:item/ancestor::anthology:subsequence), allowed-values on .//anthology:subsequence//anthology:item: pink, orange, purple-->
<assert test="not(exists(self::anthology:item/ancestor::anthology:subsequence)) or (. = ( 'pink', 'orange', 'purple' ))">Where exists(self::anthology:item/ancestor::anthology:subsequence), <name/> is expected to be (one of) 'pink', 'orange', 'purple', not '<value-of select="."/>'
</assert>
</rule>
<rule context="anthology:subsequence/anthology:item">
<!--allowed-values on : red, blue, green-->
<assert test="(. = ( 'red', 'blue', 'green' ))"
Expand All @@ -32,5 +45,11 @@
<name/> is expected to be (one of) 'A', 'B', 'C', not '<value-of select="."/>'
[[See id#global-item-allowed-values]]</assert>
</rule>
<rule context="anthology:item">
<!-- is unique-->
<assert test="count(key('item-uniqueness',@id))=1">
<name/> is expected to be unique.
</assert>
</rule>
</pattern>
</schema>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<field as-type="string" gi="item">
<flag as-type="string" key="type" gi="type"/>
<flag as-type="string" key="id" gi="id"/>
<constraint scope="global">
<constraint>
<allowed-values target="." allow-other="no" id="global-item-allowed-values">
<enum value="A">a</enum>
<enum value="B">b</enum>
Expand Down Expand Up @@ -39,7 +39,7 @@
</group>
</assembly>
</group>
<constraint scope="global">
<constraint>
<allowed-values target=".//item[@type='number']" allow-other="yes">
<enum value="1">one</enum>
<enum value="2">two</enum>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<map xmlns="http://csrc.nist.gov/ns/oscal/metaschema/1.0"
namespace="http://csrc.nist.gov/metaschema/ns/everything"
prefix="http://csrc.nist.gov/metaschema/ns/everything">
<assembly scope="global" key="EVERYTHING" gi="EVERYTHING">
<flag as-type="string" scope="global" key="id" gi="id"/>
<field scope="global" key="field-1only" gi="field-1only">
<value as-type="string" key="STRVALUE"/>
</field>
<field scope="global" key="field-base64" gi="field-base64">
<value as-type="base64Binary" key="STRVALUE"/>
</field>
<field scope="global" key="field-named-value" gi="field-named-value">
<flag as-type="string" scope="global" key="id" gi="id"/>
<value as-type="string" key="CUSTOM-VALUE-KEY"/>
</field>
<group key="groupable-fields" gi="groupable-fields">
<field scope="global" gi="field-groupable">
<value as-type="string" key="STRVALUE"/>
</field>
</group>
<group key="wrapped-fields" gi="wrapped-fields">
<field scope="global" gi="field-wrappable">
<value as-type="string" key="STRVALUE"/>
</field>
</group>
<group key="keyed-fields" gi="keyed-fields" json-key-flag="id">
<field scope="global" gi="field-by-key" json-key-flag="id">
<flag as-type="string" scope="global" key="id" gi="id"/>
<value as-type="string" key="STRVALUE"/>
</field>
</group>
<group key="dynamic-value-key-fields" gi="dynamic-value-key-fields">
<field scope="global" gi="field-dynamic-value-key">
<flag as-type="string" scope="global" key="id" gi="id"/>
<value as-type="string" key-flag="id"/>
</field>
</group>
<field scope="global" key="wrapped-prose" gi="wrapped-prose">
<value as-type="markup-multiline" key="PROSE"/>
</field>
<field scope="global" key="loose-prose">
<value as-type="markup-multiline" key="PROSE"/>
</field>
<assembly scope="global" key="assembly-1only" gi="assembly-1only">
<field scope="global" key="field-1only" gi="field-1only">
<value as-type="string" key="STRVALUE"/>
</field>
<assembly scope="global" key="assembly-1only" gi="assembly-1only"/>
</assembly>
<group key="groupable-assemblies" gi="groupable-assemblies">
<assembly scope="global" gi="assembly-groupable">
<group key="groupable-fields" gi="groupable-fields">
<field scope="global" gi="field-groupable">
<value as-type="string" key="STRVALUE"/>
</field>
</group>
<group key="groupable-assemblies" gi="groupable-assemblies">
<assembly scope="global" gi="assembly-groupable"/>
</group>
</assembly>
</group>
<group key="wrapped-assemblies" gi="wrapped-assemblies">
<assembly scope="global" gi="assembly-wrappable">
<group key="wrapped-fields" gi="wrapped-fields">
<field scope="global" gi="field-wrappable">
<value as-type="string" key="STRVALUE"/>
</field>
</group>
<group key="wrapped-assemblies" gi="wrapped-assemblies">
<assembly scope="global" gi="assembly-wrappable"/>
</group>
</assembly>
</group>
<group key="keyed-assemblies" gi="keyed-assemblies" json-key-flag="id">
<assembly scope="global" gi="assembly-by-key" json-key-flag="id">
<flag as-type="string" scope="global" key="id" gi="id"/>
<group key="keyed-fields" gi="keyed-fields" json-key-flag="id">
<field scope="global" gi="field-by-key" json-key-flag="id">
<flag as-type="string" scope="global" key="id" gi="id"/>
<value as-type="string" key="STRVALUE"/>
</field>
</group>
<group key="keyed-assemblies" gi="keyed-assemblies" json-key-flag="id">
<assembly scope="global" gi="assembly-by-key" json-key-flag="id"/>
</group>
</assembly>
</group>
<group key="everything-recursive" gi="everything-recursive">
<assembly scope="global" gi="EVERYTHING"/>
</group>
</assembly>
</map>
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<EVERYTHING xmlns="http://csrc.nist.gov/metaschema/ns/everything"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://csrc.nist.gov/metaschema/ns/everything file:/C:/Users/wap1/Documents/usnistgov/metaschema/test-suite/worked-examples/everything-metaschema/models_metaschema_XML-SCHEMA.xsd">

<field-1only>FIELD-1-ONLY</field-1only>
<field-base64>1234abcd</field-base64>
<field-named-value id="fnv1">FIELD-NAMED-VALUE</field-named-value>
<field-groupable>field-groupable 1</field-groupable>
<field-groupable>field-groupable 2</field-groupable>
<field-groupable>field-groupable 3</field-groupable>
<wrapped-fields>
<field-wrappable>field-wrappable 1</field-wrappable>
<field-wrappable>field-wrappable 2</field-wrappable>
<field-wrappable>field-wrappable 3</field-wrappable>
</wrapped-fields>
<field-by-key id="fbk1">field-by-key 1</field-by-key>
<field-by-key id="fbk2">field-by-key 2</field-by-key>
<field-by-key id="fbk3">field-by-key 3</field-by-key>
<field-dynamic-value-key id="fdvk1">field-dynamic-value-key 1</field-dynamic-value-key>
<field-dynamic-value-key id="fdvk2">field-dynamic-value-key 2</field-dynamic-value-key>
<field-dynamic-value-key id="fdvk3">field-dynamic-value-key 3</field-dynamic-value-key>

<wrapped-prose>
<h1>Wrapped up prose</h1>
<p>This is prose. All wrapped up.</p>
</wrapped-prose>
<h1>Unwrapped prose</h1>
<p>Here we have unwrapped prose....</p>
<assembly-1only>
<field-1only>ASSEMBLY-1-ONLY / FIELD-1-ONLY</field-1only>
</assembly-1only>
<assembly-groupable>
<field-groupable>assembly-groupable 1 / field-groupable 1</field-groupable>
<field-groupable>assembly-groupable 1 / field-groupable 2</field-groupable>
<field-groupable>assembly-groupable 1 / field-groupable 3</field-groupable>
</assembly-groupable>
<assembly-groupable>
<field-groupable>assembly-groupable 2 / field-groupable 1</field-groupable>
<field-groupable>assembly-groupable 2 / field-groupable 2</field-groupable>
<field-groupable>assembly-groupable 2 / field-groupable 3</field-groupable>
</assembly-groupable>
<assembly-groupable>
<field-groupable>assembly-groupable 3 / field-groupable 1</field-groupable>
<field-groupable>assembly-groupable 3 / field-groupable 2</field-groupable>
<field-groupable>assembly-groupable 3 / field-groupable 3</field-groupable>
</assembly-groupable>
<wrapped-assemblies>
<assembly-wrappable>
<wrapped-fields>
<field-wrappable>assembly-wrappable 1 / field-wrappable 1</field-wrappable>
<field-wrappable>assembly-wrappable 1 / field-wrappable 2</field-wrappable>
<field-wrappable>assembly-wrappable 1 / field-wrappable 3</field-wrappable>
</wrapped-fields>
</assembly-wrappable>
<assembly-wrappable>
<wrapped-fields>
<field-wrappable>assembly-wrappable 2 / field-wrappable 1</field-wrappable>
<field-wrappable>assembly-wrappable 2 / field-wrappable 2</field-wrappable>
<field-wrappable>assembly-wrappable 2 / field-wrappable 3</field-wrappable>
</wrapped-fields>
</assembly-wrappable>
<assembly-wrappable>
<wrapped-fields>
<field-wrappable>assembly-wrappable 3 / field-wrappable 1</field-wrappable>
<field-wrappable>assembly-wrappable 3 / field-wrappable 2</field-wrappable>
<field-wrappable>assembly-wrappable 3 / field-wrappable 3</field-wrappable>
</wrapped-fields>
</assembly-wrappable>
</wrapped-assemblies>
<assembly-by-key id="abk1">
<field-by-key id="abk1.fbk1">assembly-by-key 1 / field-by-key 1</field-by-key>
<field-by-key id="abk1.fbk2">assembly-by-key 1 / field-by-key 2</field-by-key>
<field-by-key id="abk1.fbk3">assembly-by-key 1 / field-by-key 3</field-by-key>
</assembly-by-key>
<assembly-by-key id="abk2">
<field-by-key id="abk2.fbk1">assembly-by-key 1 / field-by-key 1</field-by-key>
<field-by-key id="abk2.fbk2">assembly-by-key 1 / field-by-key 2</field-by-key>
<field-by-key id="abk2.fbk3">assembly-by-key 1 / field-by-key 3</field-by-key>
</assembly-by-key>
<assembly-by-key id="abk3">
<field-by-key id="abk3.fbk1">assembly-by-key 1 / field-by-key 1</field-by-key>
<field-by-key id="abk3.fbk2">assembly-by-key 1 / field-by-key 2</field-by-key>
<field-by-key id="abk3.fbk3">assembly-by-key 1 / field-by-key 3</field-by-key>
</assembly-by-key>
<everything>
<field-1only>nested FIELD-1-ONLY</field-1only>
</everything>
</EVERYTHING>
Loading

0 comments on commit 74a7d6d

Please sign in to comment.