XML Schema Design Patterns

14 Jun
2011

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.

Wzorzec Charakterystyka
Russian Doll, przykład Zawiera 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ład Wszystkie 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ład Pochodna 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ład Połą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

<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>

Salami Slice

<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>

Venetian Blind

<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>

Garden of Eden

<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>

Comment Form

top