Article Index

Možnosti definice struktury XML Schema

V úvodu byla jednoduchá ukázka definice posloupnosti 4 značek bez zanoření, atributů, možnosti výběru, omezení a dalších možností definičního nástroje XML Schema. Pokud vytváříme definici v XSD, musíme soubor XSD nalinkovat do XML:

<komunikace xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="komunikace.xsd">

Namespace

Každý (téměř) z jazyků rodiny XML používá namespace - je to zjednodušeně řečeno odlišení jednotlivých jazyků, zejména užitečné v případě, že kombinujeme několik jazyků v jednom souboru. Taková možnost nastane napříkald u transformací, kde lze kombinovat XSL(T), XSL:FO, SV, HTML a další. Namespace označuje některé jazyky a na první pohled je tak zřejmé, s čím pracujeme. U XSD je každá značka uvozena "xs:".

Definice elementu

Základní strukturou XSD je element - definice jediné značky - další je pak úpravou možností, co v dané značce může být (datový typ, omezení, atribut) a jaké jsou možnosti (volitelnost, výběr z možností, ...).

<xs:element name="" type="" minOccurs="" maxOccurs="" />

U elementu je vždy povinné jméno "name" a datový typ "type". Další dvě volby uvedené v příkladu jsou volitelné - udávají minimální a maximální počet výskytu dané značky na daném místě v hierarchii. Pokud tyto dvě možnosti nejsou uvedené, pak je značka povinná a vyskytuje se přesně 1x. Pokud chceme umožnit neomezený výstyk značky, pak se do uvozovek vkládá hodnota "unbounded".

Definice posloupnosti

Dokument obsahující jedinou znčku nedává moc smysl. Takže vzhledem k tomu, že v XML jazyce je jedna značka vždy kořenová (a to přesně jediná), pak je každý dokument tvořen alespoň jedním potomkem této značky. V reálném použití je hierarchie hlubší a potomků je více.

Jednoduchá posloupnost byla vidět na ukázce výše.

XML

<zprava>
  <od>Michal</od>
  <komu>Jan</komu>
  <predmet>Přednáška</predmet>
  <text>Vem to dnes prosím za mne.</text>
</zprava>

XSD

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="zprava">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="od" type="xs:string"/>
      <xs:element name="komu" type="xs:string"/>
      <xs:element name="predmet" type="xs:string"/>
      <xs:element name="text" type="xs:string"/>
     </xs:sequence>
    </xs:complexType>
   </xs:element>
</xs:schema>

Kořená značka <zprava></zprava> obsahuje elementy (potomky) <od></od>, <komu></komu>, <predmet></predmet> a <text></text>. Jdeme rozebrat jednotlivé položky.

<?xml version="1.0"?>

Dokument je v jazyce XML - tedy na začátku je deklarace XML.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

Pokud používáme namespace, musíme jej do dokumentu vložit - jinak bude validace (a jakýkoliv interpret) házet chybu, že daný namespace nezná.

<xs:element name="zprava">

Definujeme kořenovou značku. Značka neobsahuje datový typ - protože nebude sloužit k uložení hodnot (dat), ale obsahuje potomky - další značky. Stejně tak je kořenová značka vždy právě jedna, tak nemusíme určit minimální a maximální počet výskytů.

<xs:complexType>

Pokud je značka rodičem pro další značku(y), pak je to výdy complexType.

<xs:sequence>

Značka obsahuje potomky a tyto značky jsou v určitém pořadí - sekvenci. toto poředí je závazné a musí se dodržovat.

<xs:element name="od" type="xs:string"/>
<xs:element name="komu" type="xs:string"/>
<xs:element name="predmet" type="xs:string"/>
<xs:element name="text" type="xs:string"/>

A následuje výčet značek v sekvenci. A pak uzavření párových značek.

Přidání atributu

Atribut v případě elementu zpráva může být například id dané zprávy. V definici se v tomto případě přidá mezi ukončení sekvence a ukončení complexType. Zápis je stále jednoduchý - pomocí atributů name, use (required - povinný, implied - nepovinný, fixed - napevno) a type.

XML

<zprava id="125">
  <od>Michal</od>
  <komu>Jan</komu>
  <predmet>Přednáška</predmet>
  <text>Vem to dnes prosím za mne.</text>
</zprava>

XSD

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="zprava">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="od" type="xs:string"/>
      <xs:element name="komu" type="xs:string"/>
      <xs:element name="predmet" type="xs:string"/>
      <xs:element name="text" type="xs:string"/>
     </xs:sequence>
    <xs:attribute name="id" use="required" type="xs:integer"/> <!-- definice atributu id znacky zprava -->
    </xs:complexType>
   </xs:element>
</xs:schema>

Atribut je tady v elementu - v sekvenci. Pokud deklarujeme atribut pro "koncovou" značku, pak je to následovně:

<xs:element name="zprava">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:integer"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>

Zanoření více značek - reference

Uvedneý příklad je velmi jednoduchý a v praxi zřejmě zřídka dosažitelný, jak tedy na vícenásobné vnoření v XSD? Máme dvě možnosti - první je tvořit vnořenou strukturu i v případě definičního souboru. U složitějších struktur se pak dostáváme do velmi nepřehledné situace. Druhá možnost je využít reference a značky definovat postupně - napřed v rámci struktury pouze odkaz a definice dané značky je pak až jako poslední na řadě. Upravme si soubor tak, jak aby nebyl zatím příliš složitý:

<zpravy>
  <zprava id="125">
    <od>Michal</od>
    <komu>Jan</komu>
    <predmet>Přednáška</predmet>
    <text>Vem to dnes prosím za mne.</text>
  </zprava>
</zpravy>

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="zpravy">
    <xs:complexType>
     <xs:sequence>
      <xs:element ref="zprava"/> <!-- odkaz na definici elementu zprava -->
     </xs:sequence>
    <xs:attribute name="id" use="required" type="xs:integer"/>
    </xs:complexType>
   </xs:element>
  <xs:element name="zprava"> <!-- definice elementu zprava -->
    <xs:complexType>
     <xs:sequence>
      <xs:element name="od" type="xs:string"/>
      <xs:element name="komu" type="xs:string"/>
      <xs:element name="predmet" type="xs:string"/>
      <xs:element name="text" type="xs:string"/>
     </xs:sequence>
    <xs:attribute name="id" use="required" type="xs:integer"/>
    </xs:complexType>
   </xs:element>
</xs:schema>

Vnoření a definice přes referenci je vidět u elementu zpravy - kde v sekvenci je definici elementu zpravy přes odkaz - ref="zprava". Značka zprava je pak definována dále. Takto je možné použít XSD i na složité struktury a udržet soubor přehledný.

Počet výskytu vybraného elementu

Při našem zápisu prozatím neupravujeme počet výskytů daného elementu. V tom případě se předpokládá, že bude na daném místě pouze 1x. Když potřebujeme povolit jeho volitelnost (počet výskytů 0) nebo vícenásobné vložení (můžeme nechat neomezený počet nebo omezit horní počet výskytů elementu), použijeme následujíc úpravu.

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="zpravy">
    <xs:complexType>
     <xs:sequence>
      <xs:element ref="zprava" minOccurs="0" maxOccurs="unbounded"/> <!-- zpráv může být 0 až nekonečno -->
     </xs:sequence>
    <xs:attribute name="id" use="required" type="xs:integer"/>
    </xs:complexType>
   </xs:element>
  <xs:element name="zprava">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="od" type="xs:string"/>
      <xs:element name="komu" type="xs:string" minOccurs="1" maxOccurs="10"/> <!-- adresát musí být alespoň jeden, maximum je omezeno na 10 -->
      <xs:element name="predmet" type="xs:string"/>
      <xs:element name="text" type="xs:string"/>
     </xs:sequence>
    <xs:attribute name="id" use="required" type="xs:integer"/>
    </xs:complexType>
   </xs:element>
</xs:schema>

Volitelnost vybraných značek

Náš příklad se týká zprávy, pojďme si upravit příjemce tak, aby odpovídali emailové zprávě. Přidáme příjemce CC (kopie) a BCC (slepé kopie) s tím, že vždy musí být alespoň jedenkrát značka <komu></komu>.

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="zpravy">
    <xs:complexType>
     <xs:sequence>
      <xs:element ref="zprava" minOccurs="0" maxOccurs="unbounded"/> <!-- zpráv může být 0 až nekonečno -->
     </xs:sequence>
    <xs:attribute name="id" use="required" type="xs:integer"/>
    </xs:complexType>
   </xs:element>
  <xs:element name="zprava">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="od" type="xs:string"/>
      <xs:element name="komu" type="xs:string" minOccurs="1" maxOccurs="10"/>
            <xs:element name="cc" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element name="bcc" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> 
      <xs:element name="predmet" type="xs:string"/>
      <xs:element name="text" type="xs:string"/>
     </xs:sequence>
    <xs:attribute name="id" use="required" type="xs:integer"/>
    </xs:complexType>
   </xs:element>
</xs:schema>

Možnost volby - výběr z několika elementů

Pokud odhlédneme od striktního použití jako emailové zprávy, pak můžeme udělat variantu pro SMS - budou na výběr dvě skupiny značek.

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="zpravy">
    <xs:complexType>
     <xs:sequence>
      <xs:element ref="zprava" minOccurs="0" maxOccurs="unbounded"/> <!-- zpráv může být 0 až nekonečno -->
     </xs:sequence>
    <xs:attribute name="id" use="required" type="xs:integer"/>
    </xs:complexType>
   </xs:element>
  <xs:element name="zprava">
    <xs:complexType>
    <xs:choice>
     <xs:sequence>
      <xs:element name="od" type="xs:string"/>
      <xs:element name="komu" type="xs:string" minOccurs="1" maxOccurs="10"/> <!-- adresát v "normální podobě" -->
      <xs:element name="predmet" type="xs:string"/>
      <xs:element name="text" type="xs:string"/>
     </xs:sequence>
          <xs:sequence>
      <xs:element name="telefon_odesilatel" type="xs:string"/>
      <xs:element name="telefon_prijmece" type="xs:string" minOccurs="1" maxOccurs="10"/> <!-- adresát ve formě kopie -->
      <xs:element name="predmet" type="xs:string"/>
     </xs:sequence>
    </xs:choice>
    <xs:attribute name="id" use="required" type="xs:integer"/>
    </xs:complexType>
   </xs:element> 
</xs:schema>