Re: [xsl] Testing implicit XHTML hierarchy

Subject: Re: [xsl] Testing implicit XHTML hierarchy
From: "Jesper Tverskov" <jesper@xxxxxxxxxxx>
Date: Thu, 5 Jul 2007 14:15:33 +0200
I have now modified the nice XSLT stylesheet of David Carlisle in
order to get XPath testing that can be easily transferred from XSLT to
Schematron.

Basically I have made templates for h1-h4 (templates for h5 and h6 are
not necessary, they can be directly followed by any heading except h1)
to get rid of xsl:for-each, and I have provided for more exact error
messages.

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xhtml="http://www.w3.org/1999/xhtml";
exclude-result-prefixes="xhtml">
   <xsl:output indent="yes"/>

   <xsl:variable name="h"
       select="//xhtml:*[matches(local-name(),'^h[1-6]')]/number(substring(local-name(),2))"/>

   <xsl:template match="/">
     <test>
         <xsl:if test="not($h[1]=1)"><error>h1 must be the first
heading.</error></xsl:if>
         <xsl:if test="not(count($h[.=1])=1)"><error>There can only
be one h1.</error></xsl:if>
         <xsl:apply-templates
select="//xhtml:h1|//xhtml:h2|//xhtml:h3|//xhtml:h4"/>
     </test>
   </xsl:template>

   <xsl:template match="//xhtml:h1">
       <xsl:variable name="b"
           select="count(preceding::xhtml:*[matches(local-name(),'^h[1-6]')])
+ 1"/>
       <xsl:if test="$h[$b + 1]-$h[$b] gt 1">
           <error>The first heading after h1 can not be
h<xsl:value-of select="$h[$b + 1]"/>. Only h2 is allowed.</error>
       </xsl:if>
   </xsl:template>

   <xsl:template match="//xhtml:h2">
       <xsl:variable name="b"
           select="count(preceding::xhtml:*[matches(local-name(),'^h[1-6]')])
+ 1"/>
       <xsl:if test="$h[$b + 1]-$h[$b] gt 1">
       <error>The first heading after h2(<xsl:value-of
select="count(preceding::xhtml:h2) + 1" />) can not be h<xsl:value-of
select="$h[$b + 1]"/>. Only h2 or h3 is allowed.</error>
       </xsl:if>
   </xsl:template>

   <xsl:template match="//xhtml:h3">
       <xsl:variable name="b"
           select="count(preceding::xhtml:*[matches(local-name(),'^h[1-6]')])
+ 1"/>
       <xsl:if test="$h[$b + 1]-$h[$b] gt 1">
           <error>The first heading after h3(<xsl:value-of
select="count(preceding::xhtml:h3) + 1" />) can not be h<xsl:value-of
select="$h[$b + 1]"/>. Only h2 or h3 or h4 is allowed.</error>
       </xsl:if>
   </xsl:template>

   <xsl:template match="//xhtml:h4">
       <xsl:variable name="b"
           select="count(preceding::xhtml:*[matches(local-name(),'^h[1-6]')])
+ 1"/>
       <xsl:if test="$h[$b + 1]-$h[$b] gt 1">
           <error>The first heading after h4(<xsl:value-of
select="count(preceding::xhtml:h4) + 1" />) can not be h6. Only h2 or
h3 or h4 or h5 is allowed.</error>
       </xsl:if>
   </xsl:template>

</xsl:stylesheet>

Cheers,
Jesper Tverskov
http://www.xmlplease.com/schematron

Current Thread