Potřebujete pomoci s XML schématy?
Nabízím školení, konzultace, vývoj schémat na zakázku. Nevájte a kontaktujte mne.

Podpořte provoz stránek
Platba probíhá pomocí služby PayPal a je možné platit kartou nebo převodem z vašeho PayPal účtu.

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[5] 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 – sch/zamestnanci.sch

s
c
h
<?xml version="1.0" encoding="utf-8"?> <schema xmlns="http://purl.oclc.org/dsdl/schematron"> <pattern> <title>Seznam zaměstnanců je neprázdný a máme na výplaty</title> <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> <title>Podmínky pro zaměstnance</title> <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> <title>Duplicita osobních čísel</title> <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ž sada XSLT transformací, které ze Schematronového schématu vygenerují další transformaci XSLT. Takto vygenerovanou trnasformací pak zpracujeme 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 v několika postupných krocích vygenerujeme ze schématu transformaci XSLT (validuj.xsl):

saxon -o temp1.sch zamestnanci.sch ..\tools\iso_dsdl_include.xsl
saxon -o temp2.sch temp1.sch ..\tools\iso_abstract_expand.xsl
saxon -o validuj.xsl temp2.sch ..\tools\iso_schematron_message.xsl

Získanou transformací pak zpracujeme dokument, který chceme zvalidovat:

saxon zamestnanci-chyby.xml validuj.xsl 
Součet platů nemůže být větší než 500.000,-
Duplicitní osobní číslo 102 u elementu zamestnanec.
Duplicitní osobní číslo 102 u elementu zamestnanec.

Pro další zpracování chyb je vhodnější než prostý textový výstup formát SVRL (Schematron Validation Report Language). Pokud jej chceme získat, stačí při generování validační transformace použít v poslední fází transformaci iso_svrl_for_xslt1.xsl místo iso_schematron_message.xsl.

Příklad 5.2. Ukázka chybových hlášení ve formátu SVRL

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<svrl:schematron-output xmlns:svrl="http://purl.oclc.org/dsdl/svrl">
   <svrl:active-pattern name="Seznam zaměstnanců je neprázdný a máme na výplaty"/>
   <svrl:fired-rule context="zamestnanci"/>
   <svrl:successful-report test="sum(zamestnanec/plat) &gt; 500000" location="/zamestnanci">
      <svrl:text>Součet platů nemůže být větší než 500.000,-</svrl:text>
   </svrl:successful-report>
   <svrl:active-pattern name="Podmínky pro zaměstnance"/>
   <svrl:fired-rule context="zamestnanec"/>
   <svrl:fired-rule context="zamestnanec"/>
   <svrl:fired-rule context="zamestnanec"/>
   <svrl:active-pattern name="Duplicita osobních čísel"/>
   <svrl:fired-rule context="zamestnanec"/>
   <svrl:fired-rule context="zamestnanec"/>
   <svrl:successful-report test="count(../zamestnanec[@id = current()/@id]) &gt; 1"
      location="/zamestnanci/zamestnanec[2]">
      <svrl:text>Duplicitní osobní číslo 102 u elementu zamestnanec.</svrl:text>
   </svrl:successful-report>
   <svrl:fired-rule context="zamestnanec"/>
   <svrl:successful-report test="count(../zamestnanec[@id = current()/@id]) &gt; 1"
      location="/zamestnanci/zamestnanec[3]">
      <svrl:text>Duplicitní osobní číslo 102 u elementu zamestnanec.</svrl:text>
   </svrl:successful-report>
</svrl:schematron-output>

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.3. 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://purl.oclc.org/dsdl/schematron"> <xs:element name="zamestnanci"> <xs:annotation> <xs:appinfo> <sch:pattern> <sch:title>Máme dost na vyplacení platů</sch:title> <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.4. 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://purl.oclc.org/dsdl/schematron" name="zamestnanci"> <sch:pattern> <sch:title>Máme dost na vyplacení platů</sch:title> <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> <sch:title>Duplicita osobních čísel</sch:title> <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.5. Schematron vložený do RNC – sch/zamestnanci-limit-platu.rnc

namespace sch = "http://purl.oclc.org/dsdl/schematron"

[
  sch:pattern [
    sch:title [ "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 [
         sch:title [ "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 [ ]
             "."
           ]
         ]
       ]
  }+
}

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.6. 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.7. 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.8. Ukázka síly Schematronu – sch/objednavka.sch

s
c
h
<?xml version="1.0" encoding="utf-8"?> <schema xmlns="http://purl.oclc.org/dsdl/schematron"> <title>Ukázka pokročilé validace objednávky</title> <ns uri="urn:x-eshop:document-schemas:purchase-order" prefix="o"/> <pattern> <title>Datum doručení je správně</title> <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> <title>Produkt je v číselníku</title> <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>

Standardně Schematron pro zápis podmínek používá XPath 1.0. Nicméně pomocí atributu queryBinding můžeme zvolit jiný dotazovací jazyk – nejpoužívanější je asi hodnota xslt2, která zastupuje XPath 2.0 obohacený o přídavné funkce definované v rámci XSLT 2.0. Nejzajímavější je pak možnost využít zejména nové funkce podporující přímo typy XML schémat.

Příklad 5.9. Schematron s podmínkami zapsanými v XPath 2.0 – sch/objednavka-xpath2.sch

s
c
h
<?xml version="1.0" encoding="utf-8"?> <schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2"> <title>Ukázka pokročilé validace objednávky</title> <ns uri="urn:x-eshop:document-schemas:purchase-order" prefix="o"/> <ns uri="http://www.w3.org/2001/XMLSchema" prefix="xs"/> <pattern> <title>Datum doručení je správně</title> <rule context="o:objednávka"> <assert test="xs:date(o:doručení) gt xs:date(o:přijata)">Datum doručení musí být větší než datum přijetí objednávky.</assert> <assert test="xs:date(o:přijata) - xs:date(o:doručení) gt xs:dayTimeDuration('P7D')">Na doručení musí být lhůta alespoň sedmi dnů.</assert> </rule> </pattern> </schema>



[5] 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.

© Jiří Kosek 2014

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-2013 Jiří Kosek