<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
   <title>ISO Schematron rules</title>
   <!-- This file generated by 'extract-isosch.xsl'. -->
   <!-- ********************* -->
   <!-- namespaces, declared: -->
   <!-- ********************* -->
   <ns prefix="snh" uri="https://w3id.org/soranoha/ns/tei"/>
   <ns prefix="tei" uri="http://www.tei-c.org/ns/1.0"/>
   <ns prefix="xs" uri="http://www.w3.org/2001/XMLSchema"/>
   <ns prefix="rng" uri="http://relaxng.org/ns/structure/1.0"/>
   <ns prefix="rna" uri="http://relaxng.org/ns/compatibility/annotations/1.0"/>
   <ns prefix="sch" uri="http://purl.oclc.org/dsdl/schematron"/>
   <ns prefix="sch1x" uri="http://www.ascc.net/xml/schematron"/>
   <!-- ******************************************************* -->
   <!-- constraints in en, und, mul, zxx, of which there are 90 -->
   <!-- ******************************************************* -->
   <pattern id="snh-tei-header-title">
      <rule context="tei:teiHeader">
         <assert test="tei:fileDesc/tei:titleStmt/tei:title[not(@type = ('sub', 'sub-reading', 'reading', 'original'))]"> Soranoha TEI requires a main title in teiHeader/fileDesc/titleStmt.</assert>
      </rule>
   </pattern>
   <pattern id="snh-tei-header-source-work-id">
      <rule context="tei:teiHeader">
         <assert test=".//tei:idno[@type = ('aozora-work-id', 'source-work-id')]"> Soranoha TEI requires an Aozora work ID or source work identifier.</assert>
      </rule>
   </pattern>
   <pattern id="snh-publication-licence">
      <rule context="tei:teiHeader">
         <assert test="tei:fileDesc/tei:publicationStmt/tei:availability/tei:licence[@target and normalize-space(@target) != '']"> Soranoha TEI requires a rights grant in teiHeader/fileDesc/publicationStmt/availability/licence with a non-empty @target (snh-publication-licence)</assert>
      </rule>
   </pattern>
   <pattern id="snh-header-language-declared">
      <rule context="tei:TEI">
         <assert test="tei:teiHeader/tei:profileDesc/tei:langUsage/tei:language[@ident and normalize-space(@ident) != '']"> teiHeader must declare at least one tei:profileDesc/tei:langUsage/tei:language with non-empty @ident (snh-header-language-declared)</assert>
      </rule>
   </pattern>
   <pattern id="snh-ruby-complete">
      <rule context="tei:ruby">
         <assert test="tei:rb and tei:rt"> Soranoha TEI ruby requires both rb and rt components.</assert>
      </rule>
   </pattern>
   <pattern id="snh-ruby-base-non-empty">
      <rule context="tei:ruby/tei:rb">
         <assert test="normalize-space(string(.)) != '' or .//tei:g[starts-with(@ref, '#')]"> Soranoha TEI ruby base must contain source text or a declared character.</assert>
      </rule>
   </pattern>
   <pattern id="snh-ruby-reading-non-empty">
      <rule context="tei:ruby/tei:rt">
         <assert test="normalize-space(string(.)) != '' or .//tei:g[starts-with(@ref, '#')]"> Soranoha TEI ruby reading must contain source text or a declared character.</assert>
      </rule>
   </pattern>
   <pattern id="snh-gaiji-reference">
      <rule context="tei:g">
         <assert test="@ref or @corresp or @ana"> Soranoha TEI gaiji requires a declaration reference, source marker reference, or resolution status.</assert>
      </rule>
   </pattern>
   <pattern id="snh-gaiji-chardecl-resolution">
      <rule context="tei:g[starts-with(@ref, '#')]">
         <assert test="/tei:TEI/tei:teiHeader//tei:charDecl/tei:char/@xml:id = substring-after(@ref, '#')"> Soranoha TEI gaiji local @ref must point to a charDecl/char declaration in this document.</assert>
      </rule>
   </pattern>
   <pattern id="snh-char-resolution-form">
      <rule context="tei:charDecl/tei:char">
         <assert test="(some $m in tei:mapping satisfies normalize-space(string($m)) != '') or (some $u in tei:unicodeProp satisfies normalize-space(string($u/@value)) != '') or (some $l in tei:localProp satisfies normalize-space(string($l/@value)) != '') or (some $d in tei:desc satisfies normalize-space(string($d)) != '')"> tei:charDecl/tei:char must declare at least one non-empty resolution form: tei:mapping, tei:unicodeProp/@value, tei:localProp/@value, or tei:desc (snh-char-resolution-form)</assert>
      </rule>
   </pattern>
   <pattern id="snh-figure-accessibility">
      <rule context="tei:figure">
         <report role="warning"
                 test="not((tei:figDesc | tei:head | tei:p | tei:note[@type = ('image-description', 'caption-reference')])[normalize-space(.) != ''])"> Soranoha TEI figure carries no nonempty description or caption, so the image it names has no alternative text.</report>
      </rule>
   </pattern>
   <pattern id="snh-source-span-reference">
      <rule context="*[@source]">
         <assert test="every $s in tokenize(normalize-space(@source), '\s+') satisfies starts-with($s, '#')"> Soranoha TEI source span references must point to local span identifiers.</assert>
      </rule>
   </pattern>
   <pattern id="snh-source-span-target-exists">
      <rule context="*[@source]">
         <assert test="every $s in tokenize(normalize-space(@source), '\s+') satisfies exists(id(substring-after($s, '#'))[@xml:id = substring-after($s, '#')])"> Soranoha TEI source span fragments must resolve to an existing @xml:id in this document.</assert>
      </rule>
   </pattern>
   <pattern id="snh-transcription-vs-annotation">
      <rule context="tei:text//tei:c | tei:text//tei:cl | tei:text//tei:interp | tei:text//tei:interpGrp | tei:text//tei:m | tei:text//tei:pc | tei:text//tei:phr | tei:text//tei:s | tei:text//tei:span | tei:text//tei:spanGrp | tei:text//tei:w">
         <assert role="warning"
                 test="ancestor::tei:TEI/tei:teiHeader//tei:encodingDesc//tei:tagsDecl//tei:namespace[@name = 'http://www.tei-c.org/ns/1.0']/tei:tagUsage/@gi = local-name()"> Soranoha TEI linguistic enrichment in the transcription layer must be declared in the header.</assert>
      </rule>
   </pattern>
   <pattern id="snh-vocab-version-declared">
      <rule context="tei:TEI[@snh:* or .//@snh:*]">
         <assert test="@snh:vocab-version"> TEI roots using Soranoha extension attributes must declare snh:vocab-version.</assert>
      </rule>
   </pattern>
   <pattern id="snh-preservation-record-shape">
      <rule context="*[@snh:preservation-record]">
         <assert test="matches(@snh:preservation-record, '^r[0-9]{6}$')"> snh:preservation-record must be a deterministic preservation sidecar record id such as r000042.</assert>
      </rule>
   </pattern>
   <pattern id="snh-layout-params-shape">
      <rule context="*[@snh:layout-params]">
         <assert test="matches(@snh:layout-params, '^[A-Za-z0-9_.:-]+=[^\s;]+(;[A-Za-z0-9_.:-]+=[^\s;]+)*$')"> snh:layout-params must use semicolon-delimited key=value pairs.</assert>
      </rule>
   </pattern>
</schema>
