---
title: "Validating properties"
source: https://dev.pageseeder.com/reference/sample_code/schematron/validating_properties.html
last_updated: 2026-09-14T15:59:05+10:00
tokens: ~1343
---

# 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:

```xml

<!-- 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.

```xml

<!-- 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.

> **Note:** Keep validation in mind when specifying the ID for a  \<properties-fragment\> when creating the document template. 

For example:

```xml

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 that `value` 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

```xml

<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

```xml

<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](https://www.w3.org/TR/xmlschema-2).

> **Note:** To use the XML schema datatypes, make sure the XML Schema namespace is both declared (using `xmlns`) *and* mapped (using `<sch:ns />`)

```xml

<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.

```xml

<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.

```xml

<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()](https://www.w3.org/TR/xpath-functions) function.

```xml
<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>
```

