Кажется, что для пользователей, которые хотят использовать XML-схему для проверки XML-документа на соответствие контракту, определение производных сложных типов посредством расширений является отличным способом разложить на компоненты аспекты схемы и повторно воспользоваться ими. Однако, первое впечатление обманчиво - взаимодействие с другими конструкциями XML-схемы W3C, как, например, группами подстановки (
) и
, превращает использование определения производных сложных типов посредством расширений в разряд трудно контролируемых задач. Рассмотрим, например, следующее объявление элемента:
<xs:element name="xml-deviant" type="XML-Deviant" />
в котором объявляется элемент xml-deviant, тип которого, XML-Deviant, является сложным типом, описанным в приведенной выше схеме. Оба XML-элемента, приведенные в следующем фрагменте, являются допустимыми в соответствии с этим объявлением элемента xml-deviant:
Несмотря на то, что в объявлении этого элемента явно указано, что типом элемента xml-deviant является сложный тип XML-Deviant, экземпляр может замещать это объявление в схеме, используя атрибут xsi:type, при условии, что этот новый тип является подтипом первоначального типа. Это означает, что по умолчанию даже если элемент успешно прошел проверку на допустимость, он необязательно соответствует модели содержания, по которой, как полагает получатель, он проверяется. Схожая проблема возникает, когда рассматриваемое объявление элемента назначается заголовком (head) групп подстановок.
Существует два способа обойти эту потенциальную проблему, возникающую при определении производных сложных типов посредством расширений. Первый заключается в блокировании подстановки или определении производного типа посредством размещения атрибута block или final в объявлении элемента или в описании сложного типа. Аналогично, атрибут blockDefault или finalDefault может быть добавлен в элемент xs:schema для указания, какой вид подстановок или определения производных типов неразрешен в этой схеме. Второй способ состоит в использовании поименованных групп моделей (xs:group) и групп атрибутов для разбиения схемы на модули - как альтернатива определению производных сложных типов посредством расширений. Ниже приведена схема, которая была рассмотрена в предыдущем раздела и в которую были добавлены поименованные группы моделей.
Для сценариев использования, которые применяют строго типизированные XML-документы, определение производных сложных типов посредством расширений представляет хотя и отличный, но родственный ряд проблем. В случае, если XML-схема используется в качестве основы преобразования между XML и объектно-ориентированной или реляционной моделями, такое определение производных сложных типов не оказывается проблематичным. Однако, при обработки таких строго типизированных XML-документов с помощью языков программирования, поддерживающих схему, как, например,
for $x in //xml-deviant return $x/signature
С одной стороны, это выражение должно привести к статической ошибке, поскольку элемент xml-deviant объявлен как элемент типа XML-Deviant, который не содержит элемент signature. С другой стороны, поскольку у XML-Deviant существует подтип, у которого в модели содержания есть элемент signature и который, следовательно, мог бы быть адресатом директивы xsi:type, это ошибка не должна расцениваться как статическая. Обе позиции являются допустимыми, но независимо от того, что выберет XQuery, всегда найдутся люди, которые будут ожидать противоположенное. Разработчики, знакомые с XPath, могут решить, что этот запрос будет работать, в то время как, те, кто освоился со статически типизированными языками, посчитает его эквивалентом следующего выражения и, таким образом, ошибкой:
foreach(xmldeviant b in list) { yield b.signature; // static type error. }
Чтобы предотвратить эту и другие родственные проблемы, самое лучше - это постараться не использовать определение производных сложных типов посредством расширений, если XML-документ будет обрабатываться с помощью языка обработки, поддерживающего XML-схему, как, например, XQuery.
Заключение
С учетом нынешнего уровня развития технологий возможность определения производных сложных типов в соответствии с положениями XML-схемы W3C скорее добавит сложности, а не упростит ситуацию в двух наиболее общих случаях использования схемы. Для сценариев проверки допустимости документов получение производных типов посредством ограничений имеет минимальную ценность, но получение производных типов посредством расширений - это удобный способ применить модульный подход и воспользоваться принципом повторного использования. Однако, следует внимательно изучить последствия использования подстановок различных типов (xsi:type и группы подстановок) при определении производных типов посредством расширения в сценариях, задействованных в проверке допустимости документа.
В настоящий момент обработка и хранение строго типизированных XML-данных - это удел традиционных объектно-ориентированных языков программирования и реляционных баз данных. Это означает, что определенные возможности XML-схемы W3C, такие как получение производного типа посредством ограничения (и в меньшей степени определение производного типа посредством расширения) являются причиной возникновения несоответствия между системой типов, используемых для описания строго типизированного XML-документа, и механизма, применяемого для обработки и хранения вышеупомянутого XML. В конечном счете, когда такие технологии, как XQuery, получат широкое распространение как средство обработки и поддержки типизированных XML-документов, а XML-схема W3C будет интегрирована в основные продукты баз данных, это несоответствии перестанет быть существенным. Но до этого момента необходимо тщательно продумывать, применять ли определение производных сложных типов в ситуациях, в которых XML-схема W3C используется главным образом как механизм создания аннотированных информационных наборов типов XML.
Благодарности
Автор хотел бы поблагодарить Дона Бокса (Don Box), Криса Ловетта (Chris Lovett) и Эрика Мейджера (Erik Meijer) за их идеи и помощь, предоставленные при написании этой статьи.