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
@value
attribute is always present for a single-valued property, so tests should expect that@value
will match 1 value. <value>
elements are only present for multi-valued properties if a value has been specified, so tests should expect thatvalue
will 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>