Schematron Implementation for DDMS 5.0

This document is an attempt to map some of the more complex DDMS conditions to a Schematron file. Where an XML Schema can be used to validate correctness and syntax, a Schematron file can more easily address rules related to content and dependencies between various elements and attributes. Please note that DDMSence currently validates these rules with Java instead of Schematron, for slightly increased performance.

DDMS 5.0 introduced an official Schematron file as part of the specification, DDMS-v5.sch. This file currently validates new country code rules. I submitted a CR in 2013 to incorporate some of the tests below into the official file, but the CR has not yet been reviewed.

Schematron File Template

Schematron rules must be placed in a valid schema template which identifies any XML namespaces that the XML instance might employ.

<?xml version="1.0" encoding="utf-8"?>
<iso:schema   
   xmlns="http://purl.oclc.org/dsdl/schematron"
   xmlns:iso="http://purl.oclc.org/dsdl/schematron">
   
   <iso:title>Test ISO Schematron File for DDMSence (DDMS 5.0)</iso:title>
   <iso:ns prefix='ddms' uri='urn:us:mil:ces:metadata:ddms:5' />
   <iso:ns prefix='gml' uri='http://www.opengis.net/gml/3.2' />
   <iso:ns prefix='ism' uri='urn:us:gov:ic:ism' />
   <iso:ns prefix='ntk' uri='urn:us:gov:ic:ntk' />
   <iso:ns prefix='tspi' uri='http://metadata.ces.mil/mdr/ns/GSIP/tspi/2.0' />
   <iso:ns prefix='virt' uri='urn:us:gov:ic:virt' />
   <iso:ns prefix='xlink' uri='http://www.w3.org/1999/xlink' />

   <!-- Patterns go here. -->
</iso:schema>

If your rules employ any newer XSLT2 functions, a queryBinding attribute is required. Setting this attribute to xslt2 will ensure that the proper Schematron transformation stylesheets are used. The absence of this attribute defaults to "xslt1".

<?xml version="1.0" encoding="utf-8"?>
<iso:schema   
   xmlns="http://purl.oclc.org/dsdl/schematron"
   xmlns:iso="http://purl.oclc.org/dsdl/schematron"
   queryBinding="xslt2">

Dates Constraints

<iso:pattern id="Dates_Constraints">
    <iso:rule context="//ddms:resource//ddms:dates">
       <iso:report test="count(@*) = 0">
          The ddms:dates element does not have any date attributes.
       </iso:report>
    </iso:rule>
</iso:pattern>

Extent Constraints

<iso:pattern id="Extent_Constraints">
    <iso:rule context="//ddms:resource/ddms:format/ddms:extent">
       <iso:assert test="not(@ddms:value) or (@ddms:qualifier and @ddms:value)">
          If a ddms:extent element has a value, it must also have a qualifier.
       </iso:assert>
       <iso:report test="count(@*) = 0">
          The ddms:extent element does not have any attributes.
       </iso:report>
       <iso:report test="not(@ddms:value) and @ddms:qualifier">
          The ddms:extent element has a qualifier but no value.
       </iso:report>
    </iso:rule>
</iso:pattern>

GeographicIdentifier Constraints

<iso:pattern id="GeographicIdentifier_Constraints">
    <iso:rule context="//ddms:resource//ddms:geographicIdentifier">
       <iso:assert test="(ddms:facilityIdentifier and count(*) = 1) or not(ddms:facilityIdentifier)">
          A ddms:facilityIdentifier element cannot be used with any sibling elements.
       </iso:assert>
    </iso:rule>
</iso:pattern>

GeospatialCoverage Constraints

<iso:pattern id="GeospatialCoverage_Constraints">
    <iso:rule context="//ddms:resource/ddms:geospatialCoverage">
       <iso:assert test="(ddms:geographicIdentifier/ddms:facilityIdentifier and count(*) = 1) or not(ddms:geographicIdentifier/ddms:facilityIdentifier)">
          A ddms:geospatialCoverage element which contains a facilityIdentifier-based geographicIdentifier cannot contain any other child elements.
       </iso:assert>
    </iso:rule>
</iso:pattern>

Language Constraints

<iso:pattern id="Language_Constraints">
    <iso:rule context="//ddms:resource/ddms:language">
       <iso:assert test="not(@ddms:value) or (@ddms:qualifier and @ddms:value)">
          If a ddms:language element has a value, it must also have a qualifier.
       </iso:assert>
       <iso:report test="count(@*) = 0">
          A ddms:language element does not have any attributes.
       </iso:report>
       <iso:report test="not(@ddms:value) and @ddms:qualifier">
          A ddms:language element has a qualifier but no value.
       </iso:report>
    </iso:rule>
</iso:pattern>

Point Constraints

DDMSence does not test these conditions yet.

<iso:pattern id="Point_Constraints">
   <iso:rule context="//tspi:Point">
      <iso:assert test="not(gml:pos/@srsName) or (@srsName = gml:pos/@srsName)">
         If a srsName attribute appears on a gml:pos element, it should have the same value as the srsName attribute on the enclosing tspi:Point element.
      </iso:assert>
      <iso:assert test="@srsName or not(@axisLabels)">
         If the srsName attribute on a tspi:Point element is omitted, the axisLabels attribute must be omitted as well. 
      </iso:assert>
      <iso:assert test="@axisLabels or not(@uomLabels)">
         If the axisLabels attribute on a tspi:Point element is omitted, the uomLabels attribute must be omitted as well. 
      </iso:assert>
   </iso:rule>
</iso:pattern>

Polygon Constraints

DDMSence does not test these conditions yet.

<iso:pattern id="Polygon_Constraints">
   <iso:rule context="//tspi:Polygon/gml:exterior/gml:LinearRing">
      <iso:assert test="not(gml:pos/@srsName) or (gml:pos/@srsName = ../../@srsName)">
         If a srsName attribute appears on a gml:pos element, it should have the same value as the srsName attribute on the enclosing tspi:Polygon element.
      </iso:assert>
      <iso:assert test="gml:pos[1] = gml:pos[last()]">
         The first and last gml:pos elements in a tspi:Polygon must be identical, to outline an enclosed shape.
      </iso:assert>
      <iso:assert test="@srsName or not(@axisLabels)">
         If the srsName attribute on a tspi:Polygon element is omitted, the axisLabels attribute must be omitted as well. 
      </iso:assert>
      <iso:assert test="@axisLabels or not(@uomLabels)">
         If the axisLabels attribute on a tspi:Polygon element is omitted, the uomLabels attribute must be omitted as well. 
      </iso:assert>
   </iso:rule>
</iso:pattern>

Position Constraints

DDMSence does not test these conditions yet.

<!-- This rule employs the XPath 2.0 function, tokenize(). Make sure you have a queryBinding attribute set. -->
<iso:pattern id="Position_Constraints">
   <iso:rule context="//gml:pos">
      <iso:let name="firstCoord" value="number(tokenize(text(), ' ')[1])"/>
      <iso:let name="secondCoord" value="number(tokenize(text(), ' ')[2])"/>
      <iso:assert test="$firstCoord &gt;= -90 and $firstCoord &lt;= 90">
         The first coordinate in a gml:pos element must be between -90 and 90 degrees.
      </iso:assert>
      <iso:assert test="$secondCoord &gt;= -180 and $secondCoord &lt;= 180">
         The second coordinate in a gml:pos element must be between -180 and 180 degrees.
      </iso:assert>
      <iso:assert test="@srsName or not(@axisLabels)">
         If the srsName attribute on a gml:Point element is omitted, the axisLabels attribute must be omitted as well. 
      </iso:assert>
      <iso:assert test="@axisLabels or not(@uomLabels)">
         If the axisLabels attribute on a gml:Point element is omitted, the uomLabels attribute must be omitted as well. 
      </iso:assert>
   </iso:rule>
</iso:pattern>

Source Constraints

<iso:pattern id="Source_Constraints">
    <iso:rule context="//ddms:resource/ddms:source">
       <iso:report test="count(@*) = 0">
          A ddms:source element does not have any attributes.
       </iso:report>
    </iso:rule>
</iso:pattern>

SubjectCoverage Constraints

<iso:pattern id="SubjectCoverage_Constraints">
   <iso:rule context="//ddms:resource/ddms:subjectCoverage">
      <iso:report test="ddms:keyword[./@ddms:value = preceding-sibling::ddms:keyword/@ddms:value]">
         The ddms:subjectCoverage element contains duplicate keywords.
      </iso:report>
      <iso:report test="ddms:category[./@ddms:qualifier = preceding-sibling::ddms:category/@ddms:qualifier and ./@ddms:code = preceding-sibling::ddms:category/@ddms:code]">
         The ddms:subjectCoverage element contains duplicate categories.
      </iso:report>
   </iso:rule>
</iso:pattern>

Type Constraints

<iso:pattern id="Type_Constraints">
    <iso:rule context="//ddms:resource/ddms:type">
       <iso:assert test="not(@ddms:value) or (@ddms:qualifier and @ddms:value)">
          If a ddms:type element has a value, it must also have a qualifier.
       </iso:assert>
       <iso:report test="count(@*) = 0">
          A ddms:type element does not have any attributes.
       </iso:report>
       <iso:report test="not(@ddms:value) and @ddms:qualifier">
          A ddms:type element has a qualifier but no value.
       </iso:report>
    </iso:rule>
</iso:pattern>

VirtualCoverage Constraints

<iso:pattern id="VirtualCoverage_Constraints">
    <iso:rule context="//ddms:resource/ddms:virtualCoverage">
       <iso:report test="count(@*) = 0">
          A ddms:virtualCoverage element does not have any attributes.
       </iso:report>
       <iso:report test="@virt:address and not(@virt:protocol)">
          A ddms:virtualCoverage element has an address but no protocol.
       </iso:report>
    </iso:rule>
</iso:pattern>

Back to Top
Back to Documentation