Шаблоны проектирования XSD



    В жизни каждого аналитика и программиста наступает такой день, когда он узнает о существовании шаблонов (паттернов) проектирования XML-схем и его жизнь меняется. Для меня, например, с этого знания началось постижение красоты проектирования.

    Сегодня хочу поговорить о том, какие есть шаблоны проектирования XSD, о преимуществах и недостатках каждого, и почему мы для своих задач выбрали «Райский сад».

    Для примера возьмем следующий XML-документ в качестве источника данных.

    <?xml version="1.0" encoding="UTF-8"?>
    <Customer>
       <CustomerId>100</CustomerId>
       <FirstName>Павел</FirstName>
       <LastName>Орлов</LastName>
       <Address>
          <StreetAddress>Угрешская 2</StreetAddress>
          <City>Москва</City>
          <Zip>115088</Zip>
       </Address>
    </Customer>

    И посмотрим, как можно описать одну и ту же структуру XML-документа разными способами.
    В основе разделения на шаблоны лежит принцип определения глобальных элементов и/или типов данных внутри XSD.

    Матрешка (Russian Doll)




    Суть шаблона в том, что схема является зеркалом описываемого ею XML-документа: если сложные элементы содержат внутри себя другие сложные элементы, а те в свою очередь содержат простые, то и в XSD описания таких элементов будут вложены друг в друга. Название шаблон получил в честь известной во всем мире нашей куклы-матрешки, по аналогии с тем, как дочерние элементы в шаблоне инкапсулируются в родительские.

    Схема, описывающая структуру нашего файла-источника с использованием шаблона «Матрешка», выглядит так:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/Customer" xmlns:tns="http://www.example.org/Customer"  elementFormDefault="qualified">
    
        <xsd:element name="Customer">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="CustomerId" type="xsd:int" />
                    <xsd:element name="FirstName" type="xsd:string" />
                    <xsd:element name="LastName" type="xsd:string" />
                    <xsd:element name="Address">
                        <xsd:complexType>
                            <xsd:sequence>
                                <xsd:element name="StreetAddress" type="xsd:string"/>
                                <xsd:element name="City" type="xsd:string"/>
                                <xsd:element name="Zip" type="xsd:string"/>
                            </xsd:sequence>
                        </xsd:complexType>
                    </xsd:element>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    
    </xsd:schema>

    Характеристики шаблона:
    • Непрозрачность содержания. Содержание XSD непрозрачно для других схем, и даже для других частей той же схемы. Вследствие чего ни один из типов или элементов внутри XSD не может быть повторно использован.
    • Скрытые области. Области схемы, в которой определяются локальные элементы («City» и «Zip» в примере), локализованы внутри корневого элемента («Address»). В результате если задать в схеме elementFormDefault = «unqualified», то пространства имен локальных элементов («City» и «Zip») скрыты в пределах схемы.
    • Независимость. При такой конструкции каждый компонент схемы является автономным (т.е. не взаимосвязан с другими компонентами). Следовательно, изменения отдельных компонентов будет иметь ограниченное влияние. Например, если добавить в состав адреса элемент «FlatNumber», это никак не повлияет на другие элементы схемы.
    • Компактность. Благодаря такой конструкции все связанные по смыслу данные объединяются в схеме в автономные компоненты, т.е. компоненты являются компактными.


    Салями (Salami Slice)




    Суть шаблона в том, что описываемый XML-документ разделяется на составные элементы, каждый из которых описывается в XSD как глобальный. Затем описанные элементы соединяются воедино.

    Схема, описывающая структуру файла-источника с использованием шаблона «Салями», выглядит так:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.example.org/Customer"
            xmlns:tns="http://www.example.org/Customer"
            elementFormDefault="qualified">
    
        <xsd:element name="CustomerId" type="xsd:int" />
        <xsd:element name="FirstName" type="xsd:string" />
        <xsd:element name="LastName" type="xsd:string" />
        <xsd:element name="StreetAddress" type="xsd:string"/>
        <xsd:element name="City" type="xsd:string"/>
        <xsd:element name="Zip" type="xsd:string"/>
    
        <xsd:element name="Customer">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element ref="tns:CustomerId" />
                    <xsd:element ref="tns:FirstName" />
                    <xsd:element ref="tns:LastName" />
                    <xsd:element name="Address">
                        <xsd:complexType>
                            <xsd:sequence>
                                <xsd:element ref="tns:StreetAddress" />
                                <xsd:element ref="tns:City" />
                                <xsd:element ref="tns:Zip" />
                            </xsd:sequence>
                        </xsd:complexType>
                    </xsd:element>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
        
    </xsd:schema>

    Характеристики шаблона:
    • Прозрачность содержания. Все элементы могут видеть другие схемы, а также другие компоненты этой XSD.
    • Глобальность. Так как все элементы схемы объявлены глобально, то независимо от значения elementFormDefault пространства имен схемы в XML-документе будет показан весь набор атрибутов (что-то может быть пустым).
    • Взаимозависимость. При такой конструкции сложные элементы ссылаются на другие части схемы, то есть зависят от них. Следовательно, изменение отдельных компонентов могут повлечь обширные изменения всей схемы.
    • Компактность. Благодаря такой конструкции все связанные по смыслу данные объединяются в схеме в автономные компоненты, т. е. компоненты являются компактными.


    Венецианские жалюзи (Venetian Blind)




    Суть шаблона в том, что описываемый XML-документ разделяется на составные типы, каждый из которых описывается в XSD как глобальный. Затем объявляется корневой элемент, соответствующий глобальному типу, соединяющему схему воедино.

    Схема, описывающая структуру файла-источника с использованием шаблона «Венецианские жалюзи», выглядит так:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.example.org/Customer"
            xmlns:tns="http://www.example.org/Customer"
            elementFormDefault="qualified">
    
        <xsd:complexType name="AddressType">
            <xsd:sequence>
                <xsd:element name="StreetAddress" type="xsd:string"/>
                <xsd:element name="City" type="xsd:string"/>
                <xsd:element name="Zip" type="xsd:string"/>
            </xsd:sequence>
        </xsd:complexType>
        
        <xsd:complexType name="CustomerType">
            <xsd:sequence>
                <xsd:element name="CustomerId" type="xsd:int" />
                <xsd:element name="FirstName" type="xsd:string" />
                <xsd:element name="LastName" type="xsd:string" />
                <xsd:element name="Address" type="tns:AddressType" />
            </xsd:sequence>
        </xsd:complexType>
        
        <xsd:element name="Customer" type="tns:CustomerType" />
    
    </xsd:schema>

    Характеристики шаблона:
    • Прозрачность содержания. Типы данных видны из других схем, а также видны компонентам этой XSD.
    • Максимальное скрытие имен. Объявления элементов локальны, поэтому шаблон имеет максимальный потенциал для скрытия имен.
    • Простое управление скрытием пустых атрибутов. Если пространства имен скрыты, то показывать или нет пустые атрибуты в документах управляется одним переключателем elementFormDefault.
    • Взаимозависимость. При такой конструкции сложные типы данных ссылаются на другие части схемы, то есть зависят от них. Следовательно, изменение отдельных компонентов могут повлечь обширные изменения всей схемы.
    • Компактность. Благодаря такой конструкции все связанные по смыслу данные объединяются в схеме в автономные компоненты, т. е. компоненты являются компактными.


    Райский сад (Garden of Eden)




    «Райский сад» хорош тем, что определяет каждый элемент и составной тип данных как глобальный. Это позволяет ссылаться на любой тип или элемент в пределах одного XSD или из любой другой XSD и даже из WSDL. Только так можно полностью контролировать семантику и типов и элементов.

    Схема, описывающая структуру файла-источника с использованием шаблона «Райский сад», выглядит так:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.example.org/Customer"
            xmlns:tns="http://www.example.org/Customer"
            elementFormDefault="qualified">
        
        <xsd:element name="CustomerId" type="xsd:int"/>
        <xsd:element name="FirstName" type="xsd:string"/>
        <xsd:element name="LastName" type="xsd:string"/>
        <xsd:element name="StreetAddress" type="xsd:string"/>
        <xsd:element name="City" type="xsd:string"/>
        <xsd:element name="Zip" type="xsd:string"/>
    
        <xsd:element name="Address" type="tns:AddressType"/>
        <xsd:element name="Customer" type="tns:CustomerType"/>
    
        <xsd:complexType name="AddressType">
            <xsd:sequence>
                <xsd:element ref="tns:StreetAddress"/>
                <xsd:element ref="tns:City"/>
                <xsd:element ref="tns:Zip"/>
            </xsd:sequence>
        </xsd:complexType>
          
        <xsd:complexType name="CustomerType">
             <xsd:sequence>
                 <xsd:element ref="tns:CustomerId"/>
                 <xsd:element ref="tns:FirstName"/>
                 <xsd:element ref="tns:LastName"/>
                 <xsd:element ref="tns:Address"/>
             </xsd:sequence>
        </xsd:complexType>
    
    </xsd:schema>

    Характеристики шаблона:
    • Максимальная прозрачность содержания. И типы, и элементы данных видны из других схем, а также видны компонентам этой XSD.
    • Максимальное раскрытие имен. Ничего локально не определяется, поэтому видимость имен максимальная.
    • Взаимозависимость. При такой конструкции сложные типы данных и элементы ссылаются на другие части схемы, то есть зависят от них. Следовательно, изменение отдельных компонентов могут повлечь обширные изменения всей схемы.
    • Громоздкость. Связанные по смыслу данные «размазаны» по определению типа и элемента. «Читать» такую схему сложнее.


    Выбор шаблона


    При выборе шаблона важно учитывать несколько критериев:
    1. Насколько возможно повторное использование компонентов схемы;
    2. Насколько легко со схемой работать;
    3. Насколько компоненты схемы должны быть взаимозависимы или независимы.


    Часто при выборе шаблона проектирования приходится искать баланс между возможностью повторно использовать компоненты схемы и глубиной взаимосвязи между компонентами. На рисунке показан потенциал каждого из шаблонов в разрезе этих двух аспектов.



    Те схемы, в которых хорошо поддерживается повторное использование компонентов, с другой стороны имеют сильные взаимосвязи между компонентами. При необходимости что-то поменять в такой схеме разработчик схемы может столкнуться с тем, что менять придется много связанных элементов и/или типов. Такими схемами впоследствии трудно управлять.

    В целом можно вывести следующие правила выбора шаблона:
    • если повторное использование компонентов схемы не является необходимым, если важнее удобство использования XSD разработчиками, и строгой необходимости контролировать имена компонентов нет, то следует выбирать «Матрешку»;
    • если повторное использование компонентов важнее удобства для разработчиков, а имена элементов данных нужно контролировать в пределах всей системы, то следует выбирать «Салями»;
    • если вдобавок к предыдущему пункту важно контролировать наименования типов данных и иметь возможность повторно использовать типы данных, следует выбирать «Райский сад»;
    • «Венецианские жалюзи» подойдут в случае, если важно и повторное использование компонентов, и свобода в определении их локальных имен (или возможность скрыть их внутри схемы).


    Нам в проекте важнее всего было повторное использование типов и элементов схемы и во вторую очередь тотальный семантический контроль имен. Выбор шаблона был очевиден – Райский сад.

    Небольшое лирическое отступление. Самым интересным применением шаблонов проектирования XML-схем на моей памяти был и остается гипноз аудитории. Один наш титулованный аналитик любит брать инициативу в свои руки через рассказ на эту тему. Засекала время, через 5 минут взгляд слушателей тускнеет, и они уходят куда-то далеко в себя. На «Райском саде» сознание большинства отключается.

    И в заключении хочу добавить, что миксы шаблонов тоже возможны, мы с ними встречались.

    Источники и ресурсы:
    XML-Schema спецификация
    Schema scope: Primer and best practices
    Introducing Design Patterns in XML Schemas
    • +11
    • 26,7k
    • 4
    ООО «ЦИТ»
    54,00
    ИКТ-решения и сервисы для органов власти и бизнеса
    Поделиться публикацией

    Комментарии 4

      +1
      Очень интересный материал на самом деле, удивлен, что в статье нет никакой активности.
      Мы под свои нужды используем «матрешку».
        0
        Читал о шаблонах в xsd в samolisov.blogspot.ru/2013/01/xml.html Там, кстати, «Райского сада» нет.
        Соглашусь, тема вообще интересная — я когда xsd писал не подозревал о существовании шаблонов в такой, вроде бы простой, области. Сам использовал «Венецианское жалюзи» — удобно при описании больших типов со вставкой комментариев. Если «Матрёшку» использовать, то будет большой тип, в котором сложно ориентироваться, в моём случае.
          0
          Тема довольно давняя, но когда я начинала ее раскапывать (года полтора назад), с удивлением обнаружила, что у нас в рунете совсем нет по ней ничего. Все что есть — переводы. Возможно это связано с нашим менталитетом, который в принципе не любит шаблоны. Или не знаю еще с чем.
          0
          Вообще не знал о шаблонах проектирования применительно XSD :) но оказывается использовал «Венецианские жалюзи» и «Райский сад». Хотя имена конечно так себе

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое