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

First crack at addressing #2173 in a serious way. #2442

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from
Draft
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
7 changes: 5 additions & 2 deletions P5/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,16 @@ valid: jing_version=$(wordlist 1,3,$(shell jing))
valid: check.stamp p5.xml
@echo BUILD: Check validity with rnv \(https://github.com/dtolpin/RNV\) if we have it
-command -v rnv && rnv -v p5odds.rnc p5.xml
@echo BUILD: Check validity with special-purpose XSL code, looking for bad links etc
@echo BUILD: Check validity with special-purpose XSL code, looking for bad links etc — START
${ANT} -lib Utilities/lib/${SAXONJAR} -f antbuilder.xml -DXSL=${XSL} validators
@echo BUILD: Check validity with special-purpose XSL code, looking for bad links etc — END
@grep -v "ARNING: use of deprecated element" ValidatorLog.xml
(grep -q "<ERROR>" ValidatorLog.xml;if [ $$? -ne 1 ] ; then echo "Oh dear me. ERROR found";diff ValidatorLog.xml expected-results/ValidatorLog.xml;false; fi)
@echo BUILD: Test existence of graphic files \(using script generated in "validators step 07", above\)
sh graphics.sh
@echo BUILD: Check validity with nvdl, first examples with feasible validity, and then the valid ones
@echo BUILD: Check validity with nvdl, examples with feasible validity
./run-onvdl p5.nvdl p5.xml
@echo BUILD: Check validity with nvdl, valid examples
./run-onvdl p5valid.nvdl v.xml

test: schemas.stamp
Expand Down
6 changes: 4 additions & 2 deletions P5/Source/Guidelines/en/TD-DocumentationElements.xml
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,8 @@ to mark any technical term, thus:
of the attributes of the TEI element <gi>relation</gi> were expressed informally as follows: <q>only
one of the attributes <att>active</att> and <att>mutual</att> may be supplied; the attribute
<att>passive</att> may be supplied only if the attribute <att>active</att> is supplied.</q>. In the current version of the
Guidelines, constraint specifications expressed as Schematron rules have been added, as follows:
Guidelines, constraint specifications expressed as Schematron rules have been added to the specification of the
<gi>relation</gi> element, as follows:
<egXML xmlns="http://www.tei-c.org/ns/Examples">
<constraintSpec ident="reforkeyorname" scheme="schematron">
<constraint>
Expand Down Expand Up @@ -875,7 +876,8 @@ to mark any technical term, thus:
</constraintSpec>
</egXML>
Schematron rules are also useful where an application needs to enforce rules on attribute values, as
in the following examples which check that various types of <gi>title</gi> are provided:
in the following examples which might be written into the
specification of <gi>teiHeader</gi> to check that various types of <gi>title</gi> are provided:
<egXML xmlns="http://www.tei-c.org/ns/Examples">
<constraintSpec ident="introtitle" scheme="schematron">
<constraint>
Expand Down
148 changes: 148 additions & 0 deletions P5/Source/Specs/constraintSpec.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,148 @@ $Id$
</sch:rule>
</constraint>
</constraintSpec>
<constraintSpec ident="context_for_constraint" scheme="schematron">
<desc xml:lang="en" versionDate="2023-06-14">Any
<gi>constraintSpec</gi> that <emph>not</emph> a child of
<gi>schemaSpec</gi>, or a descendant of <gi>elementSpec</gi>, or
inside a <gi>specGrp</gi> which is referred to from a child of an
<gi>elementSpec</gi> should have a <att>context</att>
attribute.</desc>
<constraint>
<!-- Fire on <constraintSpec scheme=schematron> that has no descendant @context -->
<!-- Note that the “not( ancestor::teix:egXML )” predicate is
not needed for normal TEI procerssing. It is only needed
for the P5 build process itself, during which Schematron
rules are run with the "tei:" prefix is bound to the
Examples namespace, such that this rule would be fired
inside <egXML>s when we don’t want that, because quite a
few examples are contextless. -->
<sch:rule context="tei:constraintSpec[ not( ancestor::teix:egXML ) ][ @scheme eq 'schematron' and not( .//@context ) ]">
<!--
Since <specGrp> can self-nest, it is possible we have more
than 1 ancestor <specGrp>. We can keep track of them by
@xml:id, because although @xml:id is not a required
attribute on a <specGrp>, if there is no @xml:id it
*cannot* be referenced from anywhere, let alone somewhere
the Stylesheets can't figure out a context. So here assign
all of the IDs of all of my ancestor <specGrp>s to a
variable.

It is probably not necesssary to normalize the whitespace
around the @xml:id value, but use of normalize-space()
makes it clear that we are dealing with strings here, not
nodes.

It is probably better in the general XPath 3+ case to use
the simple mapping operator (‘!’) rather than the path
operator (‘/’) before the normalize-space() step, but my
current commandline Schematron processor (probatron)
chokes on it. Maybe after I have switched to the
poorly-named but well-executed SchXslt … —Syd
-->
<sch:let name="mySpecGrps" value="ancestor::tei:specGrp/@xml:id/normalize-space()"/>

<!--
Collect a sequence of the distinct targets of every
<specGrpRef> in the current ODD document. Thus we end up
with something like "#one subCust.odd#two #three".

Note that there is no need to worry about multiple values
in a specGrpRef/@target value, as the attribute is defined
as having one and only one value (and is required).
-->
<sch:let name="allSpecGrpRefs"
value="distinct-values( //tei:specGrpRef/@target/normalize-space() )"/>

<!--
Prune the list down to those that are just shorthand
pointer fragment identifiers, and then strip off their
leading ‘#’ characters so the result is a sequence of
unique IDs.

Thus we end up with something like "one three". Yes, we
are dropping references to external files that might
somehow refer back to our <specGrp>. Such is life, we can
only do so much. (And that is, at least in part, why we
use role=warn.)
-->
<sch:let name="localSpecGrpRefs"
value="for $r in $allSpecGrpRefs return
if ( starts-with( $r,'#') )
then substring( $r, 2 )
else '' "/>

<!--
If this <constraintSpec> (which remember, does not have a
@context or we would not be in this <sch:rule>) is *not* a
descdendant of an <elementSpec>, a <specGrp>, or the child
of a <schemaSpec>, then there is no way the (current)
Stylesheets can generate a context.
-->
<sch:assert test=" ancestor::tei:elementSpec
| parent::tei:schemaSpec
| ancestor::tei:specGrp" role="warn">
this constraintSpec <sch:value-of select="if (@ident) then
concat('(&quot;', @ident,'&quot;)') else ''"/> does not have
an explicit context specified (via a @context attribte), but
software can probably not generate an appropriate context.
</sch:assert>

<!-- Now the hard part: check those in <specGrp>(s) -->
<sch:report role="warn"
test="(: I am inside a specGrp, :)
ancestor::tei:specGrp
(: and I am not inside an elementSpec, :)
and not( ancestor::tei:elementSpec )
(: and there are one or more references to one or more of my
scpecGrp ancestors (of which there is probably only one) :)
and $mySpecGrps = $localSpecGrpRefs
and
(
(: each of the specGrps I am in … :)
every $id in $mySpecGrps satisfies
(
(: … is either not referred to by a local specGrpRef … :)
not( $localSpecGrpRefs = $id )
or
(
(: … OR it is not the case that every specGrpRef that
does point to it … :)
not(
every $tsgr in (: tsgr = this specification group reference :)
//tei:specGrpRef[
substring( normalize-space( @target ), 2 )
=
tokenize( $mySpecGrps )
]
satisfies
(: … is a descendant of elementSpec or
is a child of schemaSpec. :)
$tsgr/ancestor::tei:elementSpec
| $tsgr/parent::tei:schemaSpec
)
(: Which is to say none of the &lt;specGrpRef>s that
point to it are going to get an auto-generated
context. Note that one might argue that we don’t
really have to test for anyplace other than child
of &lt;schemaSpec> because the only places in the
tagdocs module in which a &lt;specGrpRef> is
allowed is as a child of &lt;specGrp> or
&lt;schemaSpec>. However, since (at the moment)
it can also be a child of &lt;p>, &lt;emph>,
or &lt;metaMark>, it is probably appropriate to
check. :)
)
)
)">
this constraintSpec <sch:value-of select="
if (@ident)
then concat('(&quot;', @ident,'&quot;)')
else ''"/> has no @context, but is in a specGrp that has at
least 1 reference to it that is not contextulizable.</sch:report>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: contextulizable (missing "a") and I would spell out 1 to "one"

</sch:rule>
</constraint>
</constraintSpec>
<attList>
<attDef ident="scheme" usage="req">
<desc versionDate="2009-06-10" xml:lang="en">supplies the name of the language in which the constraints
Expand Down Expand Up @@ -131,6 +273,12 @@ $Id$
</egXML>
</exemplum>
<exemplum xml:lang="en">
<p>This example demonstrates a constraint that may be added to the
specification of <gi>figure</gi> to unsure that a textual
explanation is present. It checks for the existence of one of the
elements in which such an explanation is expected — it does not
actually check that there is textual content in that element, nor
that the textual explanation makes sense.</p>
<egXML xmlns="http://www.tei-c.org/ns/Examples">
<constraintSpec ident="demo-c2" scheme="schematron">
<desc>Implement an accessibility rule which says that pictures
Expand Down
12 changes: 12 additions & 0 deletions P5/Utilities/validator.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@

<xsl:template match="/">
<Messages>
<xsl:text>&#x0A;</xsl:text>
<xsl:comment> *** results from specific hard-coded checks: *** </xsl:comment>
<xsl:text>&#x0A;</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#x0A;</xsl:text>
<xsl:comment> *** results from check uniquness of @xml:id values: *** </xsl:comment>
<xsl:text>&#x0A;</xsl:text>
<xsl:for-each select="distinct-values( //*[@xml:id]/@xml:id )">
<xsl:variable name="thisID" select="."/>
<xsl:for-each select="$root">
Expand All @@ -36,8 +42,14 @@
</xsl:if>
</xsl:for-each>
</xsl:for-each>
<xsl:text>&#x0A;</xsl:text>
<xsl:comment> *** results from Schematron, normal part of Guidelines, i.e. p5odds.isosch.xsl *** </xsl:comment>
<xsl:text>&#x0A;</xsl:text>
<xsl:apply-templates select="doc('../Schematron1.xml')//svrl:failed-assert"/>
<xsl:apply-templates select="doc('../Schematron1.xml')//svrl:successful-report"/>
<xsl:text>&#x0A;</xsl:text>
<xsl:comment> *** results from Schematron, examples in Guidelines marked as valid, i.e. p5examples.isosch.xsl *** </xsl:comment>
<xsl:text>&#x0A;</xsl:text>
<xsl:apply-templates select="doc('../Schematron2.xml')//svrl:failed-assert"/>
<xsl:apply-templates select="doc('../Schematron2.xml')//svrl:successful-report"/>
</Messages>
Expand Down
11 changes: 8 additions & 3 deletions P5/antbuilder.xml
Original file line number Diff line number Diff line change
Expand Up @@ -246,27 +246,32 @@
</target>

<target name="validators">
<echo>Running target "validators" ...</echo>
<echo>... step 01: p5.xml → v.xml, using Utilities/extractegXML.xsl</echo>
<xslt processor="trax" force="yes" style="Utilities/extractegXML.xsl" in="p5.xml" out="v.xml">
<factory name="net.sf.saxon.TransformerFactoryImpl"/>
</xslt>
<echo>Run Schematron script (normal part of Guidelines)</echo>
<echo>... step 02: p5.xml → Schematron1.xml using p5odds.isosch.xsl (normal part of Guidelines)</echo>
<xslt processor="trax" force="yes" style="p5odds.isosch.xsl" in="p5.xml" out="Schematron1.xml">
<factory name="net.sf.saxon.TransformerFactoryImpl"/>
</xslt>
<echo>Run Schematron script (Examples in Guidelines marked as valid)</echo>
<echo>... step 03: p5.xml → Schematron2.xml using p5examples.isosch.xsl (examples in Guidelines marked as)</echo>
<xslt processor="trax" force="yes" style="p5examples.isosch.xsl" in="p5.xml" out="Schematron2.xml">
<factory name="net.sf.saxon.TransformerFactoryImpl"/>
</xslt>
<echo>Run ad hoc XSLT validators</echo>
<echo>... step 04: p5.xml → Utilities/pointerattributes.xsl using Utilities/prevalidator.xsl</echo>
<xslt processor="trax" force="yes" style="Utilities/prevalidator.xsl" in="p5.xml" out="Utilities/pointerattributes.xsl">
<factory name="net.sf.saxon.TransformerFactoryImpl"/>
</xslt>
<echo>... step 05: p5.xml → ValidatorLog.xml using Utilities/validator.xsl</echo>
<xslt processor="trax" force="yes" style="Utilities/validator.xsl" in="p5.xml" out="ValidatorLog.xml">
<factory name="net.sf.saxon.TransformerFactoryImpl"/>
</xslt>
<echo>... step 06: p5.xml → STDOUT using Utilities/listspecwithnoexample.xsl</echo>
<xslt processor="trax" force="yes" style="Utilities/listspecwithnoexample.xsl" in="p5.xml" out="/dev/stdout">
<factory name="net.sf.saxon.TransformerFactoryImpl"/>
</xslt>
<echo>... step 07: p5.xml → graphics.sh using Utilities/listgraphics.xsl</echo>
<xslt processor="trax" force="yes" style="Utilities/listgraphics.xsl" in="p5.xml" out="graphics.sh">
<factory name="net.sf.saxon.TransformerFactoryImpl"/>
</xslt>
Expand Down
Loading