Validating images
Images in PSML documents often have constraints beyond what the PSML schema requires. This article provides some sample code for common use cases.
Basics
Image rule
Most rules applying to images match the <image>
element:
<!-- Matches images in PSML --> <sch:rule context="image"> <!-- Assertions and reports here ... --> </sch:rule>
Message
The message returned by Schematron when reported or when an assertion fails should allow the user to quickly identify the problem so that it can be fixed.
On the <image>
element, you can use the attributes @src
, @uriid
and @alt
to help the user identify the problematic image. But note, however, that the @alt
attribute is not always present.
To know where to fix the problem, it is often useful to provide either the fragment or section ID.
For example:
Image '<sch:value-of select="@alt"/>' at '<sch:value-of select="@src"/>' in fragment <sch:value-of select="ancestor::fragment/@id"/>
Can be used to display:
Image 'Program schedule' at '/images/program_sch.png' in fragment 43.
Validating the image reference
From version 5.8, images are no longer simple declarations, but are proper references. So PageSeeder is able to check that images references correspond to actual image files.
Checking that an image is resolved
Similar to unresolved cross-references, unresolved image references are flagged as unresolved using the @unresolved
attribute.
Unresolved images might occur after an upload or if an image file is deleted.
The following rule checks that the images are resolved:
<sch:rule context="image"> <!-- Image has no 'unresolved' attribute --> <sch:assert test="not(@unresolved) and @uriid"> The image at <sch:value-of select="@src"/> is unresolved. </sch:assert> </sch:rule>
The extra check that @uriid
exists is for PageSeeder documents from before version 5.8, when @unresolved
was introduced. Documents after this point have @unresolved
for unresolved images.
Validating dimensions
The following rules define assertions on the @width
and @height
attributes of the <image>
element.
Checking that dimensions are defined
The following rule defines an assertion to check that the @width
and @height
attributes have been defined on the image element.
<sch:rule context="image"> <!-- Width is not defined --> <sch:assert test="@width"> The width of this image was not defined: <sch:value-of select="@src"/>. </sch:assert> <!-- Height is not defined --> <sch:assert test="@height"> The height of this image was not defined: <sch:value-of select="@src"/>. </sch:assert> </sch:rule>
Checking that dimensions meet criteria
The following rule checks that an image fits within dimensions specified by a minimum and maximum value for width and height.
In this example, we have defined the minimum and maximum dimensions as variables to make it easier to configure.
<sch:rule context="image"> <!-- Min/max dimensions are defined here --> <sch:let name="min-width" value="400"/> <sch:let name="max-width" value="800"/> <sch:let name="min-height" value="200"/> <sch:let name="max-height" value="600"/> <!-- Width exceeds max width --> <sch:assert test="@width and @width le $max-width"> The width of image at '<sch:value-of select="@src"/>' is too large. Width is <sch:value-of select="@width"/> (max=<sch:value-of select="$max-width"/>px). </sch:assert> <!-- Width lower than min width --> <sch:assert test="@width and @width ge $min-width"> The width of image at '<sch:value-of select="@src"/>' is too small. Width is <sch:value-of select="@width"/> (min=<sch:value-of select="$min-width"/>px). </sch:assert> <!-- Height exceeds max height --> <sch:assert test="@height and @height le $max-height"> The height of image at '<sch:value-of select="@src"/>' is too large. Height is <sch:value-of select="@height"/> (max=<sch:value-of select="$max-height"/>px). </sch:assert> <!-- Height lower than min height --> <sch:assert test="@height and @height ge $min-height"> The height of image at '<sch:value-of select="@src"/>' is too small. Height is <sch:value-of select="@height"/> (min=<sch:value-of select="$min-height"/>px). </sch:assert> </sch:rule>
In the example above, we defined several assertions, but the same requirements could also be validated with less assertions. This would essentially affect the number of errors reported and the error message displayed to the user.
For example, the following rule has the same requirements for the dimensions, but only a single failure is reported with a less precise message.
<!-- Match images in PageSeeder --> <sch:rule context="image"> <!-- Min/max dimensions are defined here --> <sch:let name="min-width" value="400"/> <sch:let name="max-width" value="800"/> <sch:let name="min-height" value="200"/> <sch:let name="max-height" value="600"/> <!-- Width exceeds max width --> <sch:assert test="@width and @height and @width ge $min-width and @width le $max-width and @height ge $min-height and @height le $max-height"> Image at '<sch:value-of select="@src"/>' does not meet dimensions criteria. Dimensions specified were (W×H): <sch:value-of select="@width"/>× <sch:value-of select="@height"/> but required dimensions are minimum <sch:value-of select="$min-width"/>× <sch:value-of select="$min-height"/> and maximum <sch:value-of select="$max-width"/>× <sch:value-of select="$max-height"/>. </sch:assert> </sch:rule>
Validating image path
The path to an image is defined in the @src
attribute.
Checking that an image is not archived
The following rule checks that the image is not in the archive folder.
<sch:rule context="image"> <!-- Image is archived --> <sch:assert test="not(contains(@src, '/archive/'))"> Image at '<sch:value-of select="@src"/>' is archived. </sch:assert> </sch:rule>
Checking that images are in specific folder
From PageSeeder 5.8, the path of resolved images is automatically generated and stored in the @src
attribute.
<sch:rule context="image"> <!-- Define folder here --> <sch:let name="folder" value="images"/> <!-- Image is archived --> <sch:assert test="tokenize(@src,'/')[last()-1] = $folder"> Image at '<sch:value-of select="@src"/>' is not in folder '<sch:value-of select="$folder"/>'. </sch:assert> </sch:rule>