Validating properties
PageSeeder properties often have specific constraints associated with them including:
- A minimum or maximum number of characters.
- A list of allowable values.
- A datatype.
- A regular expression.
Basics
Property rule
Most rules applying to images match the <property> element based on its name:
<!-- Matches a specific property in PSML based on name --> <sch:rule context="property[@name = 'acme']"> <!-- Assertions and reports here ... --> </sch:rule>
Alternatively, the datatype can be used.
<!-- Matches a specific property in PSML based on datatype --> <sch:rule context="property[@datatype = 'date']"> <!-- Assertions and reports here ... --> </sch:rule>
Message
Messages generated by Schematron rules should allow the user to quickly identify the problem.
One technique is for the message to include the @name or @title attributes from the <property> element. It can also help to include a value using the @value attribute for single-valued properties or the <value> element for multi-valued properties.
Another locator is the @id attribute of the <properties-fragment> or <section> element.
<properties-fragment> when creating the document template. For example:
Property '<sch:value-of select="@name"/>' in fragment '<sch:value-of select="parent::properties-fragment/@id"/>'
Can be used to display:
Property 'isbn' in properties fragment 'book-metadata'.
Single value vs. multiple values
Some properties only have a single value using a @value attribute while other properties contain zero or multiple values specified in the <value> element. Whether a property is single-valued or multi-valued is determined by the @count attribute.
Validation should expect having to deal with either option but not both.
Value test
One significant difference between single-valued and multi-valued properties:
- The
@valueattribute is always present for a single-valued property, so tests should expect that@valuewill match 1 value. <value>elements are only present for multi-valued properties if a value has been specified, so tests should expect thatvaluewill match 0 or more values.
Property count
Properly designed document templates should ensure that a property is consistent across a collection of documents. However, when data is uploaded from external sources, it can happen that one document has the property expressed for a single value and another document has it expressed as multi-value.
In cases where some documents are inconsistent with the document template or other documents, the following tests can determine the @value and @count attributes:
Using the <value> element is not reliable because it isn’t necessarily specified.
Single-valued
<sch:rule context="property[@name='abc']">
<!-- Expecting a single-valued property -->
<sch:assert test="@value and (@count=1 or not(@count))">
Property '<sch:value-of select="@name"/>' should be single-valued.
</sch:assert>
</sch:rule>
Multi-valued
<sch:rule context="property[@name='xyz']">
<!-- Expecting a multi-valued property -->
<sch:assert test="not(@value) and count and @count != '1'">
Property '<sch:value-of select="@name"/>' should be multi-valued.
</sch:assert>
</sch:rule>
Validating XML schema datatypes
A common constraint is to check that a property matches a specific XML Schema datatype .
To use the XML schema datatypes, make sure the XML Schema namespace is both declared (using xmlns) and mapped (using <sch:ns />)
<sch:ns prefix="xs" uri="http://www.w3.org/2001/XMLSchema"/>
Limitations
PageSeeder doesn’t use a schema-aware Schematron validator; therefore, the following techniques are limited to the built-in XML Schema datatypes.
Dates
To validate that a property value matches a date, it’s sufficient to check that it can be casted as an xs:date XML Schema value.
<sch:rule context="property[@datatype='date']">
<!-- Expecting a date -->
<sch:assert test="@value castable as xs:date">The value of property
'<sch:value-of select="@name"/>' should be a date as 'yyyy-mm-dd'
but was '<sch:value-of select="@value"/>'.</sch:assert>
</sch:rule>
Integers
To validate that a property has an integer value, it’s sufficient to check that it can be casted as an xs:integer XML Schema value.
<sch:rule context="property[@datatype='integer']">
<!-- Expecting an integer -->
<sch:assert test="@value castable as xs:integer">The value of property
'<sch:value-of select="@name"/>' should be an integer
but was '<sch:value-of select="@value"/>'.</sch:assert>
</sch:rule>
Patterns
Regular expressions are a common way to check whether a value is valid against the constraints of a pattern. To do this, use the XPath 2.0 matches() function.
<sch:rule context="property[@name='abc']">
<sch:assert test="matches(@value, 'REGEX')">The value of
property '<sch:value-of select="@name"/>' should match
pattern but was '<sch:value-of select="@value"/>'.
</sch:assert>
</sch:rule>