Sample Code

Some code samples

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

In order 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

Just like unresolved cross-references, unresolved image references will be flagged as unresolved using the @unresolved attribute.

Unresolved images may 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 to cover the case of old documents modified before @unresolved was introduced. All documents modified/created on v5.8 or later should 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 check 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>

Note

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 rule below has the same requirements for the dimension, but will be only report a single failure 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 rule below 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>

Created on , last edited on