Принципи проектування XML-схем: чи потрібні похідні складні типи, Різне, Інтернет-технології, статті

Фахеем Кан (Faheem Khan)

Незважаючи на те, що в специфікації консорціуму W3C XML Schema міститься ряд конструкцій, що нагадують поняття об’єктно-орієнтованого програмування – у тому числі визначення похідних типів і поліморфізм, реальна практика показує, що вони скоріше ускладнюють схеми, володіючи важко відчутною взаємозв’язком, яка чревата виникненням серйозних проблем, і найчастіше можуть бути замінені іншими конструкціями XML Schema. У цій статті розглянуті визначення похідних складних типів за допомогою накладання обмежень і розширень, показані переваги і недоліки обох підходів, запропоновані альтернативні рішення.

Навіщо перевіряти XML-документи на допустимість

Рекомендація консорціуму W3C “XML Schema“- Це всього лише одна з безлічі специфікацій мов XML-схем: DTD, RELAX NG і XML Data-Reduced. Для опису структури XML-документа в XML-схемі визначаються допустимі елементи, які можуть знаходиться в документі, порядок їх проходження, а також обмеження, що накладаються на певні характеристики цих елементів. Все більш широке поширення мови XML і мов XML-схем виявило два основні сценарії використання XML-схем для перевірки допустимості XML-документа.

  1. Опис і забезпечення дотримання контракту між авторами та одержувачами XML-документів: Зазвичай XML-схема використовується одержувачами і авторами XML-документів в якості засобу для розуміння структури переданого або формованого документа. Схеми – це досить стислий машиночитаних спосіб опису складу допустимого XML-документа, допустимого згідно з окремим XML-словника. Таким чином, схема може розглядатися як контракт між автором і одержувачем XML-документа. Як правило одержувач звіряє переданий XML-документ з цим контрактом, перевіривши його допустимість за схемою.
    Цей опис контракту охоплює широкий спектр сценаріїв використання мови XML, починаючи бізнес-суб’єктами, обмінюються XML-документами, і закінчуючи додатками, в яких використовуються конфігураційні XML-файли.
  2. Формування основи для обробки та зберігання типізованих даних, представлених у вигляді XML-документів: Популярність мови XML як способу подання жорстко структурованих, строго типізованих даних, таких як, наприклад, вміст реляційної бази або об’єктів різних мов програмування, зажадала можливості описувати типи даних елементів XML-документа. В результаті, з’явилися мови схем XML Data і XML Data-Reduced, А потім і XML-схема W3C. Ці мови схем використовуються для перетворення вхідного інформаційного набору XML (XML infoset) в анотований інформаційний набір типів (type annotated infoset (TAI)), у якому інформаційні одиниці елемента і атрибута забезпечені (анотований) іменами типів.
    У рекомендації консорціуму W3C “XML Schema” описується створення анотованого інформаційного набору типів, що з’являється в результаті перевірки допустимості документа за схемою. При перевірці документа по XML-схемі W3C вхідний інформаційний набір XML перетворюється на постверіфікаціонний інформаційний набір (post schema validation infoset (PSVI)), в якому крім усього іншого містяться анотації типів. Однак, практичний досвід показує, що для створення анотованих інформаційних наборів типів не потрібно проведення повної перевірки допустимості документа; як правило, більшість програм, в яких використовуються XML-схеми для формування строго типізованих XML-документів, наприклад, для перетворення XML<->об’єкт, не виконує повною перевірку допустимості документів, оскільки ряд конструкцій XML-схеми W3C не відповідає поняттям предметної області.

У цій статті розглядаються переваги і недоліки визначення похідних складних типів з точки зору їх впливу на зазначені випадки використання XML-схеми.

Розгляд визначення похідних складних типів за допомогою обмежень

При накладенні обмежень на складні типи виходить похідний складний тип, моделлю змісту якого є підмножина моделі змісту його базового типу. Це означає, що екземпляр похідного типу також повинен бути допустимим екземпляром цього базового складного типу. Нижче наведені деякі обмеження, які можна накладати на модель змісту:

Визначення похідного типу допомогою обмежень в основному зручно у поєднанні з абстрактними елементами або типами. Так, можна створити абстрактний тип, який містить всі характеристики ряду пов’язаних моделей змісту, а потім обмежити його для створення кожної з необхідних моделей змісту. Цей прийом був розглянутий в повідомленні Роджера Костелло (Roger Costello), Спрямованого на адресу XML-DEV, в якому він звів PublicationType до MagazineType.

У наведеній нижче схемі, яка була запозичена з попередніх статей, використовується обмеження складного типу для отримання з типу, що характеризує передплатника списку розсилки XML-DEV, типу, що описує автора. В результаті, можна перевірити допустимість будь-якого елемента, відповідного типу DareObasanjo, Як примірника типу XML-Deviant.


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:complexType name="XML-Deviant">
<xs:sequence>
<xs:element name="numPosts" type="xs:integer" minOccurs="0" maxOccurs="1" />
<xs:element name="signature" type="xs:string" nillable="true" />
<xs:element name="email" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="firstSubscribed" type="xs:date" use="optional" />
<xs:attribute name="mailReader" type="xs:string"/>
</xs:complexType>

<xs:complexType name="DareObasanjo">
<xs:complexContent>
<xs:restriction base="XML-Deviant">
<xs:sequence>
<xs:element name="numPosts" type="xs:integer" minOccurs="1" />
<xs:element name="signature" type="xs:string" nillable="false" />
<xs:element name="email" type="xs:string" maxOccurs="0" />
</xs:sequence>
<xs:attribute name="firstSubscribed" type="xs:date" use="required" />
<xs:attribute name="mailReader" type="xs:string" fixed="Microsoft Outlook" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:schema>

Зауважимо, що коли заданий складний тип повинен бути отриманий з іншого складного типу за допомогою обмеження, його модель змісту повинна бути продубльована і перевизначена.

Проблеми, що виникають при визначенні похідних складних типів за допомогою обмежень

У попередній статті “Як уникнути заплутаності” (Avoiding Complexity) із серії “Принципи проектування XML-схем” автор пояснив чому необхідно бути обережним при використанні визначення складних типів за допомогою обмеження:

“Правила визначення складних типів за допомогою накладання обмежень описані в Розділах 3.4.6 і 3.9.6 Рекомендації W3C “XML Schema”. Більшість багів в реалізаціях тісно пов’язані з цією функціональністю, і досить часто при обговоренні різних нюансів отримання таких похідних типів розробники висловлюють найсерйозніше невдоволення. Більш того, цей спосіб визначення похідних типів не повністю відповідає поняттям ні предметно-орієнтованого програмування, ні теорії реляційних баз даних, які є основними споживачами і творцями XML-даних “.

Для того класу користувачів, яким важливий контракт, заснований на перевірці допустимості, отримання похідних типів за допомогою обмеження мало привабливо, якщо взагалі привабливо, порівняно з визначенням моделей змісту без завдання обмежень. Наведена нижче схема є еквівалентом розглянутої вище з тією умовою, що все, що від неї вимагається, це гарантія того, що елемент XML-Deviant (Або DareObasanjo) Відповідає зазначеній моделі даних.


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="XML-Deviant">
<xs:sequence>
<xs:element name="numPosts" type="xs:integer" minOccurs="0" maxOccurs="1" />
<xs:element name="signature" type="xs:string" nillable="true" />
<xs:element name="email" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="firstSubscribed" type="xs:date" use="optional" />
<xs:attribute name="mailReader" type="xs:string"/>
</xs:complexType>
<xs:complexType name="DareObasanjo">
<xs:sequence>
<xs:element name="numPosts" type="xs:integer" minOccurs="1" />
<xs:element name="signature" type="xs:string" nillable="false" />
<xs:element name="email" type="xs:string" maxOccurs="0" />
</xs:sequence>
<xs:attribute name="firstSubscribed" type="xs:date" use="required" />
<xs:attribute name="mailReader" type="xs:string" fixed="Microsoft Outlook" />
</xs:complexType>
</xs:schema>

Варто зауважити, що ця схема не забезпечує відносини між типами XML-Deviant і DareObasanjo. Цей альтернативний підхід незадовільний для тих випадків, коли потрібно підтримувати відношення підтипів.

Для сценаріїв використання, в яких схема застосовується для створення строго типізованого XML, отримання похідних типів за допомогою обмеження загрожує виникненням проблем. В реляційній моделі і традиційних положеннях про визначення похідних типів в об’єктно-орієнтованих мовах програмування відсутня можливість накладати обмеження на факультативні елементи і атрибути. Наведений вище приклад, в якому елемент email є факультативним в базовому типі, а в похідному не може з’являтися, несумісний з нотацією отримання похідного типу з позиції об’єктно-орієнтованого підходу, його також важко змоделювати, використовуючи таблиці реляційної бази даних. Аналогічно, зміна ознаки, що вказує, що модель змісту типу є порожній, не є характеристикою, яка відповідає реляційної або об’єктно-орієнтованої моделям. З іншого боку, приклад, в якому не використовується отримання похідного типу за допомогою обмеження, більш просто моделювати у вигляді класів на мові об’єктно-орієнтованого програмування або у вигляді реляційних таблиць. Це важливо, якщо врахувати, що це зменшує неузгодженість, що виникає при спробі відобразити зміст XML-документа в реляційну базу даних або перетворити його в примірник об’єктно-орієнтованого класу.

Незважаючи на те, що деякі аспекти отримання похідних типів за допомогою обмеження погано перетворюються, їх все ж можна реалізувати безпосередньо, наприклад, генеруючи виняток при спробі звернутися до властивості чи полю в похідному типі, який був вилучений при накладенні обмеження. Однак таке пряме завдання обмежень XML-схеми W3C є неприродним для розробників, які звикли писати на об’єктно-орієнтованих мовах програмування, і малоймовірно, щоб ці правила стали загальноприйнятими у всіх розробників інструментів перетворення XML-схеми W3C.

Розгляд визначення похідних складних типів за допомогою розширення

При розширенні складних типів виходить похідний складний тип, модель змісту якого є розширеним безліччю моделі змісту його базового типу. Іншими словами, до моделі змісту базового типу в складі похідного типу додаються додаткові атрибути або елементи. При цьому додані елементи трактуються так, як ніби вони були послідовно приєднані до моделі змісту базового типу (конструкція sequence). Цей підхід зручний для витягання загальних властивостей з набору складних типів з подальшим використанням цих спільнот за допомогою розширення визначення базового типу.

У наведеній нижче схемі використовується розширення складного типу для отримання з складного типу, що характеризує передплатника списку розсилки XML-DEV, типу, що описує автора. Таким чином, примірник типу DareObasanjo необов’язково є допустимим екземпляром типу XML-Deviant.


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:complexType name="XML-Deviant">
<xs:sequence>
<xs:element name="numPosts" type="xs:integer" minOccurs="0" maxOccurs="1" />
<xs:element name="email" type="xs:string" />
</xs:sequence>
<xs:attribute name="firstSubscribed" type="xs:date" use="optional" />
<xs:attribute name="lastPostDate" type="xs:date" use="optional" />
</xs:complexType>

<xs:complexType name="DareObasanjo">
<xs:complexContent>
<xs:extension base="XML-Deviant">
<xs:sequence>
<xs:element name="signature" type="xs:string" />
</xs:sequence>
<xs:attribute name="mailReader" type="xs:string" fixed="Microsoft Outlook" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>

Проблеми, що виникають при визначенні похідних складних типів за допомогою розширень

Здається, що для користувачів, які хочуть використовувати XML-схему для перевірки XML-документа на відповідність контрактом, визначення похідних складних типів за допомогою розширень є відмінним способом розкласти на компоненти аспекти схеми та повторно скористатися ними. Однак, перше враження оманливе – взаємодія з іншими конструкціями XML-схеми W3C, як, наприклад, групами підстановки (substitution groups) І xsi:type, Перетворює використання визначення похідних складних типів за допомогою розширень в розряд важко контрольованих завдань. Розглянемо, наприклад, таке оголошення елементи:


<xs:element name="xml-deviant" type="XML-Deviant" />

в якому оголошується елемент xml-deviant, Тип якого, XML-Deviant, Є складним типом, описаним у наведеній вище схемі. Обидва XML-елементу, наведені в наступному фрагменті, є допустимими відповідно до цього оголошенням елемента xml-deviant:


<xml-deviant firstSubscribed="1999-05-31" >
<email>johndoe@example.com</email>
</xml-deviant>
<xml-deviant xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="DareObasanjo" firstSubscribed="1999-05-31"
mailReader="Microsoft Outlook">
<email>dareo@online.microsoft.com</email>
<signature>XML is about data not objects, that is the zen of XML.</signature>
</xml-deviant>

Незважаючи на те, що в оголошенні цього елемента явно вказано, що типом елемента xml-deviant є складний тип XML-Deviant, Примірник може заміщати це оголошення у схемі, використовуючи атрибут xsi:type, За умови, що цей новий тип є підтипом первісного типу. Це означає, що за замовчуванням навіть якщо елемент успішно пройшов перевірку на допустимість, він необов’язково відповідає моделі змісту, по якій, як вважає одержувач, він перевіряється. Схожа проблема виникає, коли розглядається оголошення елемента призначається заголовком (head) груп підстановок.

Існує два способи обійти цю потенційну проблему, що виникає при визначенні похідних складних типів за допомогою розширень. Перший полягає в блокуванні підстановки або визначенні похідного типу за допомогою розміщення атрибута block або final в оголошенні елемента або в описі складного типу. Аналогічно, атрибут blockDefault або finalDefault може бути доданий в елемент xs:schema для вказівки, який вид підстановок або визначення похідних типів недозволено в цій схемі. Другий спосіб полягає у використанні пойменованих груп моделей (xs:group) І груп атрибутів для розбиття схеми на модулі – як альтернатива визначення похідних складних типів за допомогою розширень. Нижче наведена схема, яка була розглянута в попередньому розділу і в яку були додані пойменовані групи моделей.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="XML-Deviant">
<xs:group ref="XMLDeviantGrp" />
<xs:attributeGroup ref="XMLDeviantAttrGrp" />
</xs:complexType>
<xs:complexType name="DareObasanjo">
<xs:sequence>
<xs:group ref="XMLDeviantGrp" />
<xs:element name="signature" type="xs:string" />
</xs:sequence>
<xs:attributeGroup ref="XMLDeviantAttrGrp" />
<xs:attribute name="mailReader" type="xs:string" fixed="Microsoft Outlook" />
</xs:complexType>
<xs:group name="XMLDeviantGrp">
<xs:sequence>
<xs:element name="numPosts" type="xs:integer" minOccurs="0" maxOccurs="1" />
<xs:element name="email" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:group>
<xs:attributeGroup name="XMLDeviantAttrGrp">
<xs:attribute name="firstSubscribed" type="xs:date" use="optional" />
<xs:attribute name="lastPostDate" type="xs:date" use="optional" />
</xs:attributeGroup>
</xs:schema>

Для сценаріїв використання, які застосовують строго типізовані XML-документи, визначення похідних складних типів за допомогою розширень являє хоча і відмінний, але споріднений ряд проблем. У випадку, якщо XML-схема використовується в якості основи перетворення між XML і об’єктно-орієнтованої чи реляційної моделями, таке визначення похідних складних типів не виявляється проблематичним. Однак, при обробки таких строго типізованих XML-документів за допомогою мов програмування, що підтримують схему, як, наприклад, XQuery або XSLT 2.0, Виникають певні складнощі. XQuery – це статично типізований мова, а це означає, що очікується, що він виявить помилки, пов’язані з типом, під час компіляції, а не у воремя виконання. Наступний запит, заданий до наведеного вище прикладу, загрожує виникненням проблем:


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) за їх ідеї і допомогу, надані при написанні цієї статті.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*