Bладимир Энгельс,
Oracle СНГ
Практика использования пространств имен XML
в проектах, содержащих несколько XML-схем
Источник: сайт
SOA Design,
http://soa.it-consultants.ru:8888/?q=node/12
Введение
При реализации типичных SOA-проектов, как правило, создается несколько XML-схем. В этих случаях проектировщик XML-схем должен решить
следующий вопрос:
- необходимо ли всем XML-схемам в проекте присваивать различные значения targetNamespace
- или нужно использовать единый targetNamespace для всех
- и можно ли некоторым XML-схемам не присваивать никакого targetNamespace?
Какой подход будет более оптимальный? Каким руководствам нужно следовать, начиная работу над SOA-проектами, в которых создается несколько XML-схем?
Точности ради, надо отметить, что имеется три проектных подхода при работе с несколькими XML-схемами:
- гетерогенное пространство имен - каждой XML-схеме присваивается свой targetNamespace;
- гомогенное пространство имен - всем XML-схемам присваивается единый targetNamespace;
- пространство имен типа "хамелеон" - главной XML-схеме присваивается targetNamespace, а вспомогательным XML-схемам не присваивается никакого targetNamespace (XML-схемы без targetNamespace используют targetNamespace главной XML-схемы при объединении подобно хамелеону).
Для описания и оценки достоинств и недостатков трех указанных проектных подходов приведем примеры для каждого из них.
Пример: XML-модель данных компании
Представим себе проект, который требует создания модели данных компании, используя XML-схемы. Данная модель создается в виде следующих трех XML-схем:
- Company.xsd
- Person.xsd
- Product.xsd
Это можно охарактеризовать как "информация о компании включает в себя данные по персоне и по продукту". Приведем три схемы для каждого проектного подхода.
Гетерогенное пространство имен
Данный проектный подход предполагает использование для каждой XML-схемы своего targetNamespace. Ниже приводится три схемы, спроектированные с применением данного проектного подхода.
Product.xsd
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.product.org"
xmlns="http://www.product.org"
elementFormDefault="unqualified">
xmlns:per="http://www.person.org"
xmlns:pro="http://www.product.org">
<xsd:complexType name="ProductType">
<xsd:sequence>
<xsd:element name="Type" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Person.xsd
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.person.org"
xmlns="http://www.person.org"
elementFormDefault="unqualified">
<xsd:complexType name="PersonType">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="SSN" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Company.xsd
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.company.org"
xmlns="http://www.company.org"
elementFormDefault="unqualified"
xmlns:per="http://www.person.org"
xmlns:pro="http://www.product.org">
<xsd:import namespace="http://www.person.org"
schemaLocation="Person.xsd"/>
<xsd:import namespace="http://www.product.org"
schemaLocation="Product.xsd"/>
<xsd:element name="Company">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Person" type="per:PersonType"
maxOccurs="unbounded"/>
<xsd:element name="Product" type="pro:ProductType"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Обратите внимание, что в схемах используется три различных пространства имен:
http://www.product.org
http://www.person.org
http://www.company.org
Гомогенное пространство имен
Данный проектный подход предполагает использование единого targetNamespace для всех XML-схем. Ниже приводится три схемы, спроектированные с применением данного проектного подхода.
Product.xsd
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.company.org"
xmlns="http://www.product.org"
elementFormDefault="qualified">
<xsd:complexType name="ProductType">
<xsd:sequence>
<xsd:element name="Type" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Person.xsd
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.company.org"
xmlns="http://www.person.org"
elementFormDefault="qualified">
<xsd:complexType name="PersonType">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="SSN" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Company.xsd
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.company.org"
xmlns="http://www.company.org"
elementFormDefault="qualified">
<xsd:include schemaLocation="Person.xsd"/>
<xsd:include schemaLocation="Product.xsd"/>
<xsd:element name="Company">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Person" type="PersonType"
maxOccurs="unbounded"/>
<xsd:element name="Product" type="ProductType"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Обратите внимание, что во всех трех схемах используется единое пространств имен:
http://www.company.org
Также обратите внимание, что для объединения XML-схем, использующих единое пространство имен, применяется механизм <include>.
Пространство имен типа "хамелеон"
Данный проектный подход предполагает использование targetNamespace только для главной XML-схемы, а вспомогательным XML-схемам не присваивается никакого targetNamespace. Ниже приводится три схемы, спроектированные с применением данного проектного подхода. В данном примере XML-схема Company.xsd является главной, XML-схемы Product.xsd и Person.xsd - вспомогательные.
Product.xsd (нет targetNamespace)
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:complexType name="ProductType">
<xsd:sequence>
<xsd:element name="Type" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Person.xsd (нет targetNamespace)
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:complexType name="PersonType">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="SSN" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Company.xsd
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.company.org"
xmlns="http://www.company.org"
elementFormDefault="qualified">
<xsd:include schemaLocation="Person.xsd"/>
<xsd:include schemaLocation="Product.xsd"/>
<xsd:element name="Company">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Person" type="PersonType"
maxOccurs="unbounded"/>
<xsd:element name="Product" type="ProductType"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>>
Обратите внимание на два аспекта при использовании данного проектного подхода:
- для объединения XML-схем, использующих пространство имен "хамелеон", также используется механизм <include>, и главная XML-схема имеет доступ к элементам вспомогательных XML-схем;
- вспомогательные XML-схемы без targetNamespace в рамках данного проектного подхода обладают следующей характеристикой - компоненты XML-схем без targetNamespace используют приведение пространства имен (это значит, что компоненты принимают targetNamespace главной XML-схемы).
"Эффект хамелеона..." - этот термин ввел Генри Томпсон (Henry Thompson).
Влияние проектных подходов на XML-документы
Выше было продемонстрировано, как могли бы быть спроектированы XML-схемы с применением трех проектных подходов. Теперь обратимся к XML-документам. Отличается ли создание XML-документов, в зависимости от применения того или иного проектного подхода? Все вышеприведенные XML-схемы были спроектированы с требованием явного указания пространств имен в XML-документах (на что указывает: elementFormDefault="qualified"). Если бы они использовали вместо этого
elementFormDefault="unqualified", то XML-документ для всех трех случаев имел бы следующую форму:
<?xml version="1.0"?>
<c:Company xmlns:c="http://www.company.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.company.org/Company.xsd">
<Person>
<Name>John Doe</Name>
<SSN>123-45-6789</SSN>
</Person>
<Product>
<Type>Widget</Type>
</Product>
</c:Company>
Как же будут выглядеть XML-документы для наших трех подходов проектирования?
Company.xml (для версии с гетерогенным пространством имен в targetNamespace)
<?xml version="1.0"?>
<Company xmlns="http://www.company.org"
xmlns:pro="http://www.product.org"
xmlns:per="http://www.person.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.company.org/Company.xsd">
<Person>
<per:Name>John Doe</per:Name>
<per:SSN>123-45-6789</per:SSN>
</Person>
<Product>
<pro:Type>Widget</pro:Type>
</Product>
</Company>
Обратите внимание на следующее:
- необходимо иметь декларацию namespace для кадого пространства имен;
- все элементы должны быть уникально квалифицированы (явно или через пространство имен "по-умолчанию").
Company.xml (для версии с гомогенным пространством имен в targetNamespace)
<?xml version="1.0"?>
<Company xmlns="http://www.company.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.company.org/Company.xsd">
<Person>
<Name>John Doe</Name>
<SSN>123-45-6789</SSN>
</Person>
<Product>
<Type>Widget</Type>
</Product>
</Company>
Поскольку все схемы принадлежат одному пространству имен, то в XML-документах для данной ситуации можно воспользоваться преимуществом использования пространства имен "по-умолчанию".
Company.xml (для версии с пространством имен типа "хамелеон" в targetNamespace)
<?xml version="1.0"?>
<Company xmlns="http://www.company.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.company.org/Company.xsd">
<Person>
<Name>John Doe</Name>
<SSN>123-45-6789</SSN>
</Person>
<Product>
<Type>Widget</Type>
</Product>
</Company>
Обе XML-схемы без определения targetNamespace приняли targetNamespace XML-схемы Company.xsd (подобно хамелеон-эффекту). Таким образом, все компоненты принадлежат одному targetNamespace, и в XML-документах для данной ситуации также можно воспользоваться преимуществом использования пространства имен "по-умолчанию".
<redefine> - применяемый только в гомогенном пространстве имен и в пространстве имен типа "хамелеон"
Элемент <redefine> используется в XML-схемах для получения доступа к компонентам в других XML-схемах и одновременно дает возможность внести какое-то число (ноль или более) изменений в определения импортируемых компонентов. Таким образом, элемент <redefine> выполняет двойную функцию:
- он выполняет неявный <include>, что позволяет иметь доступ ко всем компонентам во вспомогательных схемах;
- он дает возможность внести какое-то число (ноль или более) изменений в определения импортируемых компонентов, то есть расширить определения компонентов или наоборот наложить дополнительные ограничения на определения компонентов.
Пример. Рассмотрим опять вышеприведенную XML-схему Company.xsd. Предположим, что она использует элемент ProductType из Product.xsd. Дополнительно, во время использования необходимо расширить элемент ProductType и включить в него элемент ID (идентификатор продукта). Приведем пример, как это можно сделать, используя элемент <redefine>:
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.company.org"
xmlns="http://www.company.org"
elementFormDefault="qualified">
<xsd:include schemaLocation="Person.xsd"/>
<xsd:redefine schemaLocation="Product.xsd">
<xsd:complexType name="ProductType">
<xsd:complexContent>
<xsd:extension base="ProductType>
<xsd:sequence>
<xsd:element name="ID" type="xsd:ID"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:redefine>
<xsd:element name="Company">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Person" type="PersonType"
maxOccurs="unbounded"/>
<xsd:element name="Product" type="ProductType"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Теперь элемент <Product> в XML-документе должен содержать оба элемента <Type>
и <ID>, то есть:
<?xml version="1.0"?>
<Company xmlns="http://www.company.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.company.org/Company.xsd">
<Person>
<Name>John Doe</Name>
<SSN>123-45-6789</SSN>
</Person>
<Product>
<Type>Widget</Type>
<ID>1001-01-00</ID>
</Product>
</Company>
Элемент <redefine> обладает очень большой проектной мощью. Правда, использоваться он может только в XML-схемах с единым пространством имен или в XML-схемах без указания пространства имен. Таким образом, элемент <redefine> может быть применим только проектных подходах с гомогенным пространством имен и с пространством имен типа "хамелеон".
Пространство имен "по-умолчанию" и проектный подход типа "хамелеон"
Если XML-схема предполагает использование елемнта <include> в рамках проетного подхода типа "хамелеон" (используя схемы без определения targetNamespace), то главная схема должна объявлять пространство имен из targetNamespace также как пространство имен "по-умолчанию".
Как избежать коллизии имен при использовании подхода типа "хамелеон"
Коллизия имен
Когда главная XML-схема использует хамелеон-комоненты, то эти компоненты становятся частью пространства имен (указанного в targetNamespace) главной XML-схемы, так как будто проектировщик XML-схемы использовал in-line декларацию элементов и типов. Если главная схема включает (<include>) несколько XML-схем без указания пространства имен, то существует шанс, что возникнет коллизия имен. Таким образом, главная XML-схема не сможет использовать некоторые компоненты вспомогательных XML-схем (в которых не указано пространство имен), поскольку для них имеет место коллизия имен с элементами из других вспомогательных XML-схем. Для демонстрации проблемы коллизии имен, рассмотрим следующий пример.
Предположим, существует две XML-схемы без указания targetNamespace:
1.xsd
A
B
2.xsd
A
C
XML-схема 1.xsd определяет элементы A и B без указания пространства имен.
XML-схема 2.xsd определяет элементы A и C без указания пространства имен.
Теперь, если XML-схема 3.xsd включает в себя (<include>) две указанные XML-схемы без указания пространства имен, возникает коллизия имен для элемента A, поскольку он объявлен два раза:
3.xsd
targetNamespace="http://www.example.org"
<include schemaLocation="1.xsd"/>
<include schemaLocation="2.xsd"/>
Обратите внимание, что ошибкой не является существование определения двух элементов с одинаковым именем, если они принадлежат к одному типу. Если же они принадлежат различным типам, то это ошибка, и имеет место коллизия имен.
Стандартным механизмом исключения коллизий имен как раз и является применение пространств имен. Если бы в приведенном выше примере компоненты XML-схем 1.xsd и 2.xsd находились бы в различных пространствах имен и они были бы импортированы в XML-схему 3.xsd, то коллизии имен не возникло. [Заметьте, что два компонента могут иметь одинаковое имя, если компоненты принадлежат различным пространствам имен.]
А как же разрешить проблему коллизии имен при использовании пространств имен типа "хамелеон"?
Решение проблемы коллизии имен с применением проксирующих XML-схем
Существует очень простое решение данной проблемы коллизии имен: для каждой включаемой XML-схемы без указания пространства имен создается вспомогательная проксирующая XML-схема, в которой декларировано пространство имен и которая сама уже включает (<include>) вспомогательные XML-схемы без указания пространств имен. Затем главная схема просто импортирует (<import>) все проксирующие XML-схемы.
Приведем пример демонстрирующий данный проектный подход:
<!-- Поместим "хамелеон"-компоненты XML-схемы 1.xsd
в пространство имен, указанное в targetNamespace, данной проксирующей XML-схемы -->
1-proxy.xsd
targetNamespace="http://www.1-proxy.org"
<xsd:include schemaLocation="1.xsd"/>
<!-- Поместим "хамелеон"-компоненты XML-схемы 2.xsd
в пространство имен, указанное в targetNamespace, данной проксирующей XML-схемы -->
2-proxy.xsd
targetNamespace="http://www.2-proxy.org"
<xsd:include schemaLocation="2.xsd"/>
<!-- Теперь импортируем проксирующие XML-схемы в главную схему -->
main.xsd
targetNamespace="http://www.main.org"
<xsd:import namespace="http://www.1-proxy.org"
schemaLocation="1-proxy.xsd"/>
<xsd:import namespace="http://www.2-proxy.org"
schemaLocation="2-proxy.xsd"/>
Применяя данный проектный подход, нам удалось избежать коллизии имен. Более того, у этого проектного подхода есть еще одно дополнительное преимущество: в рамках проксирующих XML-схем также можно использовать элемент <redefine> для внесения изменения в хамелеон-компоненты.
Таким образом, данный проектный подход регламентирует трехступенчатый процесс:
- создать хамелеон-схемы;
- создать проксирующие XML-схемы для каждой хамелеон-схемы;
- импортировать (<import>) проксирующие XML-схемы в главную.
Использование данного трехступенчатого процесса позволяет более гибко принимать решения в проекте по поводу доменов (пространств имен) тех компонентов, которые используются повторно. Более того, появляется возможность внести изменения в хамелеон-компоненты. Хотя в данном подходе и используется дополнительный шаг процесса (создание проксирующих XML-схем), все же он обладает большой гибкостью.
Сравним данный трехступенчатый процесс с ранее описанным двухступенчатым процессом, в котором компонентам назначаются пространства имен с самого начала существования компонента:
1-fixed.xsd
targetNamespace="http://www.1-fixed.org"
A
B
2-fixed.xsd
targetNamespace="http://www.2-fixed.org"
A
C
main.xsd
targetNamespace="http://www.main.org"
<xsd:import namespace="http://www.1-fixed.org"
schemaLocation="1-fixed.xsd"/>
<xsd:import namespace="http://www.2-fixed.org"
schemaLocation="2-fixed.xsd"/>
Двухступенчатый процесс дает тот же результат, что и трехступенчатый. В данном примере компоненты уже не являются "хамелеонами", и элементы A, B и C жестко привязанны к соответствующим пространствам имен с начала жизненного цикла компонентов. Обратная сторона данного подхода - если в main.xsd понадобится внести изменения в определения компонентов с использованием <redefine>, то это будет невозможно. Кроме того, проектировщик главной XML-схемы вынужден использовать пространства имен, определенные кем-то другим. Эти компоненты являются статичными, неизменяемыми и с фиксированным пространством имен.
Средства, облегчающих использование хамелеон-компонентов
Описание проблемы идентификации хамелеон-компонентов
Мы уже несколько раз наблюдали, что хамелеон-компоненты могут смешиваться в схемах, которые их используют. Это происходит, когда они принимают пространство имен включающих (<include>) их XML-схем. Какими же средствами можно идентифицировать компоненты, которые имеют много представлений, относящихся к различным пространствам имен?
Предположим, существуют следующие XML-схемы без определения пространств имен:
1.xsd
A
B
Далее мы определяем главную XML-схему main.xsd, которая включает (<include>) вспомогательную XML-схему "хамелеон" 1.xsd, а также сама содержит определение элемента с именем A (поскольку он находится в другом символьном окружении - внутри элемента <stuff>, это не приведет к коллизии имен).
main.xsd
targetNamespace="http://www.example.org"
<include schemaLocation="1.xsd"/>
<element name="stuff">
<complexType>
<sequence>
<element name="A" type="xxx"/>
...
</sequence>
</complexType>
</element>
Предположим, в процессе трансформации нам необходимо четко идентифицировать хамелеон-компонент 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-схемы.
Более интересна ситуация (ситуация, которая рассматривалась в качестве примеров), как поступить с пространством имен XML-схем, создаваемых в рамках проекта и полностью подконтрольных одному проектировщику (или группе). Ниже приведено несколько рекомендаций:
Используйте пространство имен типа "хамелеон":
с XML-схемами, которые содержат компоненты, которые не обладают наследственной семантикой сами по себе;
с XML-схемами, которые содержат компоненты, которые обладают семантикой только в контесте главной XML-схемы;
когда нет желания жестко назначать пространство имен для XML-схемы, чтобы иметь возможность назначать проектируемым компонентам спецефическое пространство имен того приложения, в котором они будут использованы.
Пример. Репозиторий таких компонентов как, например, XML-схема, определяющая типы массива, вектора, связанного списка и т. п., должны определяться без указания targetNamespace (то есть как хамелеон-XML-схема).
Если XML-схема содержит только определения типов (отсутствуют декларации элементов), то она также хороший кандидат на использование хамелеон- пространства имен.
Используйте гомогенное пространство имен:
- если все XML-схемы концептуально соотносятся друг с другом;
- если нет необходимости визуально идентифицировать в XML-документе принадлежность элементов и атрибутов той или иной XML-схеме. При данном подходе все компоненты принадлежат одному пространству имен и, таким образом, теряется возможность идентифицировать в XML-документе, что "элемент A определен в схеме X". Часто это нормально, что проектировщик не желает категоризовывать раздельно элементы или атрибуты. В этом случае гомогенное пространство имен вполне подходит.
Используйте гетерогенное пространство имен:
когда имеется несколько элементов с одинаковым именем (с целью предотвратить коллизию имен);
если есть необходимость визуально идентифицировать в XML-документе принадлежность элементов и атрибутов той или иной XML-схеме. При данном подходе компоненты принадлежат различным пространствам имен, и, таким образом, существует возможность идентифицировать в XML-документе, что "элемент A определен в схеме X".
И, наконец, как было продемонстрировано выше, в XML-схемах каждый компонент может быть уникально идентифицирован с использованием атрибута id (это не то же самое, что объявить атрибут id для элемента; это внутренний механизм XML-схем для идентификации каждого компонента XML-схемы). Использование атрибута id для идентификации каждого компонента XML-схемы дает даже больший контроль над компонентом, чем при использовании пространств имен. Комбинация этих двух средств - пространств имен и атрибутов id компонентов XML-схем - мощный тандем, позволяющий надежно идентифицировать комоненты XML-схем, как визуально, так и программно.