<?xml version="1.0"?>
<!-- Look in source code to see unformatted XML -->
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
    <sch:ns uri="http://www.w3.org/1999/xhtml" prefix="xhtml"/>
    <!-- Loads the XHTML document as unparsed text -->
    <sch:let name="unparsed" value="unparsed-text(document-uri(.))"/>
    <!-- unparsed - comment -->
    <sch:let name="unparsed2" value="replace($unparsed,  '&lt;!--.*?--&gt;', '', 's')"/>
    <!-- unparsed - comment - cdata -->
    <sch:let name="unparsed3"
        value="replace($unparsed2,  '&lt;!\[CDATA\[.*?\]\]&gt;', '', 's')"/>
    <!-- unparsed - comment - cdata - pi -->
    <sch:let name="unparsed4"
    value="if (starts-with($unparsed, '&lt;?xml')) then concat(substring-before($unparsed3, '?&gt;'), '?&gt;', replace($unparsed3,  '&lt;\?.*?\?&gt;', '', 's')) else replace($unparsed3,  '&lt;\?.*?\?&gt;', '', 's')"/>
    <!-- Variable for the XML declaration -->
    <sch:let name="declaration"
        value="if (starts-with($unparsed, '&lt;?xml')) then concat(substring-before($unparsed, '?>'), '?>') else ''"/>
    <sch:pattern>
        <sch:title>Validating XML declaration</sch:title>
        <sch:rule context="xhtml:html">
            <!-- Validate if document starts with an XML declaration.  -->
            <sch:assert test="starts-with($unparsed, '&lt;?xml')">Your XHTML document must start
                with an XML declaration.</sch:assert>
            <!-- Validate if XML declaration is version 1.0.  -->
            <sch:assert
                test="not(starts-with($unparsed, '&lt;?xml') and not(matches($declaration, '1.0')))"
                >Your must use XML version 1.0.</sch:assert>
            <!-- Validate if encoding="UTF-8" is used explicitly.  -->
            <sch:assert
                test="not(starts-with($unparsed, '&lt;?xml') and not(matches($declaration, 'utf-8|UTF-8')))"
                >You must use XML encoding="UTF-8" explicitly.</sch:assert>
            <!-- Validate that the standalone pseudo attribute is not used.  -->
            <sch:assert
                test="not(starts-with($unparsed, '&lt;?xml') and matches($declaration, 'standalone'))"
                >The standalone pseudo attribute must not be used.</sch:assert>
            <!-- Validate that the XML declaration has no insignificant whitespace.  -->
            <sch:assert
                test="not(matches($declaration, 'utf-8|UTF-8') and not(matches($declaration, 'standalone')) and not(string-length($declaration) eq 38))"
                >The XML declaration must not contain insignificant whitespace.</sch:assert>
        </sch:rule>
    </sch:pattern>
    <sch:pattern>
        <sch:title>Validating DTD</sch:title>
        <sch:rule context="xhtml:html">
            <!-- Validate that DTD is used. -->
            <sch:assert test="matches($unparsed4, '&lt;!DOCTYPE')">The DOCTYPE declaration is
                missing.</sch:assert>
            <!-- Validate that there are no comments or processing instruction between XML declaration and DTD.  -->
            <sch:assert
                test="not(matches($declaration, 'utf-8|UTF-8') and not(matches($declaration, 'standalone')) and string-length($declaration) eq 38 and matches($unparsed4, '&lt;!DOCTYPE') and matches(substring-after(substring-before($unparsed, '&lt;!DOCTYPE'), '?&gt;'), '&lt;(!--|\?)'))"
                >There must be no comments or PIs between XML declaration and DTD.</sch:assert>

            <!-- Validate that there is exactly one newline between XML declaration and the DTD.  -->
            <sch:assert
                test="not(string-length($declaration) eq 38 and not(matches(substring-after(substring-before($unparsed, '&lt;!DOCTYPE'), '?&gt;'), '&lt;(!--|\?)')) and not(string-length(substring-before($unparsed4, '&lt;!DOCTYPE')) - string-length(replace(substring-before($unparsed4, '&lt;!DOCTYPE'), '&#xA;', '')) = 1))"
                >There must be exactly one newline between XML declaration and the DTD.</sch:assert>

            <!-- Validate that DTD for XHTML 1.0 Strict! is used. -->
            <sch:assert
                test="not(matches($unparsed4, '&lt;!DOCTYPE') and not(matches($unparsed4, 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd')) and not(matches($unparsed4, '-//W3C//DTD XHTML 1.0 Strict//EN')))"
                >The DTD must be for XHTML 1.0 Strict!</sch:assert>
        </sch:rule>
    </sch:pattern>
</sch:schema>

