--- marp: true theme: default paginate: true size: 16:9 style: | section { font-size: 24px; } section h1 { color: #1a5276; } section h2 { color: #2980b9; } section table { font-size: 20px; } section small { font-size: 18px; } --- # Wykład 8 ## Relax NG — alternatywny język schematów **Systemy Zarządzania Treścią** Politechnika Poznańska --- # Część 1 ## Wprowadzenie do Relax NG --- ## Czym jest Relax NG? > **Relax NG** (REgular LAnguage for XML Next Generation) to język schematów dla dokumentów XML, oparty na **gramatykach regularnych** — alternatywa dla DTD i XML Schema. ### Geneza i status | Aspekt | Informacja | |---|---| | **Autor** | James Clark (współtwórca XSLT) | | **Standard ISO** | ISO/IEC 19757-2 (DSDL) | | **Standard OASIS** | RELAX NG Specification | | **Dwie składnie** | XML (pełna) i compact (skrótowa) | | **Podstawa teoretyczna** | Gramatyki regularne drzew | ### Filozofia projektowa Relax NG łączy **prostotę i moc DTD** z **formalną czystością** gramatyk regularnych. W przeciwieństwie do XML Schema, model jest **jednolity i przewidywalny** — bez rozróżnienia na typy proste/złożone jako osobnych bytów. --- ## Dwie składnie Relax NG Relax NG występuje w dwóch równoważnych formach składniowych: ### 1. Składnia XML (pełna) ```xml ``` ### 2. Składnia compact (skrótowa) ``` element addressBook { element card { element name { text }, element email { text } }* } ``` > Obie składnie są **równoważne** — narzędzie Trang konwertuje między nimi automatycznie. --- ## Relax NG na tle DTD i XML Schema | Cecha | DTD | XML Schema | Relax NG | |---|---|---|---| | **Podstawa** | gramatyki SGML | typy + struktury | gramatyki regularne | | **Składnia** | własna (nie-XML) | XML | XML + compact | | **Typy danych** | 10 typów | 44 wbudowane + własne | dowolne (przez biblioteki) | | **Jednolitość modelu** | — | podział proste/złożone | jednolity model wzorców | | **Przestrzenie nazw** | brak | pełne | pełne (klasy nazw) | | **Mieszana zawartość** | ograniczona | możliwa | naturalna (mixed) | | **Przeplot (interleave)** | brak | brak | tak | | **Modularyzacja** | encje parametryczne | include/import/redefine | include/externalRef/combine | | **Złożoność specyfikacji** | niska | bardzo wysoka | niska–średnia | > Relax NG oferuje **najprostszy formalnie** model spośród trzech języków — jednolity mechanizm "wzorców" zamiast podziału na typy. Dla porównania: DTD omówione w **wykładzie 4**, XML Schema w **wykładach 5–7**. --- ## Zasada działania — wzorce Relax NG opiera się na jednym, uniwersalnym pojęciu: **wzorca** (*pattern*). > **Wzorzec** opisuje dopuszczalną strukturę fragmentu dokumentu — elementy, atrybuty, tekst i ich kombinacje. ### Cechy modelu wzorców - Wszystko jest wzorcem — nie ma osobnych "typów", - Wzorce **składają się** rekurencyjnie (pattern composition), - Schemat to **gramatyka** złożona ze wzorców, - Walidacja = dopasowanie dokumentu do wzorca. ### Przykład podstawowego wzorca ```xml ``` Ten wzorzec oznacza: element o nazwie `name`, zawierający dowolny tekst. --- # Część 2 ## Podstawowe wzorce --- ## Wzorce element, attribute, text, empty Cztery podstawowe wzorce opisują fundament dokumentu XML: | Wzorzec | Znaczenie | Przykład | |---|---|---| | `` | element o danej nazwie | `` | | `` | atrybut o danej nazwie | `` | | `` | dowolny tekst | `` | | `` | brak treści i atrybutów | `` | ### Przykład — prosty dokument **Dokument XML:** ```xml John Smith js@example.com ``` **Schemat Relax NG:** ```xml ``` --- ## Odpowiednik DTD — porównanie Ten sam dokument opisany w DTD: ```xml ]> ``` ### Porównanie zapisu | Element struktury | DTD | Relax NG | |---|---|---| | Element główny | `` | `` | | Powtórzenie (0+) | `card*` | `` | | Sekwencja | `(name, email)` | kolejne wzorce | | Tekst | `#PCDATA` | `` | > Relax NG jest **bardziej rozwlekły** w składni XML, ale **bardziej jednolity** — każda konstrukcja jest wzorcem. --- ## Krotność: zeroOrMore, oneOrMore, optional Relax NG wyraża liczebność przez **wzorce-kontenery**: | Wzorzec | Znaczenie | Odpowiednik DTD | |---|---|---| | `` | zero lub więcej | `*` | | `` | jeden lub więcej | `+` | | `` | zero lub jeden | `?` | | *(brak kontenera)* | dokładnie raz | *(brak)* | ### Przykład — opcjonalny element ```xml ``` > `optional` oznacza, że element `note` **może**, ale nie musi wystąpić. --- ## Przestrzeń nazw Relax NG Wszystkie elementy wzorca należą do przestrzeni nazw: `http://relaxng.org/ns/structure/1.0` ### Dwa sposoby deklaracji **Domyślna przestrzeń nazw:** ```xml ``` **Prefiks:** ```xml ``` > Każdy element wzorca **musi** być kwalifikowany tą przestrzenią nazw — inaczej jest traktowany jako adnotacja (ignorowany). --- # Część 3 ## Wzorce złożone --- ## Wzorzec choice — alternatywa `choice` dopasowuje **jeden** z podanych wzorców: ```xml ``` ### Odpowiednik DTD ```xml ``` ### Znaczenie - `choice` = **albo** `name`, **albo** para `givenName` + `familyName`, - `group` = **grupowanie** (sekwencja), potrzebne, gdy alternatywa dotyczy więcej niż jednego elementu. --- ## Wzorzec group — sekwencja `group` grupuje wzorce w **sekwencję** (wszystkie po kolei): ```xml ``` ### Kiedy group jest konieczny? `group` jest potrzebny, gdy chcemy zgrupować kilka wzorców jako **całość** — np. jako jedną gałąź `choice`. > Bez `group` nie dałoby się wyrazić "albo pojedynczy `name`, albo para `givenName`+`familyName`" — bo `choice` przyjmuje pojedyncze wzorce. --- ## Wzorzec interleave — przeplot `interleave` pozwala elementom potomnym występować w **dowolnej kolejności**: ```xml ``` ### Semantyka interleave Sekwencja elementów pasuje do `interleave`, jeśli jest **przeplotem** (interleavingiem) sekwencji pasujących do wzorców-dzieci. ### Przykład z HTML `` ```xml ``` > `interleave` to cecha **unikatowa** Relax NG — ani DTD, ani XML Schema nie oferują tak elastycznego mechanizmu. --- ## interleave vs łącznik `&` z SGML `interleave` jest **silniejszy** niż łącznik `&` znany z SGML: | Wyrażenie | Dopasuje `A A B`? | Dopasuje `A B A`? | |---|---|---| | `A* & B` (SGML) | ✅ tak | ❌ nie | | `interleave(A*, B)` (Relax NG) | ✅ tak | ✅ tak | > `interleave` pozwala na **pełne przeplatanie** sekwencji, podczas gdy `&` wymaga blokowego ułożenia. --- ## Wzorzec mixed — zawartość mieszana `mixed` to **skrót** dla przeplatania tekstu z innymi wzorcami: ``` p ⟺ p ``` ### Przykład — treść mieszana ```xml ``` > `mixed` naturalnie wyraża treść typu "tekst przeplatany elementami formatującymi" — bez ograniczeń znanych z DTD. --- ## Elementy a atrybuty — kolejność Relax NG zachowuje **rozróżnienie** między elementami a atrybutami: ### Kolejność elementów — istotna ```xml ``` Powyższy wzorzec **nie** dopasuje `......` — elementy muszą być w zadeklarowanej kolejności. ### Kolejność atrybutów — nieistotna Wzorzec `` dopasuje **oba** układy atrybutów (kolejność atrybutów w XML nie ma znaczenia). > Zasada: kolejność **elementów** ma znaczenie, kolejność **atrybutów** nie — zgodnie z modelem XML. --- ## Domyślna zawartość: text vs empty Ważna asymetria między wzorcami `element` i `attribute`: | Wzorzec | Domyślna zawartość | Zapis skrócony | |---|---|---| | `` | `` | `attribute` bez treści = tekst | | `` | **niedozwolone** | element wymaga jawnego wzorca | ### Przykład ```xml ``` > Element bez treści i atrybutów opisuje się jawnie przez ``. Wyjątek: element z samymi atrybutami nie wymaga `` — atrybuty już "wypełniają" wzorzec. --- # Część 4 ## Gramatyki i nazwane wzorce --- ## Wzorce nazwane: grammar, start, define, ref Dla nietrywialnych schematów wygodnie jest **nazywać** części wzorca: ```xml ``` ### Struktura gramatyki | Element | Rola | |---|---| | `` | Kontener gramatyki — jeden `` i zero lub więcej `` | | `` | Wzorzec początkowy (dopasowywany do całego dokumentu) | | `` | Nazwana definicja wzorca | | `` | Odwołanie do nazwanej definicji | > Gramatyka jest dopasowywana przez dopasowanie wzorca w elemencie ``. --- ## Styl zbliżony do DTD Relax NG pozwala pisać gramatyki w stylu przypominającym DTD — każdy element jako osobna definicja: ```xml ``` > Ten styl jest czytelny dla osób przyzwyczajonych do DTD — każda definicja odpowiada jednemu typowi dokumentu. --- ## Odwołania rekurencyjne Relax NG pozwala na **rekurencyjne odwołania** — pod warunkiem, że rekursja jest "przez element": ```xml ``` ### Ograniczenie rekursji Rekurencyjne odwołanie musi **przechodzić przez element**. Poniższa definicja jest **niedozwolona** (rekursja bezpośrednia bez elementu): ```xml ``` > To ograniczenie gwarantuje **rozstrzygalność** gramatyki — zapobiega nieskończonym pętlom. --- # Część 5 ## Typy danych --- ## Wzorzec data — typy danych Relax NG odwołuje się do **zewnętrznych bibliotek typów** (np. W3C XML Schema Datatypes): ```xml ``` ### Atrybuty wzorca data | Atrybut | Rola | |---|---| | `type` | Nazwa typu w bibliotece | | `datatypeLibrary` | URI identyfikujące bibliotekę typów | ### Domyślna biblioteka Atrybut `datatypeLibrary` może być **dziedziczony** — zwykle deklaruje się go na elemencie głównym: ```xml ``` --- ## Ograniczenie: data musi dopasować całość Wzorzec `data` musi dopasować **całą zawartość** elementu lub atrybutu — nie można mieszać `data` z innymi wzorcami treści: ### Niedozwolone ```xml ``` ### Dozwolone ```xml ``` > Ograniczenie to nie dotyczy wzorca `` — tylko `data` i `value` muszą dopasować całość. --- ## Parametry typów danych Typy danych mogą mieć **parametry** przekazywane elementem ``: ```xml 127 ``` ### Zasada - Parametry definiowane są przez **słownik typów** (datatyping vocabulary), - `wartość` jako dziecko elementu `data`. > Dzięki parametrom Relax NG może wyrazić np. "napis o maksymalnej długości 127 znaków" — podobnie jak aspekty w XML Schema. --- ## Wzorzec value — wyliczenia `value` dopasowuje **konkretną wartość** (wyliczenie): ```xml html text ``` ### value vs data | Wzorzec | Znaczenie | |---|---| | `` | **dowolna** wartość danego typu | | `` | **konkretna** wartość danego typu | ### Normalizacja białych znaków Domyślnie `value` porównuje po **normalizacji białych znaków** (usunięcie skrajnych, scalenie środkowych). Aby porównywać dokładnie, użyj `type="string"`: ```xml html ``` > `value type="string"` porównuje **bez** normalizacji — " html " nie dopasuje "html". --- ## Wzorzec list — listy wartości `list` dopasowuje **ciąg tokenów rozdzielonych spacjami**: ```xml ``` ### Warianty **Jeden lub więcej elementów:** ```xml ``` **Parzysta liczba elementów (pary):** ```xml ``` > `list` dzieli napis na tokeny i dopasowuje je do wzorca wewnętrznego — odpowiednik `xsd:list`. --- # Część 6 ## Przestrzenie nazw i klasy nazw --- ## Przestrzenie nazw — atrybut ns Relax NG jest **świadomy przestrzeni nazw** — nazwa elementu/atrybutu składa się z nazwy lokalnej i URI przestrzeni nazw. ```xml ``` ### Dopasuje ```xml ``` ### Nie dopasuje ```xml ``` --- ## Dziedziczenie atrybutu ns Atrybut `ns` jest **dziedziczony** przez elementy potomne: ```xml ``` ### Różnica dla atrybutów Atrybut `ns` **nie jest dziedziczony** przez wzorce `attribute` — domyślnie mają pustą przestrzeń nazw: ```xml ``` > To odzwierciedla fakt, że w XML atrybuty **nie dziedziczą** domyślnej przestrzeni nazw. --- ## Nazwy kwalifikowane Zamiast atrybutu `ns` można używać **prefiksów** w wartości `name`: ```xml ``` ### Zasada Prefiks w `name` **określa przestrzeń nazw** niezależnie od atrybutu `ns`. Domyślna przestrzeń nazw (xmlns) **nie** wpływa na dopasowywanie nazw we wzorcach. --- ## Klasy nazw (name classes) Klasa nazw pozwala dopasować **wiele nazw** naraz. Podstawowe klasy: | Klasa | Znaczenie | |---|---| | `` | dowolna nazwa (lokalna + przestrzeń) | | `` | dowolna nazwa w danej przestrzeni nazw | | `` | konkretna nazwa | | `` | suma klas | | `` | wykluczenie z klasy | ### Przykład — dowolny dokument XML ```xml ``` --- ## Klasy nazw — except i nsName ```xml ``` ### Znaczenie Powyższy wzorzec pozwala elementowi `card` na **dowolną liczbę atrybutów** kwalifikowanych przestrzenią nazw **inną** niż przestrzeń `card` — ale nie z przestrzeni `card` ani bez przestrzeni. ### Zastosowanie klas nazw Klasy nazw umożliwiają **otwartą walidację** (*lax validation*) — pozwalają na "dowolne atrybuty z wyjątkiem tych, które definiujemy ściśle". --- ## Lax validation — przykład z xml:space Problem: chcemy pozwolić na **dowolne atrybuty**, ale jeśli wystąpi `xml:space`, to musi mieć wartość `default` lub `preserve`. ### Rozwiązanie z except ```xml xml:space default preserve ``` > Klasa `anyName` z `except` pozwala wykluczyć `xml:space` z "dowolności", a następnie zdefiniować go **ściśle** osobno. --- # Część 7 ## Modularyzacja --- ## Odwołania zewnętrzne — externalRef `externalRef` odwołuje się do wzorca zdefiniowanego w **osobnym pliku**: ```xml ``` ### Łączenie wzorców z plików ```xml ``` > `externalRef` to prosty mechanizm **wielokrotnego użycia** schematów z osobnych plików. --- ## Łączenie definicji — combine Wiele definicji o tej samej nazwie łączy się atrybutem `combine`: ```xml ``` Jest to równoważne: ```xml ``` ### Wartości combine | Wartość | Znaczenie | |---|---| | `choice` | suma alternatyw (elementy) | | `interleave` | przeplot (zwykle dla atrybutów) | --- ## combine="interleave" dla atrybutów Przy łączeniu atrybutów typowo używa się `interleave`: ```xml ``` Jest to równoważne (dla atrybutów kolejność nie ma znaczenia): ```xml ``` > Zasada: `combine="choice"` dla elementów, `combine="interleave"` dla atrybutów. --- ## Scalanie gramatyk — include `include` scala gramatyki z osobnych plików: ```xml ``` ### Działanie - Definicje z `inline.rng` są **dołączane** do gramatyki, - `combine="choice"` **rozszerza** definicję `inline.class` o nowe elementy. --- ## notAllowed — wzorzec "nic" `notAllowed` **nigdy nic nie dopasowuje** — używany do budowy punktów rozszerzeń: ```xml ``` ### Zastosowanie `inline.extra` jest domyślnie "pusty" (nic nie dopasowuje), ale gramatyka dołączająca może go **rozszerzyć** przez `combine="choice"`: ```xml ``` > `notAllowed` pełni rolę **wtyczki rozszerzeń** — jak punkt zaczepienia dla przyszłych modyfikacji. --- ## Zastępowanie definicji — include z define Element `include` może zawierać `define`, które **zastępują** definicje z dołączanej gramatyki: ```xml ``` ### Zasada - Definicja `cardContent` w `include` **zastępuje** oryginalną, - Analogicznie `start` wewnątrz `include` zastępuje `start` dołączanej gramatyki. --- ## Gramatyki zagnieżdżone — parentRef Relax NG pozwala **zagnieżdżać gramatyki**. `parentRef` ucieka z bieżącej gramatyki do definicji gramatyki **nadrzędnej**: ```xml ``` ### Znaczenie Wzorzec `table.rng` (zagnieżdżona gramatyka) redefiniuje `cell.content`, odwołując się do `inline` z gramatyki **zewnętrznej** — to umożliwia **parametryzację** dołączanych modułów. --- ## Adnotacje Elementy i atrybuty z **innej przestrzeni nazw** niż Relax NG są **ignorowane** — można ich używać jako adnotacji: ```xml Informacja o karcie. ``` ### Element div `div` grupuje definicje (np. w moduły) i przenosi adnotacje: ```xml
... ...
...
``` --- ## Podsumowanie | Temat | Kluczowe wnioski | |---|---| | **Relax NG** | Język schematów oparty na gramatykach regularnych (ISO 19757-2) | | **Dwie składnie** | XML (pełna) i compact (skrótowa) | | **Wzorce** | element, attribute, text, empty, group, choice, optional, zeroOrMore, oneOrMore | | **interleave/mixed** | Unikatowy mechanizm przeplotu — brak odpowiednika w DTD/XSD | | **Gramatyki** | grammar, start, define, ref — nazwane wzorce i rekursja | | **Typy danych** | data (typy zewnętrzne), value (wyliczenia), list (listy) | | **Przestrzenie nazw** | ns, klasy nazw: anyName, nsName, except | | **Modularyzacja** | externalRef, combine, include, notAllowed, parentRef | ### Porównanie trzech języków | | DTD | XML Schema | Relax NG | |---|---|---|---| | **Prostota** | wysoka | niska | średnia | | **Siła wyrazu** | niska | wysoka | wysoka | | **Jednolitość** | — | podział typów | jednolite wzorce | | **Przeplot** | brak | brak | tak | --- # Dziękuję za uwagę **Systemy Zarządzania Treścią** Politechnika Poznańska