XML Schema jest bodajże najlepszym sposobem walidacji dokumentów XML. Model zastosowany w przypadku tego meta-języka pozwala na tworzenie złożonych konstrukcji. W oparciu o niego można budować własne rozszerzenia czy też zagnieżdżać w sekcjach xsd:appinfo dodatkowe metadane. Dzisiaj jednak nie o tym, a o wzorcach projektowych. Sam się zdziwiłem gdy trafiłem na artykuł Introducing Design Patterns in XML Schemas. W życiu się nie zastanawiałem czy to co piszę w XSD ma coś wspólnego z wzorcami czy nie. Sun wyprzedził w tym momencie chyba wszystkich. :-)
Wzorce, które zostały wymienione we wspomnianym artykule odnoszą się do powiązania definiowanych typów z definiowanymi elementami. Ciężko mi się zgodzić z tym, że wybór wzorca jest krytyczny przy projektowaniu schematu, ponieważ schemat zazwyczaj ma przeznaczenie już w chwili pisania i zazwyczaj nie możemy powiedzieć, zrobimy to wzorcem X, ponieważ sam nasuwa się wzorzec Y. Ale to tak tylko moim zdaniem.
Tabelka poniżej prezentuje zawartość przeniesioną ze strony Suna. Zawiera ona 4 najpopularniejsze wzorce. Dwa najczęściej spotykane w internecie to Venetian Blind oraz Garden of Eden ze względu na to, że są bardzo podatne na ponowne użycie. WzorzecCharakterystykaRussian Doll, przykładZawiera jeden element globalny, pozostałe są lokalne.
-
Jest tylko jeden poprawny element.
-
Może uprościć przestrzeń nazw poprzez zastosowanie atrybutu elementFormDefault dla elementu xsd:schema.
-
Nadaje się tylko dla pojedynczych schematów.
-
Pozwala na ponowne użycie tylko całej gałęzi, a nie każdego typu z osobna.
Salami Slice, przykładWszystkie elementy są globalne, stąd każdy może być użyty w charakterze root node’a.
-
Wszystkie elementy można ponownie użyć.
-
Łatwe wiązanie schematów pomiędzy plikami.
-
Powoduje większą złożoność w przestrzeni nazw.
-
Trudny do określenia root.
Venetian Blind, przykładPochodna Russian Doll, zawiera jeden element globalny, pozostałe są lokalne
-
Zawiera tylko jeden element nadrzędny.
-
Pozwala na ponowne użycie wszystkich typów oraz elementu nadrzędnego.
-
Łatwa praca z wieloma plikami.
-
Ograniczona enkapsulacja poprzez ekspozycję wszystkich typów.
Garden of Eden, przykładPołączenie Venetian Blind oraz Salami Slice. Wiele elementów globalnych, wiele typów publicznych. Wiele kandydatów na root node.
-
Pozwala ponownie użyć elementy oraz typy.
-
Łatwa praca z wieloma plikami.
-
Zawiera wiele potencjalnych elementów nadrzędnych.
-
Ograniczona enkapsulacja.
-
Trudna do czytania i zrozumienia.
Źródło: Sun Developers Network
Przykłady
Russian Doll
[sourcecode lang=“xml”]<xsd:schema xmlns:xsd=“http://www.w3.org/2001/XMLSchema" targetNamespace=“http://schemas.sun.com/point/russiandoll" xmlns:tns=“http://schemas.sun.com/point/russiandoll" elementFormDefault=“qualified”>
<xsd:element name=“Line”> xsd:complexType xsd:sequence <xsd:element name=“PointA”> xsd:complexType <xsd:attribute name=“x” type=“xsd:integer”/> <xsd:attribute name=“y” type=“xsd:integer”/> </xsd:complexType> </xsd:element> <xsd:element name=“PointB”> xsd:complexType <xsd:attribute name=“x” type=“xsd:integer”/> <xsd:attribute name=“y” type=“xsd:integer”/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>[/sourcecode]
Salami Slice
[sourcecode lang=“xml”]<xsd:schema xmlns:xsd=“http://www.w3.org/2001/XMLSchema" targetNamespace=“http://schemas.sun.com/point/salami" xmlns:tns=“http://schemas.sun.com/point/salami" xmlns=“http://schemas.sun.com/point/salami" elementFormDefault=“qualified”>
<xsd:element name=“PointA”> xsd:complexType <xsd:attribute name=“x” type=“xsd:integer”/> <xsd:attribute name=“y” type=“xsd:integer”/> </xsd:complexType> </xsd:element>
<xsd:element name=“PointB”> xsd:complexType <xsd:attribute name=“x” type=“xsd:integer”/> <xsd:attribute name=“y” type=“xsd:integer”/> </xsd:complexType> </xsd:element>
<xsd:element name=“Line”> xsd:complexType xsd:sequence <xsd:element ref=“PointA”/> <xsd:element ref=“PointB”/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>[/sourcecode]
Venetian Blind
[sourcecode lang=“xml”]<xsd:schema xmlns:xsd=“http://www.w3.org/2001/XMLSchema" targetNamespace=“http://schemas.sun.com/point/venetianblind" xmlns:tns=“http://schemas.sun.com/point/venetianblind" xmlns=“http://schemas.sun.com/point/venetianblind" elementFormDefault=“qualified”>
<xsd:complexType name=“PointType”> <xsd:attribute name=“x” type=“xsd:integer”/> <xsd:attribute name=“y” type=“xsd:integer”/> </xsd:complexType>
<xsd:element name=“Line”> xsd:complexType xsd:sequence <xsd:element name=“PointA” type=“PointType”/> <xsd:element name=“PointB” type=“PointType”/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> [/sourcecode]
Garden of Eden
[sourcecode lang=“xml”]<xsd:schema xmlns:xsd=“http://www.w3.org/2001/XMLSchema" targetNamespace=“http://schemas.sun.com/point/gardenofeden" xmlns=“http://schemas.sun.com/point/gardenofeden" elementFormDefault=“qualified”>
<xsd:complexType name=“PointType”> <xsd:attribute name=“x” type=“xsd:integer”/> <xsd:attribute name=“y” type=“xsd:integer”/> </xsd:complexType>
<xsd:complexType name=“LineType”> xsd:sequence <xsd:element ref=“PointA”/> <xsd:element ref=“PointB”/> </xsd:sequence> </xsd:complexType>
<xsd:element name=“PointA” type=“PointType”/>
<xsd:element name=“PointB” type=“PointType”/>
<xsd:element name=“Line” type=“LineType”/> </xsd:schema> [/sourcecode]