Skip to content

Commit

Permalink
Further implementation, worked example
Browse files Browse the repository at this point in the history
  • Loading branch information
wendellpiez committed Jun 11, 2020
1 parent b92626b commit 0a214b8
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 29 deletions.
12 changes: 6 additions & 6 deletions test-suite/worked-example/everything_metaschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,13 @@ Under 'widget'
</model>
<constraint>
<require when="@type='couplet'">
<has-cardinality target="line" max-occurs="2" min-occurs="2"/>
<has-cardinality target="everything:line" max-occurs="2" min-occurs="2"/>
</require>
<require when="@type='tercet'">
<has-cardinality target="line" max-occurs="3" min-occurs="3"/>
<has-cardinality target="everything:line" max-occurs="3" min-occurs="3"/>
</require>
<require when="@type='quatrain'">
<has-cardinality target="line" max-occurs="4" min-occurs="4"/>
<has-cardinality target="everything:line" max-occurs="4" min-occurs="4"/>
</require>
</constraint>
</define-assembly>
Expand All @@ -237,17 +237,17 @@ Under 'widget'
</define-flag>
<constraint>
<require when="@type='type'">
<allowed-values target="value()">
<allowed-values target="data()">
<enum value="start">start</enum>
<enum value="end">end</enum>
</allowed-values>
</require>
<require when="@type='date'">
<matches datatype="date" target="value()"/>
<matches datatype="date" target="data()"/>
</require>
<require when="@type='roleref'">
<index-has-key target="." name="role-index">
<key-field target="value()"/>
<key-field target="data()"/>
</index-has-key>
</require>
</constraint>
Expand Down
2 changes: 1 addition & 1 deletion test-suite/worked-example/kitchen-drawer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<poem>
<stanza type="quatrain">
<line>'Twas brilling, and the slithy toves</line>
<line>Did gyre and gimble in the wabe:</line>
<!--<line>Did gyre and gimble in the wabe:</line>-->
<line>All mimsy were the borogoves,</line>
<line>And the mome raths outgrabe.</line>
</stanza>
Expand Down
99 changes: 77 additions & 22 deletions toolchains/xslt-proto-v04/schema_gen/make-metaschema-metatron.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,19 @@

<xsl:template match="text()"/>

<xsl:template match="constraint//matches | constraint//allowed-values | constraint//has-cardinality">
<xsl:template match="constraint">
<xsl:variable name="context">
<xsl:apply-templates select="." mode="rule-context"/>
</xsl:variable>
<rule context="{ $context }">
<xsl:apply-templates mode="assertion" select="."/>
</rule>
<xsl:where-populated>
<rule context="{ $context }">
<xsl:apply-templates/>
</rule>
</xsl:where-populated>
</xsl:template>

<xsl:template match="matches |allowed-values | has-cardinality">
<xsl:apply-templates mode="assertion" select="."/>
</xsl:template>

<xsl:template match="has-cardinality/@min-occurs" mode="assertion">
Expand All @@ -82,7 +88,6 @@
<assert test="{ $exception }count({ $target }) le { (. cast as xs:integer) } )">
<xsl:value-of select="m:condition(parent::has-cardinality) ! ('Where ' || . || ', ')"/><name/>/ <xsl:value-of
select="$target"/> is expected to occur <xsl:value-of select="m:times(. cast as xs:integer )"/> at most</assert>

</xsl:template>

<xsl:template match="has-cardinality/@max-occurs" mode="assertion">
Expand All @@ -92,9 +97,7 @@
<xsl:if test="exists($condition)" expand-text="true">not({ $condition }) or </xsl:if>
</xsl:variable>
<assert test="{ $exception }count({ $target }) ge { (. cast as xs:integer) } )">
<xsl:value-of select="$condition ! ('Where ' || . || ', ')"/><name/>/ <xsl:value-of
select="$target"/> is expected to occur at least <xsl:value-of select="m:times(. cast as xs:integer)"/></assert>

<xsl:value-of select="$condition ! ('Where ' || . || ', ')"/><name/>/ <xsl:value-of select="$target"/> is expected to occur at least <xsl:value-of select="m:times(. cast as xs:integer)"/></assert>
</xsl:template>

<xsl:template priority="3" match="has-cardinality[@min-occurs = @max-occurs]" mode="assertion">
Expand All @@ -103,14 +106,15 @@
<xsl:variable name="exception">
<xsl:if test="exists($condition)" expand-text="true">not({ $condition }) or </xsl:if>
</xsl:variable>
<assert test="{ $exception }count({ $target }) eq { (@min-occurs cast as xs:integer) } )">
<xsl:value-of select="$condition ! ('Where ' || . || ', ')"/><name/>/ <xsl:value-of
select="$target"/> is expected to occur exactly <xsl:value-of select="m:times(@min-occurs cast as xs:integer)"/></assert>

<xsl:variable name="test" expand-text="true">count({ $target }) eq { (@min-occurs cast as xs:integer) }</xsl:variable>
<xsl:apply-templates select="." mode="echo.if"/>
<assert test="{ $exception }{ $test }">
<xsl:value-of select="$condition ! ('Where ' || . || ', ')"/><name/>/ <xsl:value-of select="$target"/> is expected to occur exactly <xsl:value-of select="m:times(@min-occurs cast as xs:integer)"/></assert>
</xsl:template>


<xsl:template priority="2" match="has-cardinality" mode="assertion">
<xsl:template priority="2" match="has-cardinality" mode="assertion">
<xsl:apply-templates select="." mode="echo.if"/>
<xsl:apply-templates mode="#current" select="@min-occurs, @max-occurs"/>
</xsl:template>

Expand All @@ -121,13 +125,13 @@
<xsl:variable name="exception">
<xsl:if test="exists(m:condition(parent::matches))" expand-text="true">not({ m:condition(parent::matches) }) or </xsl:if>
</xsl:variable>
<assert test="{ $exception }matches({ $target }, '{ . }')">
<xsl:value-of select="m:condition(parent::matches) ! ('Where ' || . || ', ')"/><name/>/ <xsl:value-of
select="$target"/> '<value-of select="{ $target }"/>' is expected to match
regular expression '<xsl:value-of select="."/>'</assert>
<xsl:variable name="test" expand-text="true">matches( { $target }, '{ . }')</xsl:variable>
<assert test="{ $exception }{ $test }">
<xsl:value-of select="m:condition(parent::matches) ! ('Where ' || . || ', ')"/><name/>/<xsl:value-of select="$target"/> '<value-of select="{ $target }"/>' is expected to match regular expression '<xsl:value-of select="."/>'</assert>
</xsl:template>

<xsl:template priority="2" match="matches" mode="assertion">
<xsl:apply-templates select="." mode="echo.if"/>
<xsl:apply-templates mode="#current" select="@regex | @datatype"/>
</xsl:template>

Expand All @@ -136,12 +140,57 @@
<xsl:if test="exists(m:condition(.))" expand-text="true">not({ m:condition(.) }) or </xsl:if>
</xsl:param>
<xsl:variable name="value-sequence" select="(enum/@value ! ('''' || . || '''')) => string-join(', ')"/>
<assert test="{ $exception } { m:target(.) } = ( { $value-sequence } )">
<xsl:value-of select="m:condition(.) ! ('Where ' || . || ', ')"/><name/>/
<xsl:value-of select="m:target(.)"/> '<value-of select="{ m:target(.) }"/>' is expected
to be one of <xsl:value-of select="$value-sequence"/></assert>
<xsl:variable name="test">
<xsl:text expand-text="true">{ m:target(.) } = ( { $value-sequence }</xsl:text>
</xsl:variable>
<xsl:apply-templates select="." mode="echo.if"/>
<assert test="{ $exception }{ $test } )">
<xsl:value-of select="m:condition(.) ! ('Where ' || . || ', ')"/><name/>/<xsl:value-of select="m:target(.)"/> '<value-of select="{ m:target(.) }"/>' is expected to be one of <xsl:value-of select="$value-sequence"/></assert>
</xsl:template>

<xsl:param name="noisy" as="xs:string">yes</xsl:param>
<xsl:variable name="echo.source" select="$noisy='yes'"/>

<xsl:template match="*" mode="echo.if">
<xsl:if test="$echo.source">
<xsl:text>&#xA;&#xA;</xsl:text>
<xsl:comment>
<xsl:value-of select="serialize(.,$serializer-settings)"/>
</xsl:comment>
</xsl:if>
</xsl:template>

<xsl:template match="allowed-values" mode="echo.if">
<xsl:if test="$echo.source">
<xsl:text expand-text="true">&#xA; { ancestor::*[exists(ancestor-or-self::constraint)] ! ' ' } </xsl:text>
<xsl:comment expand-text="true">{ m:condition(.) ! (' when ' || . || ', ') }allowed-values on { m:target(.) }: { string-join(enum/@value,', ' ) }</xsl:comment>
</xsl:if>
</xsl:template>

<xsl:template match="matches[@regex]" mode="echo.if">
<xsl:if test="$echo.source">
<xsl:text expand-text="true">&#xA; { ancestor::*[exists(ancestor-or-self::constraint)] ! ' ' } </xsl:text>
<xsl:comment expand-text="true">{ m:condition(.) ! (' when ' || . || ', ') }{ m:target(.) } matches regex '{ @regex }'</xsl:comment>
</xsl:if>
</xsl:template>

<xsl:template match="has-cardinality" mode="echo.if">
<xsl:if test="$echo.source">
<xsl:text expand-text="true">&#xA; { ancestor::*[exists(ancestor-or-self::constraint)] ! ' ' } </xsl:text>
<xsl:comment expand-text="true">{ m:condition(.) ! (' when ' || . || ', ') }{ m:target(.) } has cardinality: { @min-occurs ! ( ' at least ' || (.,'0')[1]) } { @max-occurs ! ( ' at most ' || (.,'unbounded')[1]) }</xsl:comment>
</xsl:if>
</xsl:template>

<xsl:variable name="serializer-settings" as="element()">
<output:serialization-parameters
xmlns="http://csrc.nist.gov/ns/oscal/metaschema/1.0"
xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
<output:method value="xml"/>
<output:version value="1.0"/>
<output:indent value="yes"/>
</output:serialization-parameters>
</xsl:variable>

<!-- Not yet handling flags, definition references, root or use-name ... -->
<xsl:template match="*[@name]" mode="rule-context" as="xs:string">
<xsl:value-of select="ancestor-or-self::*/(@name|@ref)/m:prefixed(.)" separator="/"/>
Expand Down Expand Up @@ -191,6 +240,12 @@
<xsl:apply-templates select="ancestor-or-self::constraint/parent::*" mode="#current"/>
</xsl:template>

<xsl:function name="m:rule-context" as="xs:string" cache="yes">
<xsl:param name="whose"/>
<!-- Insulate XPath here -->
<xsl:apply-templates select="$whose" mode="rule-context"/>
</xsl:function>

<xsl:function name="m:prefixed" as="xs:string" cache="yes">
<xsl:param name="whose"/>
<!-- Insulate XPath here -->
Expand All @@ -200,6 +255,7 @@
<xsl:function name="m:target" as="xs:string" cache="yes">
<xsl:param name="whose" as="element()"/>
<!-- Insulate XPath here -->
<!-- no-namespace paths have to be expanded to ns? -->
<xsl:value-of select="($whose/@target,'.')[1]"/>
</xsl:function>

Expand All @@ -213,7 +269,6 @@
</xsl:function>

<xsl:function name="m:times" as="xs:string?" cache="yes">
<!-- Insulate XPath here -->
<xsl:param name="count" as="xs:integer"/>
<xsl:text expand-text="true">{ if ($count eq 1) then 'once' else ($count || ' times' ) }</xsl:text>
</xsl:function>
Expand Down

0 comments on commit 0a214b8

Please sign in to comment.