Практика использования пространств имен XML в проектах, содержащих несколько XML-схемИсточник: oracle Bладимир Энгельс, Oracle СНГ
Автор: Bладимир Энгельс, Oracle СНГ Введение При реализации типичных SOA-проектов, как правило, создается несколько XML-схем. В этих случаях проектировщик XML-схем должен решить следующий вопрос:
Какой подход будет более оптимальный? Каким руководствам нужно следовать, начиная работу над SOA-проектами, в которых создается несколько XML-схем? Точности ради, надо отметить, что имеется три проектных подхода при работе с несколькими XML-схемами:
Для описания и оценки достоинств и недостатков трех указанных проектных подходов приведем примеры для каждого из них. Пример: XML-модель данных компании Представим себе проект, который требует создания модели данных компании, используя XML-схемы. Данная модель создается в виде следующих трех XML-схем:
Это можно охарактеризовать как "информация о компании включает в себя данные по персоне и по продукту". Приведем три схемы для каждого проектного подхода. Гетерогенное пространство имен Данный проектный подход предполагает использование для каждой XML-схемы своего targetNamespace. Ниже приводится три схемы, спроектированные с применением данного проектного подхода. Product.xsd
Person.xsd
Company.xsd
Обратите внимание, что в схемах используется три различных пространства имен:
Гомогенное пространство имен Данный проектный подход предполагает использование единого targetNamespace для всех XML-схем. Ниже приводится три схемы, спроектированные с применением данного проектного подхода. Product.xsd
Person.xsd
Company.xsd
Обратите внимание, что во всех трех схемах используется единое пространств имен:
Также обратите внимание, что для объединения XML-схем, использующих единое пространство имен, применяется механизм <include>. Пространство имен типа "хамелеон" Данный проектный подход предполагает использование targetNamespace только для главной XML-схемы, а вспомогательным XML-схемам не присваивается никакого targetNamespace. Ниже приводится три схемы, спроектированные с применением данного проектного подхода. В данном примере XML-схема Company.xsd является главной, XML-схемы Product.xsd и Person.xsd - вспомогательные. Product.xsd (нет targetNamespace)
Person.xsd (нет targetNamespace)
Company.xsd
Обратите внимание на два аспекта при использовании данного проектного подхода:
"Эффект хамелеона..." - этот термин ввел Генри Томпсон (Henry Thompson). Влияние проектных подходов на XML-документы Выше было продемонстрировано, как могли бы быть спроектированы XML-схемы с применением трех проектных подходов. Теперь обратимся к XML-документам. Отличается ли создание XML-документов, в зависимости от применения того или иного проектного подхода? Все вышеприведенные XML-схемы были спроектированы с требованием явного указания пространств имен в XML-документах (на что указывает: elementFormDefault="qualified"). Если бы они использовали вместо этого elementFormDefault="unqualified", то XML-документ для всех трех случаев имел бы следующую форму:
Как же будут выглядеть XML-документы для наших трех подходов проектирования? Company.xml (для версии с гетерогенным пространством имен в targetNamespace)
Обратите внимание на следующее:
Company.xml (для версии с гомогенным пространством имен в targetNamespace)
Поскольку все схемы принадлежат одному пространству имен, то в XML-документах для данной ситуации можно воспользоваться преимуществом использования пространства имен "по-умолчанию". Company.xml (для версии с пространством имен типа "хамелеон" в targetNamespace)
Обе XML-схемы без определения targetNamespace приняли targetNamespace XML-схемы Company.xsd (подобно хамелеон-эффекту). Таким образом, все компоненты принадлежат одному targetNamespace, и в XML-документах для данной ситуации также можно воспользоваться преимуществом использования пространства имен "по-умолчанию". <redefine> - применяемый только в гомогенном пространстве имен и в пространстве имен типа "хамелеон" Элемент <redefine> используется в XML-схемах для получения доступа к компонентам в других XML-схемах и одновременно дает возможность внести какое-то число (ноль или более) изменений в определения импортируемых компонентов. Таким образом, элемент <redefine> выполняет двойную функцию:
Пример. Рассмотрим опять вышеприведенную XML-схему Company.xsd. Предположим, что она использует элемент ProductType из Product.xsd. Дополнительно, во время использования необходимо расширить элемент ProductType и включить в него элемент ID (идентификатор продукта). Приведем пример, как это можно сделать, используя элемент <redefine>:
Теперь элемент <Product> в XML-документе должен содержать оба элемента <Type> и <ID>, то есть:
Элемент <redefine> обладает очень большой проектной мощью. Правда, использоваться он может только в XML-схемах с единым пространством имен или в XML-схемах без указания пространства имен. Таким образом, элемент <redefine> может быть применим только проектных подходах с гомогенным пространством имен и с пространством имен типа "хамелеон". Пространство имен "по-умолчанию" и проектный подход типа "хамелеон" Если XML-схема предполагает использование елемнта <include> в рамках проетного подхода типа "хамелеон" (используя схемы без определения targetNamespace), то главная схема должна объявлять пространство имен из targetNamespace также как пространство имен "по-умолчанию". Как избежать коллизии имен при использовании подхода типа "хамелеон" Коллизия имен Когда главная XML-схема использует хамелеон-комоненты, то эти компоненты становятся частью пространства имен (указанного в targetNamespace) главной XML-схемы, так как будто проектировщик XML-схемы использовал in-line декларацию элементов и типов. Если главная схема включает (<include>) несколько XML-схем без указания пространства имен, то существует шанс, что возникнет коллизия имен. Таким образом, главная XML-схема не сможет использовать некоторые компоненты вспомогательных XML-схем (в которых не указано пространство имен), поскольку для них имеет место коллизия имен с элементами из других вспомогательных XML-схем. Для демонстрации проблемы коллизии имен, рассмотрим следующий пример. Предположим, существует две XML-схемы без указания targetNamespace:
XML-схема 1.xsd определяет элементы A и B без указания пространства имен.
Обратите внимание, что ошибкой не является существование определения двух элементов с одинаковым именем, если они принадлежат к одному типу. Если же они принадлежат различным типам, то это ошибка, и имеет место коллизия имен. Стандартным механизмом исключения коллизий имен как раз и является применение пространств имен. Если бы в приведенном выше примере компоненты XML-схем 1.xsd и 2.xsd находились бы в различных пространствах имен и они были бы импортированы в XML-схему 3.xsd, то коллизии имен не возникло. [Заметьте, что два компонента могут иметь одинаковое имя, если компоненты принадлежат различным пространствам имен.] А как же разрешить проблему коллизии имен при использовании пространств имен типа "хамелеон"? Решение проблемы коллизии имен с применением проксирующих XML-схем Существует очень простое решение данной проблемы коллизии имен: для каждой включаемой XML-схемы без указания пространства имен создается вспомогательная проксирующая XML-схема, в которой декларировано пространство имен и которая сама уже включает (<include>) вспомогательные XML-схемы без указания пространств имен. Затем главная схема просто импортирует (<import>) все проксирующие XML-схемы. Приведем пример демонстрирующий данный проектный подход:
Применяя данный проектный подход, нам удалось избежать коллизии имен. Более того, у этого проектного подхода есть еще одно дополнительное преимущество: в рамках проксирующих XML-схем также можно использовать элемент <redefine> для внесения изменения в хамелеон-компоненты. Таким образом, данный проектный подход регламентирует трехступенчатый процесс:
Использование данного трехступенчатого процесса позволяет более гибко принимать решения в проекте по поводу доменов (пространств имен) тех компонентов, которые используются повторно. Более того, появляется возможность внести изменения в хамелеон-компоненты. Хотя в данном подходе и используется дополнительный шаг процесса (создание проксирующих XML-схем), все же он обладает большой гибкостью. Сравним данный трехступенчатый процесс с ранее описанным двухступенчатым процессом, в котором компонентам назначаются пространства имен с самого начала существования компонента:
Двухступенчатый процесс дает тот же результат, что и трехступенчатый. В данном примере компоненты уже не являются "хамелеонами", и элементы A, B и C жестко привязанны к соответствующим пространствам имен с начала жизненного цикла компонентов. Обратная сторона данного подхода - если в main.xsd понадобится внести изменения в определения компонентов с использованием <redefine>, то это будет невозможно. Кроме того, проектировщик главной XML-схемы вынужден использовать пространства имен, определенные кем-то другим. Эти компоненты являются статичными, неизменяемыми и с фиксированным пространством имен. Средства, облегчающих использование хамелеон-компонентов Описание проблемы идентификации хамелеон-компонентов Мы уже несколько раз наблюдали, что хамелеон-компоненты могут смешиваться в схемах, которые их используют. Это происходит, когда они принимают пространство имен включающих (<include>) их XML-схем. Какими же средствами можно идентифицировать компоненты, которые имеют много представлений, относящихся к различным пространствам имен? Предположим, существуют следующие XML-схемы без определения пространств имен:
Далее мы определяем главную XML-схему main.xsd, которая включает (<include>) вспомогательную XML-схему "хамелеон" 1.xsd, а также сама содержит определение элемента с именем A (поскольку он находится в другом символьном окружении - внутри элемента <stuff>, это не приведет к коллизии имен).
Предположим, в процессе трансформации нам необходимо четко идентифицировать хамелеон-компонент A, независимо от того, к какому пространству имен они, возможно, будут принадлежать в будущем. Как нам отличить хамелеон-компонент A от локально определенного в XML-схеме компонента A? Идентификация хамелеон-компонентов Существует одно простое средство - при создании хамелеон-компонента назначить ему глобально уникальный идентификатор (GUID). Спецификация XML Schema позволяет добавлять атрибут id для элемента, атрибута, а также для компонентов простого и комплексного типов. Обратите внимание, что атрибут id исключительно локален для XML-схемы, и он никогда не попадает в XML-документ. Именно этот атрибут можно использовать для точной идентификации хамелеон-компонента, независимо от его текущего пространства имен. Вопрос: что произойдет, если из-за проблем сети, XML-процессор не сможет получить доступ к XML-схеме, содержащей необходимые определения? Как и в случае с DTD-определениями произойдет исключительная ситуация в XML-процессоре. Решение данной проблемы - всегда хранить копии используемых XML-схем локально. Практика использования пространств имен XML в проектах Выше были описаны проектные подходы применительно к использованию пространств имен XML в проектах. Были рассмотрены как XML-схемы, так и XML-документы для каждого из трех проектных подходов. Теперь осталось ответить на главный вопрос: какой подход лучше, и в каком случае? Если в проекте используется XML-схема, созданная и контролируемая кем-то другим, то необходимо использовать импортирование (<import>) данной XML-схемы, то есть использовать проектный подход с гетерогенным пространством имен. Копировать такие компоненты в пространство имен проекта - не очень удачная идея по двум причинам:
Более интересна ситуация (ситуация, которая рассматривалась в качестве примеров), как поступить с пространством имен XML-схем, создаваемых в рамках проекта и полностью подконтрольных одному проектировщику (или группе). Ниже приведено несколько рекомендаций: Используйте пространство имен типа "хамелеон":
Пример. Репозиторий таких компонентов как, например, XML-схема, определяющая типы массива, вектора, связанного списка и т. п., должны определяться без указания targetNamespace (то есть как хамелеон-XML-схема). Если XML-схема содержит только определения типов (отсутствуют декларации элементов), то она также хороший кандидат на использование хамелеон- пространства имен. Используйте гомогенное пространство имен:
Используйте гетерогенное пространство имен: И, наконец, как было продемонстрировано выше, в XML-схемах каждый компонент может быть уникально идентифицирован с использованием атрибута id (это не то же самое, что объявить атрибут id для элемента; это внутренний механизм XML-схем для идентификации каждого компонента XML-схемы). Использование атрибута id для идентификации каждого компонента XML-схемы дает даже больший контроль над компонентом, чем при использовании пространств имен. Комбинация этих двух средств - пространств имен и атрибутов id компонентов XML-схем - мощный тандем, позволяющий надежно идентифицировать комоненты XML-схем, как визуально, так и программно. |