Kapitola 5. Schematron

5.1. Validace pomocí XSLT
5.2. Vložení Schematronu do WXS
5.3. Vložení Schematronu do RELAX NG
5.4. Pokročilá validace

Dříve zmíněné schémové jazyky jako DTD, W3C XML Schema a RELAX NG víceméně definují gramatiku pro dokument XML. Schematron je založen na zcela odlišném principu. Pomocí tohoto jazyka jde zapsat tvrzení o přítomnosti nebo absenci určitých vzorů v dokumentu. Validace oproti Schematronu pak vrací seznam tvrzení, který vznikne kontrolou vzorů oproti dokumentu. Pro zápis vzorů se přitom používá dobře známý jazyk XPath. To má dvě velké výhody – máme k dispozici poměrně silné vyjadřovací prostředky XPathu a pro validaci dokumentu nám stačí XSLT procesor, protože schematronové schéma lze převést na XSLT transformaci.

Celé schéma má velmi jednoduchou strukturu. Kořenový element schema, který patří do jmenného prostoru http://purl.oclc.org/dsdl/schematron[3] stejně tak jako ostatní elementy, obsahuje několik vzorů pattern. Před vzory může být ve schématu ještě uveden název schématu (element title) a deklarovány prefixy jmenných prostorů pomocí elementu ns.

Každý vzor se skládá z jednoho nebo více pravidel rule, které mají pomocí atributu context určen kontext pro jejich vyhodnocení. Jedná se v podstatě o vzor v jazyce XPath, který ze vstupního dokumentu vybere uzly, a ty se pak chápou jako aktuální uzly pro vyhodnocení XPath výrazů uvnitř pravidla.

Uvnitř pravidla se pak používají elementy assert a report, který k sobě mají připojen atribut test s XPath výrazem. V případě, že tento výraz není splněn (assert) nebo je splněn (report) je výsledkem validace text uvnitř příslušného elementu assert, resp. report.

Uvnitř textu validačního hlášení můžeme používat další elementy. Obsah elementu name bude nahrazen jménem aktuálního elementu, obsah elementu value-of bude nahrazen textovou hodnotou XPath výrazu uvedeného v atributu select.

Příklad 5.1. Ukázka schématu ve Schematronu – uvod/zamestnanci.sch

s
c
h
<?xml version="1.0" encoding="utf-8"?> <schema xmlns="http://www.ascc.net/xml/schematron"> <pattern name="Seznam zaměstnanců je neprázdný"> <rule context="zamestnanci"> <assert test="zamestnanec">V seznamu musí být alespoň jeden zaměstnanec</assert> <report test="sum(zamestnanec/plat) &gt; 500000">Součet platů nemůže být větší než 500.000,-</report> </rule> </pattern> <pattern name="Podmínky pro zaměstnance"> <rule context="zamestnanec"> <assert test="jmeno">U zaměstnance musí být zadáno jméno.</assert> <assert test="prijmeni">U zaměstnance musí být zadáno příjmení.</assert> <assert test="email">U zaměstnance musí být zadán e-mail.</assert> <assert test="narozen">U zaměstnance musí být zadáno datum narození.</assert> <assert test="@id">U zaměstnance musí být zadáno jeho osobní číslo.</assert> <report test="jmeno[2]|prijmeni[2]">Zaměstnanec nemůže mít více než jedno jméno.</report> </rule> </pattern> <pattern name="Duplicita osobních čísel"> <rule context="zamestnanec"> <report test="count(../zamestnanec[@id = current()/@id]) &gt; 1">Duplicitní osobní číslo <value-of select="@id"/> u elementu <name/>.</report> </rule> </pattern> </schema>

5.1 Validace pomocí XSLT

Kromě samostatných knihoven a programů, které umějí provádět validaci oproti Schematronu, můžeme k použít libovolný XSLT procesor. Existuje totiž XSLT styl, který ze Schematronového schématu vygeneruje další XSLT styl. Takto vygenerovaným stylem pak transformujeme dokument, který chceme validovat. Výsledkem validace je pak seznam chyb.

Validaci pro naše ukázkové schéma tak můžeme provést v následujících krocích. Nejprve vygenerujeme ze schématu XSLT styl (validuj.xsl):

saxon -o validuj.xsl zamestnanci.sch ../tools/skeleton1-5.xsl

Tímto stylem pak zpracujeme dokument, který chceme zvalidovat:

saxon zamestnanci-chyby4.xml validuj.xsl 
Duplicitní osobní číslo 102 u elementu zamestnanec.
Duplicitní osobní číslo 102 u elementu zamestnanec.

5.2 Vložení Schematronu do WXS

Protože Schematron umožňuje postihnout i jiné aspekty dokumentu, než klasické schémové jazyky, bývá s nimi často kombinován. Do WXS můžeme schematronová pravidla vkládat pomocí elementu appInfo, který je přímo určen pro vkládání uživatelských dat.

Příklad 5.2. Schematron vložený WXS schématu – sch/zamestnanci-limit-platu.xsd

w
x
s
<?xml version="1.0" encoding="utf-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sch="http://www.ascc.net/xml/schematron"> <xs:element name="zamestnanci"> <xs:annotation> <xs:appinfo> <sch:pattern name="Máme dost na vyplacení platů"> <sch:rule context="zamestnanci"> <sch:report test="sum(zamestnanec/plat) &gt; 50000">Součet platů nemůže být větší než 50.000,-. Současný součet je <sch:value-of select="sum(zamestnanec/plat)"/></sch:report> </sch:rule> </sch:pattern> </xs:appinfo> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="zamestnanec" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="jmeno" type="xs:string"/> <xs:element name="prijmeni" type="xs:string"/> <xs:element name="email" type="xs:string" maxOccurs="unbounded"/> <xs:element name="plat" type="xs:decimal" minOccurs="0"/> <xs:element name="narozen" type="xs:date"/> </xs:sequence> <xs:attribute name="id" type="xs:int" use="required"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

Takové schéma je možné validovat buď speciálním validátorem, nebo si z něj pomocí XSLT vyextrahovat samostatné schéma ve Schematronu.

saxon -o schema.sch zamestnanci-limit-platu.xsd ../tools/wxs2sch.xsl

5.3 Vložení Schematronu do RELAX NG

Schematron lze samozřejmě vkládat i do RELAX NG. Schematronová pravidla můžeme vložit v podstatě na libovolné místo, protože gramatika RELAX NG je v tomto ohledu velmi volná.

Příklad 5.3. Schematron vložený do RELAX NG – sch/zamestnanci-limit-platu.rng

r
n
g
<?xml version="1.0" encoding="utf-8"?> <element xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes" xmlns:sch="http://www.ascc.net/xml/schematron" name="zamestnanci"> <sch:pattern name="Máme dost na vyplacení platů"> <sch:rule context="zamestnanci"> <sch:report test="sum(zamestnanec/plat) &gt; 50000">Součet platů nemůže být větší než 50.000,-. Současný součet je <sch:value-of select="sum(zamestnanec/plat)"/></sch:report> </sch:rule> </sch:pattern> <oneOrMore> <element name="zamestnanec"> <attribute name="id"> <data type="int"/> </attribute> <element name="jmeno"> <data type="string"/> </element> <element name="prijmeni"> <data type="string"/> </element> <oneOrMore> <element name="email"> <data type="string"/> </element> </oneOrMore> <optional> <element name="plat"> <data type="decimal"/> </element> </optional> <element name="narozen"> <data type="date"/> </element> <sch:pattern name="Duplicita osobních čísel"> <sch:rule context="zamestnanec"> <sch:report test="count(../zamestnanec[@id = current()/@id]) &gt; 1">Duplicitiní osobní číslo <sch:value-of select="@id"/> u elementu <sch:name/>.</sch:report> </sch:rule> </sch:pattern> </element> </oneOrMore> </element>

Schematron jde vkládat i do schémat zapsaných v kompaktní syntaxi, i když to už pak nevypadá tak pěkně.

Příklad 5.4. Schematron vložený do RNC – sch/zamestnanci-limit-platu.rnc

namespace sch = "http://www.ascc.net/xml/schematron"

[
  sch:pattern [
    name = "Máme dost na vyplacení platů"
    sch:rule [
      context = "zamestnanci"
      sch:report [
        test = "sum(zamestnanec/plat) > 50000"
        "Součet platů nemůže být větší než 50.000,-.\x{a}" ~
        "        Současný součet je "
        sch:value-of [ select = "sum(zamestnanec/plat)" ]
      ]
    ]
  ]
]
element zamestnanci {
  element zamestnanec {
    attribute id { xsd:int },
    element jmeno { xsd:string },
    element prijmeni { xsd:string },
    element email { xsd:string }+,
    element plat { xsd:decimal }?,
    element narozen { xsd:date }
    >> sch:pattern [
         name = "Duplicita osobních čísel"
         sch:rule [
           context = "zamestnanec"
           sch:report [
             test = "count(../zamestnanec[@id = current()/@id]) > 1"
             "Duplicitiní osobní číslo\x{a}" 
             sch:value-of [ select = "@id" ]
             " u elementu "
             sch:name [ ]
             "."
           ]
           "\x{a}"
         ]
       ]
  }+
}

RELAX NG schéma s obsaženými schematronovými pravidly je možné validovat buď speciálním validátorem, nebo si z něj opět můžeme pomocí XSLT vyextrahovat samostatné schéma ve Schematronu.

saxon -o schema.sch zamestnanci-limit-platu.rng ../tools/RNG2Schtrn.xsl

5.4 Pokročilá validace

Schematron se používá pro validaci těch struktur, které klasické jazyky nezvládnou. Následující schéma například ukazuje, jak jde porovnávat hodnoty v jednom dokumentu nebo kontrolovat data oproti číselníku v externím souboru.

Příklad 5.5. Ukázka síly Schematronu – sch/objednavka.xml

<?xml version="1.0" encoding="UTF-8"?>
<objednávka xmlns="urn:x-eshop:document-schemas:purchase-order">
  <adresa typ="doručovací">
    <jméno>Jan Novák</jméno>
    <ulice>Bělehradská 147</ulice>
    <město>Praha 2</město>
    <psč>120 00</psč>
  </adresa>
  <adresa typ="účtovací">
    <jméno>Petra Nováková</jméno>
    <ulice>Anglická 15</ulice>
    <město>Praha 2</město>
    <psč>120 00</psč>
  </adresa>
  <doprava>DPD</doprava>
  <platba>dobírka</platba>
  <přijata>2004-12-14</přijata>
  <doručení>2004-11-19</doručení>
  <položky>
    <položka kód="2N7-516">
      <název>Sekačka na trávu</název>
      <počet mj="ks">1</počet>
      <cena>2999</cena>
      <popis>http://example.org/sekacka.html</popis>
    </položka>
    <položka kód="Q3Y-116">
      <název>Travní semeno</název>
      <počet mj="kg">2.5</počet>
      <cena>127.50</cena>
    </položka>
  </položky>
  <komentář>O dodávku mám zájem pouze v případě, že se jedná o trávu
            v odrůdě konopí.</komentář>
</objednávka>

Příklad 5.6. Ukázka síly Schematronu – sch/sklad.xml

<?xml version="1.0" encoding="UTF-8"?>
<sklad>
  <produkt>
    <kod>2N7-516</kod>
    <nazev>Sekačka</nazev>
  </produkt>
  <produkt>
    <kod>2N7-517</kod>
    <nazev>Kosa</nazev>
  </produkt>
</sklad>

Příklad 5.7. Ukázka síly Schematronu – sch/objednavka.sch

<?xml version="1.0" encoding="utf-8"?>
<schema xmlns="http://www.ascc.net/xml/schematron">
  <title>Ukázka pokročilé validace objednávky</title>
  <ns uri="urn:x-eshop:document-schemas:purchase-order" prefix="o"/>
  <pattern name="Datum doručení je správně">
    <rule context="o:objednávka">
      <assert test="number(translate(o:doručení,'-','')) > number(translate(o:přijata,'-',''))">Datum doručení musí být větší
        než datum přijetí objednávky.</assert>
    </rule>
  </pattern>
  <pattern name="Produkt je v číselníku">
    <rule context="o:položka">
      <assert test="@kód = document('sklad.xml')/sklad/produkt/kod">Objednaný produkt (kód: <value-of select="@kód"/>) není na skladě.</assert>
    </rule>
  </pattern>
</schema>


[3] Předchozí verze Schematronu používaly jmenný prostor http://www.ascc.net/xml/schematron. Při použití Schematronu si zjistěte, pro jakou verzi je validátor určen. Mnoho dnes používaných validátorů ještě nebylo rozšířeno o podporu ISO Schematronu. Z tohoto důvodu jsou i zde uváděné příklady určeny pro pre-ISO verzi Schematronu.

© Jiří Kosek 2004

Tento dokument je určen výhradně pro osobní potřebu seznámení se schémovými jazyky. Jakékoliv jiné použití, včetně dalšího šíření, pořizování kopií, použití při školeních a výuce apod. je výslovně zakázáno a bude považováno za porušení autorských práv.

Dokument je zkrácenou verzí školicích materiálů používaných během školení XML schémata. Školení se mj. věnuje i problematice data-bindingu a využití informací ze schématu uvnitř aplikací.


Copyright © 2003-2005 Jiří Kosek