- 3 декабря 2003 г.
Управление версиями XML-словарей
Третья статья посвящена одной из важнейших проблем разработки XML-схем -
управлению версиями.
Введение
Язык XML предназначен для создания языков, основанных на самодокументированной разметке. Неизбежное развитие этих языков называется управлением версиями. Управление версиями подразумевает добавление, удаление или изменение частей языка. На практике управление версиями - это чрезвычайно сложная задача в теории вычислительной техники, имеющая длинную историю безуспешных проб и ошибок. Можно утверждать, что одна из причин невероятного роста популярности "Всемирной паутины" заключается в том, что развитие языков и управление версиями были встроены в заголовки HTML и HTTP, каждый из которых предоставляет явные точки и правила расширяемости, необходимые для понимания расширений, сделавших возможным их децентрализованное расширение и управление версиями.
Спецификация "Пространства имен XML" обеспечивает идеальный механизм идентификации версий языков, и все языки XML-схемы - такие как W3C XML Schema - предусматривают управляемую расширяемость.
В этой статье описываются подходы, позволяющие добиться более эффективной слабой связи между системами за счет расширения возможности вносить изменения, обеспечивающие обратную и прямую совместимость (backwards- and forwards-compatible changes) при развитии связанных систем. Эти приемы предназначены для совместимых изменений как при передаче схемы, так и без ее распространения. Для управления версиями XML-словарей определяется набор правил, в которых используются конструкции спецификаций "Пространства имен XML" и "XML Schema". Этот набор включает правила для работы с языками, которые предоставляют расширяемую модель контейнера, особенно SOAP. Этот совокупный набор правил называется моделью расширяемости "Обязательно игнорировать" ("Must Ignore" pattern). Как ни странно, но несмотря на то, что эта модель в значительной степени способствовала признанию тегов HTML и заголовков HTTP, среди практиков-разработчиков XML-приложений она не снискала широкую популярность. Данная статья призвана исправить эту ситуацию в отношении существующих программных оболочек, предназначенных для проверки допустимости документов по схеме. В последующих материалах будут рассмотрены оболочки, в которых реализуется более новый подход к проверке допустимости - нестрогая проверка.
Определение совместимости
Определения обратной и прямой совместимости можно найти в Бесплатном он-лайн словаре по вычислительной технике FOLDOC [1]. В этой статье эти определения переосмысливаются с позиции инициатора сообщений, а именно: отправителей и получателей, а не клиентов и серверов. Итак, обратная совместимость означает, что при установке новой версии получателя существующая версия отправителя не будет разрушена. Другими словами, отправитель посылая старую версию сообщения получателю, который понимает новую версию, может быть уверен, что его сообщение успешно обработано. Прямая совместимость означает, что более старая версия получателя может использовать более новые сообщения и при этом не останавливаться. Разумеется, эта более старая версия не реализует новое поведение, но отправитель может посылать более новую версию сообщения, и это сообщение будет успешно обработано.
Другими словами, обратная совместимость подразумевает, что существующие отправители могут использовать сервисы, которые были модернизированы, а прямая совместимость означает, что более новые отправители могут продолжать использовать существующие сервисы.
Изменения, поддерживающие прямую совместимость, обычно приводят к добавлению необязательных элемент(ов) и/или атрибут(ов). Цена внесения изменений, которые не обеспечивают обратную или прямую совместимость, зачастую очень высока, обычно для того, чтобы адаптировать программный продукт к новой версии, необходимо провести его модернизацию. Правила, описанные ниже, оптимизированы для изменений, согласующихся с обратной и прямой совместимостью. В этой статье доказывается, что это не означает изменения имени пространства имен или имен элементов.
Хотя совместимость определяется для отправителя и получателя отдельного сообщения, в большинстве спецификаций Web-сервисов содержатся определения входных и выходных данных. В соответствии с этими определениями, Web-сервис, который усовершенствует свою выходную схему, считается новым получателем. В результате при применении определений совместимости к выходным сообщениям пара терминов отправитель/получатель для входных сообщений меняется местами. Если получатель модернизирует схему выходного сообщения, то он "отправляет" более новую версию сообщения, и, следовательно, он считается "отправителем".
Идентификация и расширение языков
Встраивание расширяемости в языки обычно приводит к системам, которые являются более свободно связанными. Расширяемость позволяет отправителям изменять экземпляры без необходимости следовать централизованным нормативам. Таким образом, первое правило, касающееся расширяемости - это:
1. Правило "Расширяемость допускается": языки ДОЛЖНЫ быть предназначены для расширяемости |
Основное требование, предъявляемое к расширяемости, это возможность определять язык, состоящий из элементов и атрибутов. Пространства имен XML обеспечивают технологию связывания URI (Uniform Resource Identifier, универсальный идентификатор ресурса) c именем XML-элемента или атрибута, то есть задают язык этого имени. В результате, также удается избежать конфликта имен.
Спецификация "W3C XML Schema" предоставляет конструкцию, называемую групповой символ (wildcard), <xs:any>, позволяющую проверять, где допускаются элементы из определенного пространства имен. Групповой символ означает, что элементы в указанном пространстве имен допустимы в реальных документах там, где находится групповой символ. Благодаря этому можно четко определять расширения схем. Получатели расширенных документов могут устанавливать и, в зависимости от модели обработки расширений, без риска игнорировать расширения, которые они не понимают.
<xs:any> использует атрибут namespace, чтобы проверять, из каких пространств имен поступают элементы расширения. Основные значения этого атрибута - ##any, которое означает, что схему можно расширить, используя элемент из любого возможного пространства имен; ##other, который допускает только элементы расширения из пространств имен, отличных от текущего; ##targetnamespace, допускает только элементы расширения из текущего пространства имен.
<xs:any> использует атрибут processContents, чтобы контролировать, как XML-парсер проверяет на допустимость расширенные элементы. Возможные методы: "lax" ("нестрогий") - допускающий проверку, "strict" ("строгий") - требующий проверки, "skip" ("пропустить") - позволяющий ее пропустить. В этой статье используется нестрогая проверка, поскольку это наиболее гибкий и типичный выбор для спецификаций Web-сервисов.
Основная цель модели "Необходимо пропускать" - разрешить внесение в документы изменений, обеспечивающих обратную и прямую совместимость. Как минимум, это не подразумевает ни добавления имен пространств имен, ни изменения имен элементов. Добавление имен элементов в целевое пространство имен (target namespace) может быть выполнено с пространством имен ##any или комбинацией пространства имен ##other и целевого пространства имен словаря.
Приведем ряд примеров, демонстрирующих это правило. Предположим, что заказ на поставку (purchase order) пересылается с одной машины на другую. В результате обработки этого заказа появляется сообщение "отгружено" ("shipped"). Однако, это сообщение могло быть отправлено спустя какое-то время после получения заказ на поставку. Было бы желательно, чтобы программное обеспечение, осуществляющее отправку, могло бы подождать ответ произвольное время (синхронный обмен сообщениями). Предпочтительная модель для получателя - иметь возможность самостоятельно отправить сообщение "отгружено", не заставляя отправителя ждать. Получатель "перезванивает" первоначальному отправителю - отсюда происходит термин "обратный вызов" ("callback"). Отправитель предоставляет получателю адрес в виде адреса обратного вызова. Он указывает адрес, который получатель должен использовать для отправки отправителю любых последующих сообщений. В случае Web-сервисов этот обратный вызов обычно отравляется в виде блока SOAP Header.
Предпочтительным вариантом было бы применение расширяемого стиля ##any. Ниже приведен тип CallbackType (тип обратного вызова), который использует эту модель:
Пример 1. Схема, в которой для расширяемости используется ##any
<s:complexType name="CallbackType">
<s:sequence>
<s:element name="callbackLocation" type="s:anyURI"
minOccurs="1" maxOccurs="1"/>
<s:any processContents="lax" minOccurs="0"
maxOccurs="unbounded" namespace="##any"/>
</s:sequence>
<s:anyAttribute/>
</s:complexType>
Однако, функционированию этой модели препятствуют описанные ниже детерминистических ограничения XML-схемы W3C. Проблема возникает при добавлении необязательного элемента в последующую версию обратного вызова. В качестве примера можно привести время простоя. Время простоя обратного вызова - это ценная информация для получателя. Либо получатели могут продолжить обработку, если они не понимают время простоя. Приведенная ниже схема - это приблизительно то, что желательно создать для использования групповых символов, но она неправомерна из-за детерминистических ограничений:
Пример 2. Неправомерная схема
<s:complexType name="CallbackType">
<s:sequence>
<s:element name="callbackLocation" type="s:anyURI"
minOccurs="1" maxOccurs="1"/>
<s:element name="expires" type="s:dateTime"
minOccurs="0" maxOccurs="1"/>
<s:any processContents="lax" minOccurs="0"
maxOccurs="unbounded" namespace="##any"/>
</s:sequence>
<s:anyAttribute/>
</s:complexType>
Поскольку эта модель не работает, требуется создание модели схемы, которая является грубым эквивалентом, необходимым для достижения первоначальной цели. Чтобы разрешить новые расширения в том же самом пространстве имен, разработчик схемы должен создать тип расширения, который разрешает расширения в том же пространстве имен. Чтобы разрешить надлежащее управление версиями определений языка XML, необходимы еще два правила: первое - для пространства имен:
2. Правило "Любое пространство имен": уровень расширяемости ДОЛЖЕН предусматривать расширения в любом пространстве имен. Для приложений XML-схемы точка расширяемости ДОЛЖНА быть элементом, который разрешает расширение в целевом пространстве имен, и групповым символом, который разрешает расширения в любом другом пространстве имен. |
Второе правило - допущение расширяемости:
3. Правило "Полная расширяемость": все XML-элементы ДОЛЖНЫ разрешать расширяемость элемента после определения элемента и допускать любые атрибуты. |
Ниже приведен пример типа Callbacktype, который выполняет эти требования:
Пример 3. Тип Callback с расширяемостью
<s:complexType name="CallbackType">
<s:sequence>
<s:element name="callbackLocation" type="s:anyURI"
minOccurs="1" maxOccurs="1"/>
<s:element name="Extension" type="wscb:ExtensionType"
minOccurs="0" maxOccurs="1"/>
<s:any processContents="lax" minOccurs="0"
maxOccurs="unbounded" namespace="##other"/>
</s:sequence>
<s:anyAttribute/>
</s:complexType>
<s:complexType name="ExtensionType">
<s:sequence>
<s:any processContents="lax" minOccurs="1"
maxOccurs="unbounded" namespace="##targetnamespace"/>
</s:sequence>
<s:anyAttribute/>
</s:complexType>
Поскольку каждое расширение в целевом пространстве имен находится внутри элемента Extension, каждое последующее пространство имен будет увеличивать вложенность на один уровень. Хотя такой уровень вложенности на расширение нежелателен, это то, что сегодня можно сделать при задании строгой проверки на допустимость по XML-схеме W3C. Кажется, что наличие многочисленных вложенных элементов оправдано, если в язык могут быть внесены многократные совместимые исправления. Этот прием позволяет выполнить проверку допустимости расширений в целевом пространстве имен при сохранении проверки допустимости самого целевого пространства имен.
В общем расширение может быть определено с помощью новой спецификации, в которой указывается нормативная ссылка на более раннюю спецификацию, а затем определяется новый элемент. На самом деле основной смысл в проектировании пространств имен XML - разрешить децентрализованные расширения. Неизбежным следствием является необходимость получения разрешения для расширений в том же пространстве имен. У пространства имен есть владелец, поэтому изменение смысла чего-либо не владельцами пространства имен может привести к нежелательным результатам.
Понимание расширений
В идеале отправители должны уметь расширять существующие XML-документы новыми элементами, не вынуждая при этом получателей изменять существующие реализации. Расширяемость - первый шаг на пути достижения этой цели, но для обеспечения совместимости также требуется модель обработки расширений. Поведение программного обеспечения при его взаимодействии с расширением должно быть четким. Таким образом, можно задать следующее правило:
4. Правило "Обеспечение модели обработки": языки ДОЛЖНЫ устанавливать модель обработки для взаимодействия с расширениями. |
Самая простая модель обработки, которая реализует совместимые изменения, заключается в игнорировании содержания, которое непонятно. Ниже приведено соответствующее правило:
5. Правило "Обязательно игнорировать": получатели документа ОБЯЗАНЫ игнорировать любые XML-атрибуты и элементы в допустимом XML-документе, которые они не распознают. |
Это правило не требует, чтобы элементы были физически удалены - они должны быть только пропущены при обработке. У правила "Обязательно игнорировать" длинные исторические корни. HTML 1.1, 2.0 и 3.2 следуют этому правилу; в этих языках установлено, что любой неизвестный начальный или конечный тег не отображается во процессе преобразования в символы. В HTTP 1.1 [6] указано, что получатель должен пропускать любой заголовок, который он не понимает: "Нераспознанные поля заголовков ДОЛЖНЫ быть пропущены получателем и ОБЯЗАНЫ быть пересланы прозрачными представителями (proxy)". Впервые правило "Обязательно игнорировать" появилось в 1997г., оно было введено рабочей группой WebDAV [19] в разделе 14 спецификации RFC 2518 [5] (Запрос на комментарии), а затем опубликовано отдельным документов - "Гибкий профиль обработки XML-документов" (Flexible XML Processing Profile [2]).
С обработкой расширений связаны два больших типа словарей. Эти типы являются приложениями (документами), ориентированными на данные и предназначенными для презентации. Для ориентированных на данные приложений, таких как Web-сервисы, это правило имеет следующий вид:
6. Правило "Обязательно игнорировать все": правило "Обязательно игнорировать" применяется к нераспознанным элементам и их потомкам. |
Например, если сообщение получено с нераспознанными элементами в блоке SOAP header, они должны быть пропущены, если только не помечены как "mustUnderstand" (см. ниже правило 10), однако допустимо предположить, что нераспознанные элементы могут быть записаны в лог-файл.
Возможно, что для словарей, ориентированных на документы, необходимо другое правило, поскольку приложение обычно пытается представить содержание неизвестного элемента. Ниже приведено правило для приложений, ориентированных на документы:
7. Правило "Обязательно игнорировать контейнер": правило "Обязательно игнорировать" применяется только к нераспознанным элементам. |
В результате потомки элементов сохраняются, например, с целью отображения.
Вместо игнорирования нераспознанных элементов язык может обеспечить иную модель для обработки расширений. Такая модель может заключаться в том, что получатель генерирует ошибку, если он обнаруживает компонент, который не понимает. В качестве примера можно привести спецификацию безопасности, согласно которой получатель должен понимать любое расширение. Для этого случая характерен существенный недостаток, поскольку внесение совместимых изменений в язык не допускается, а такие изменения не могут быть проигнорированы. Еще одна модель - это модель нейтрализация неисправности (fallback), в которой в случае, если получатель не понимает расширения, предлагается альтернативные элементы. XSLT 2.0 обеспечивает такую модель.
Управление версиями
Если требуется новая версия языка, и она обратно совместима с более старым языком, разработчик схем должен принять решение об имени пространства имен для имен в новом языке. В этом случае имеется два варианта: создать новое имя пространства имен или воспользоваться существующим. По нашему мнению, повторное использование более результативно, но мы рассмотрим и выбор №1 в разделе "новое пространство имен". Правило для повторного использования пространств имен может быть сформулировано следующим образом:
8. Правило "Повторного использования имен пространств имен": если в спецификацию могут быть внесены изменения, обеспечивающие обратную совместимость, НЕОБХОДИМО использовать старое имя пространства имен вместе с моделью расширения XML. |
Отсюда можно сделать важный вывод о том, что новое имя пространств имен необходимо только тогда, когда внесено несовместимое изменение.
9. Правило "Повторного использования пространств имен": новое имя пространства имен используется, если обратная совместимость недопустима, то есть программное обеспечение ОБЯЗАНО приостановиться, если оно не понимает новые конструкции языка. |
Изменения, не поддерживающие обратную совместимость, обычно возникают в следующих двух ситуациях: при добавлении требуемой информационной единицы или изменении семантики существующей информационной единицы.
Приведенное выше правило требует соблюдения правил "Обязательно игнорировать" и "Любое пространство имен". Если требования этих правил не выполнены, разработчик языка оказывается лишенным возможности вносить совместимые изменения и повторно использовать имя пространства имен.
Выше отмечалось, что повторное использование имен пространств имен для совместимых расширений - хорошая практика. Противоположенный подход состоит в том, что владелец пространства имен мог бы использовать новое имя для совместимых изменений, предоставив точки расширяемости, допускающие другие пространства имен - xs:any namespace="##other". Этот подход проблематичен - расширение в другом пространстве имен означает, что комбинированная схема не может быть проверена полностью. Точнее, невозможно создать новую схему, которая ограничивает групповой символ. Предположим, например, что ns1 содержит foo и bar. В этом случае просто используя ограничения XML-схемы W3C, невозможно взяв схему SOAP - пример схемы с групповым символом - потребовать, чтобы элемент ns1:foo был бы потомком элемента заголовка, а ns1:bar не был бы потомком элемента заголовка. Действительно, потребность в такой возможности "взывает" к функциональности WSDL (Web Services Description Language, язык описания Web сервисов). Применение подхода с новым именем пространства имен имеет своим результатом спецификации и пространства имен, которые расчленены неподходящим образом, поскольку связанные конструкции оказываются в различных пространствах имен. Далее, повторное использование одного и того же пространства имен гарантирует лучшую инструментальную поддержку. Многие приложения используют одну схему для создания эквивалентных программных конструкций. Эти инструменты часто работают наилучшим образом с поддержкой одиночного пространства имен для "обобщенных" конструкций. Повторное использование имени пространства имен разрешает по крайней мере автору пространства имен вносить изменения в пространства имен и выполнять проверку допустимости расширений.
Замещение модели обработки по умолчанию
В случае соблюдения правила "Обязательно пропускать", часто может возникнуть ситуация, при которой разработчик расширения захочет потребовать, чтобы получатель понимал расширение, замещая правило "Обязательно пропускать" следующим правилом:
10. Правило "Обеспечение mustUnderstand": языки контейнера должны обеспечить модель "mustUnderstand" для обработки факультативности расширений, которые замещают правило "Обязательно пропускать". |
Это правило и правило "Обязательно пропускать" работают совместно, обеспечивая стабильную и гибкую модель обработки расширений. Можно доказать, что наиболее простой и гибкий прием замещения - это признак mustUnderstand, который указывает, должна ли единица быть понятной. Атрибуты для SOAP [7], WSDL [8] WS-Policy [10] и значения для установления understand имеют следующий вид: soap:mustUnderstand="1", wsdl:required="1", wsp:Usage="wsp:Required", соответственно. SOAP, вероятно, наиболее общий случай контейнера, который обеспечивает модель mustUnderstand. Значение по умолчанию равно 0, что фактически является правилом "Обязательно пропускать".
Признак mustUnderstand позволяет отправителю вставлять расширения в контейнер и использовать атрибут mustUnderstand для замещения правила "Обязательно пропускать". Благодаря этому отправители могут расширять сообщения, не меняя пространство имен родителя элемента расширения и поддерживая обратную совместимость. Очевидно, получатель должен быть расширен, чтобы обрабатывать новые расширения, хотя теперь между моделью обработки языка и моделью обработки расширения появляется слабая связь.
Кроме того, возможны и другие подходы, как, например, предоставление элемента, который указывает, какие пространства имен расширения должны быть понятны.
В некоторых случаях язык не предоставляет механизм mustUnderstand. При отсутствии модели mustUnderstand невозможно заставить получателей отклонить сообщение, если они не понимают пространство имен расширения.
Детерминизм
У определений типа документа (DTD, Document Type Definition) и XML-схемы W3C есть правило, согласно которому схемы должны иметь детерминистические модели содержания. Так, в спецификации "XML 1.0" записано:
Использование ##any означает, что имеются схемы, которые хотелось бы составить, но которые не являются допустимыми.
- Групповые символы с ##any, где minOccurs не равен maxOccurs, не допускаются до объявления элемента. Экземпляр этого элемента был бы допустим для этого ##any или этого элемента. Мог бы использоваться ##other.
- Элемент перед групповым символом с ##any обязан иметь количество элементов maxOccurs, равное minOccurs. Если бы они были различны, например, minOccurs="1" и maxOccurs="2", то необязательные вхождения элементов могли бы соответствовать либо описанию элемента, либо ##any. Следствием этого правила является требование о том, что minOccurs обязано быть больше нуля.
- Необходимо избегать производных типов, которые добавляют описания элементов после группового символа с ##any. Если бы производный тип добавлял описание элемента после группового символа, экземпляр добавленного описания элемента мог бы соответствовать либо групповому символу, либо описанию производного элемента.
11. Правило "Детерминизм": использование групповых символов ОБЯЗАНО быть детерминистическим. Расположение групповых символов, пространство имен расширений групповых символов, значения minOccurs и maxOccurs являются ограниченными, а ограничения типов контролируемыми. |
Как было показано выше, обычный подход проектирования - обеспечить точку расширяемости (не элемент), разрешив любое пространство имен в конце типа. Это обычно выполняется с помощью xs:any namespace="##any".
Во многих случаях, как и с законченным решением, в ситуации с детерминизмом это невыполнимо. Во-первых, точка расширяемости может иметь место только после обязательного элемента в исходной схеме, ограничивая тем самым область расширяемости исходной схемы. Во-вторых, изменения, поддерживающие обратную совместимость, требуют, чтобы добавленный элемент был необязательным, что подразумевает minOccurs="0". Детерминизм не позволяет разместить minOccurs="0" перед точкой расширяемости ##any. Таким образом, при добавлении элемента в точке расширяемости разарботчик схемы может задать элемент необязательным и потерять точку расширяемости или же определить его как обязательный, но лишиться обратной совместимости.
Причины сложностей
Выше были показаны сложности использования XML и XML-схемы W3C для получения слабой связи посредством внесения совместимых изменений, которые хотя полностью используют описания новой схемы, но не требуют их. Следование указанным правилам расширяемости приводит к созданию документов XML-схема W3C, которые являются более громоздкими и в то же время менее выразительными, чем можно было бы пожелать. Структурные ограничения, которые накладываются в результате задания расширяемости с помощью XML-схемы W3C, являются следствием конструкции XML-схемы W3C, а не врожденными ограничениями структур, основанных на схеме.
Что касается XML-схемы W3C, то было бы удобно иметь возможность добавлять элементы в произвольных местах, например, перед другими элементами, однако ограничения детерминизма этому препятствуют. Можно было бы воспользоваться менее ограниченной детерминистической моделью, такой как "жадный" алгоритм (greedy algorithm), определенный в спецификации URI [4]. Это разрешило бы располагать необязательные элементы перед групповыми символами и позволило бы устранить потребности в введенном выше типе Extensiontype. Однако, групповые символы по-прежнему недопустимы перед элементами, поскольку вместо этого групповой символ соответствовал бы элементам. Далее, по-прежнему не могут сосуществовать групповые символы и расширения типа. "Приоритетная" модель, в которой элемент мог бы быть сопоставлен с групповым символом или элемент сопоставлялся бы с элементом, если такое возможно, разрешала бы групповые символы до и после объявления элементов. Кроме того, групповой символ, который допускал элементы, которые не были определены - фактически другие пространства имен плюс что-нибудь, не определенное в целевом пространстве имен - еще одна удобная модель. Эти изменения также разрешили бы более четкое объединение наследования и групповых символов. Но это также означает, что разработчик схемы должен распределить групповые символы по их типам. Требуется элемент уровня типа в сочетании с вышеупомянутыми изменениями групповых символов. Возможное решение заключается в том, что объявление последовательностей могло бы содержать атрибут, указывающий, что расширения допустимы в любом месте, затем - соответствующие атрибуты, указывающие пространства имен, элементы и правила проверки на допустимость.
Сложность с последним подходом состоит в том, что для конкретной схемы иногда необходимо применять в различных частях системы одну и ту же схему нестрого и нестрого. Давнее правило для Интернет - это принцип устойчивости (Robustness Principle), сформулированный следующим образом в протоколе Internet (Internet Protocol) [3]: "в большинстве случаев реализация должна быть консервативна при отправке сообщений и либеральна при их получении". Применительно к проверке допустимости по схеме отправитель может применять схему строго, а получатель - нестрого. В этом случае степень строгости - это не атрибут схемы, а то, как она используется. Решение, которое, кажется, может решить эти проблемы, - определить форму проверки по схеме, которая разрешит открытую модель содержания, используемую при задании версий схем. Назовем эту модель проверкой допустимости "по отображению" - она работает игнорируя, а не отбрасывая, имена компонентов, которые появляются в сообщении, не являясь явно определенными в схеме. Автор статьи планирует в будущем рассмотреть эту модель нестрогой проверки допустимости.
Последнее замечание в адрес расширяемости XMLсхемы W3C заключается в том, что по-прежнему остается нерешенным вопрос определения схем, которые проверяют допустимость известных расширений, сохраняя при этом расширяемость. Разработчикам схем потребуется не только создавать схему, основанную на расширяемой схеме, но и соединить с другими известными схемами с отдельными групповыми символами, сохраняя при этом расширяемость групповых символов. Автор столкнулся с такой сложностью при описании блоков SOAP header. Вопрос компоновки схем из множества схем хотя и не прост, но требует скорейшего разрешения.
Закончив с рассмотрениеv расширяемости групповых символов, отметим, что использование расширения типов во "Всемирной паутине" могло бы быть более удобным, если бы в реальном документе был выражен базовый тип, когда получатель не понимает тип расширения, например, в выражении xsi:basetype="". Тогда получатель мог бы нейтрализовать неисправность, воспользовавшись базовым типом, если он не понял расширения этого базового типа.
Еще одна область архитектурного улучшения - обеспечиn в XML, или даже XML-схеме W3C, модель mustUnderstand. В настоящий момент каждый словарь, который предоставляет модель mustUnderstand, изобретает заново "колесо mustUnderstand". XML мог бы предоставлять атрибут xml:mustUnderstand и модель, которую мог бы использовать каждый язык. Хотя в феврале 2000г. Тим Бернерс-Ли в своей проектной записке о обязательных расширениях [8] писал о необходимости включения этой модели в XML, она не была добавлена ни в XML 1.0, ни в XML 1.1.
Наконец, сохраняется неоднозначность при испытании реализаций на соответствие XML-схемам W3C. Набор тестов по XML-схемам W3C [16] не охватывает более общие случаи, которые не были рассмотрены в данной статье. Например, тесты включают особый стиль, для которого xs:any находится внутри сложного типа. Однако, они не рассматривают некоторые недетерминистические случаи, обычно возникающие при комбинировании вариаций minOccurs/maxOccurs с ##any или комбинировании наследования с ##any. Следовательно, некоторые реализации не являются корректно оттестированными в случае отсутствия детерминизма, что может привести к появлению неработоспособных документов.
Еще одна сложность связана с поддержкой в реализациях этих функциональных возможностей и комбинаций. Данные примеры были апробированы в различных парсерах и инструментальных инструментах, предназначенных для работы со схемой, как, например, XML Beans, SQC и JAX-RPC. Несмотря на то, что хотя невозможно выяснить, все ли реализации поддерживают эти правила, то, что было протестировано, похоже обеспечивает хорошую поддержку. Автору статьи, разумеется, будет небезынтересно узнать о инструментальных средствах, которые не обеспечивают поддержку этих правил.
Заключение
Проблема управления версиями и расширяемости оказалась настолько важной для архитектуры Web, что Группа технического проектирования W3C (Technical Architecture Group, сокр. TAG) опубликовала свои заключение по этому вопросу [20] и включила соответствующие материалы в документ "Архитектура Web" (Web Architecture) [21]. Данную статью можно считать отправным моментом при изучении материалов TAG, в документах TAG область рассмотрения шире, а изложение материала носит более последовательный характер. Читатели могут обриться к этим документам за текущей трактовкой вопросов расширяемости и управления версиями.
В этой статье описан ряд правил использования XML, XML-схем W3C и пространства имен XML в конструкциях и расширениях языка. Основная задача этого набора правил - разрешить разработчикам схем вносить в свои языки изменения, поддерживающие обратную и прямую совместимость, чтобы реализовать слабую связь между системами.
В определенной степени описанный подход является комбинацией моделей ##any и ##other с хорошо известными правилами построения схем, которые решают задачу совместимой расширяемости и управления версиями с проверкой допустимости с помощью XML-схемы W3C. Владелец имени пространств имен может вносить в элемент расширяемости изменения, поддерживающие обратную и прямую совместимость, сохраняя возможность проверять допустимость всех компонентов, а другие разработчики схем могут добавлять изменения в расположении группового символа ##other.
Ресурсы
- Бесплатный он-лайн словарь по вычислительной технике (Free Online Dictionary of Computing)
- Гибкий профиль обработки XML-документов (Flexible XML Processing Profile)
- Запрос на комментарии комитета по инженерным вопросам Internet 791 (IETF RFC 791)
- Запрос на комментарии комитета по инженерным вопросам Internet 2396 (IETF RFC 2396)
- Запрос на комментарии комитета по инженерным вопросам Internet 2518 (IETF RFC 2518)
- Запрос на комментарии комитета по инженерным вопросам Internet 2616 (IETF RFC 2616)
- SOAP 1.1
- WSDL 1.1
- Протокол WS-Callback
- Спецификация WS-Policy Framework
- Примеры успешного использования схем на сайте Xfront (Xfront's Schema Best Practices)
- Примечания консорциума W3C "Архитектура Web: расширяемые языки" (W3C Note, Web Architecture: Extensible Languages)
- Спецификация консорциума W3C "XML 1.0" (W3C XML 1.0)
- Спецификация консорциума W3C "Пространства имен XML" (W3C XML Namespaces)
- Спецификация консорциума W3C "XML-схема, Часть 1" (W3C XML Schema Part 1)
- Набор тестов Рабочей группы XML Schema консорциума W3C для конструкции Any (W3C XML Schema Working Group's Test collection for Any)
- Статья Деара Обасаньо (Dare Obasanjo), опубликованная на ресурсе XML.com, "Принципы проектирования XML-схем" (W3C XML Schema design Patterns)
- Работы Тима Бернерса-Ли (Tim Berners-Lee) о развитии, расширяемости и mustUnderstand:
- http://lists.w3.org/Archives/Public/w3c-dist-auth/1997AprJun/0190.html
- Заключение Группы технического проектирования W3C о расширяемости и управлению версиями (W3C TAG Finding on extensibility and versioning)
- Раздел документа Группы технического проектирования W3C "Архитектура Web" о расширяемости и управлении версиями (W3C TAG Web Architecture document section on extensibility and versioning)
Благодарности
Автор выражает благодарность многочисленным рецензентам этой статьи, способствовавшим ее написанию, а именно: Дэвиду Бо (David Bau), Уильяму Коксу (William Cox), Эдду Дамбиллу (Edd Dumbill), Крису Фэррис (Chris Ferris), Ярону Голенду (Yaron Goland), Халу Локхарту (Hal Lockhart), Марку Ноттингему (Mark Nottingham), Джеффри Шлиммеру (Jeffrey Schlimmer), Клиффу Шмидту (Cliff Schmidt) и Норману Уолшу (Norman Walsh). В этой статье используются, с разрешения авторов, примеры и часть текста из протокола WS-Callback [9].
Автор: Дэвид Орчард (David Orchard)