XML Schema, в настоящее время приближающаяся к принятию в качестве рекомендации W3C, призвана обеспечить богатую грамматическую структуру для XML-документов и преодолеть ограничения, присущие DTD (см. справа Ограничения DTD). Эта статья демонстрирует гибкость XML Schema и показывает, как определить фундаментальное понятие XML-документов - элемент - в рамках XML Schema.
XML Schema выразительнее DTD. Первые три листинга производят краткое сравнение различных путей представления элементов. Листинг 1 показывает фрагмент XML-документа. Листинг 2 демонстрирует объявление этих двух элементов в синтаксисе DTD, а Листинг 3 соответствующий синтаксис XML Schema. Заметьте, что синтаксис в Листинге 3 совпадает с синтаксисом XML. При использовании XML Schema парсер с проверкой допустимости может удостовериться, что элемент InvoiceNo является положительным целым, а элемент ProductID состоит из одной буквы от A до Z, сопровождаемой шестью цифрами. В отличие от этого, прасер с проверкой допустимости документа, использующий DTD, может лишь проверить, что эти элементы представлены как строки.
<InvoiceNo>123456789</InvoiceNo>
<ProductID>J123456</ProductID>
<!ELEMENT InvoiceNo (#PCDATA)>
<!ELEMENT ProductID (#PCDATA)>
<element name='InvoiceNo' type='positive-integer'/>
<element name='ProductID' type='ProductCode'/>
<simpleType name='ProductCode' base='string'>
<pattern value='[A-Z]{1}d{6}'/></simpleType>
В реальном мире один человек может обрабатывать документы от множества корреспондентов, которые могут хотеть по разному представлять свои данные. Более того, в рамках одногодокумента они могут нуждаться в раздельном обращении к элементам с одними и теми же именами, но в разных контекстах. Как различить друг от друга эти разные определения, имеющие одно и то же имя? XML Schema позволяет различать такие определения с помощью понятия пространства имен.
Ограничения шаблонов DTD Несмотря на то, что шаблоны DTD отлично служили разработчикам SGML и HTML на протяжении 20 лет в качестве механизма описания структурированной информации, шаблоны DTD имеют строгие ограничения по сравнению со XML Schema. DTD требует, чтобы элементы состояли из одного из трех понятий:
|
Данная XML Schema определяет набор новых имен, таких, как имена элементов, типов, атрибутов, групп атрибутов, чьи определения и объявления записаны в схеме. Листинг 3 определяет имена InvoiceNo, ProductID и ProductCode.
Говорят, что имена, определенные в схеме, принадлежат собственному пространству имен. Пространство имен само по себе имеет фиксированное, но произвольное имя, которое должно придерживаться синтаксиса URL. Например, вы можете установить имя пространства имен для схемы, фрагмент которой приведен в Листинге 3 в виде: http://www.SampleStore.com/Account.
Однако даже если пространство имен начинается с http://, оно не является URL файла, содержащего определение схемы. В действительности, URL http://www.SampleStore.com/Account вообще не относится ни к какому файлу, а только к присвоенному имени.
Определения и объявления в схеме могут обращаться к именам, принадлежащим другим пространствам имен. В этой статье мы называем такие пространства имен используемыми пространствами имен (source namespaces). Каждая схема имеет одно собственноепространство имен и, возможно, множество используемых пространств имен. Фактически, каждое имя в данной схеме принадлежит какому-либо пространству имен. Имена для пространств имен могут быть достаточно длинными, однако они они могут быть сокращены до аббревиатуры с помощью синтаксиса объявления xmlns в документе схемы XML. Чтобы проиллюстрировать эти понятия, мы можем кое-что добавить к примерной схеме, как это показано в Листинге 4.
<!--XML Schema fragment in file schema1.xsd-->
<xsd:schema targetNamespace='http://www.SampleStore.com/Account'
xmlns:xsd='http://www.w3.org/1999/XMLSchema'
xmlns:ACC='http://www.SampleStore.com/Account'>
<xsd:element name='InvoiceNo' type='xsd:positive-integer'/>
<xsd:element name='ProductID' type='ACC:ProductCode'/>
<xsd:simpleType name='ProductCode' base='xsd:string'>
<xsd:pattern value='[A-Z]{1}d{6}'/>
</xsd:simpleType>
В XML Schema из Листинга 4 имя targetNamespace
представлено как http://www.SampleStore.com/Accountt
и содержит имена InvoiceNo
, ProductID
, и ProductCode
. Имена schema
, element
, simpleType
, pattern
, string
, и positive-integer
принадлежат используемому пространству имен http://www.w3.org/1999/XMLSchema
, сокращенному до аббревиатуры xsd
с помощью объявления xmlns
. В псевдониме xsd
нет ничего особенного; мы могли выбрать любое имя. Для удобства и простоты далее в статье мы используем xsd
для обращения к пространству имен http://www.w3.org/1999/XMLSchema
и опускаем характеристику xsd
в некоторых фрагментах кода. В этом примере targetNamespace
также оказывается одним из используемых пространств имен, так как имя ProductCode
использовано при определении других имен.
Фрагмент схемы в Листинге 4 не нуждается в специальном определении местоположения файлов исходной схемы. Для общей "схемы схем" http://www.w3.org/1999/XMLSchema
вам нет необходимости определять местоположение , так как оно хорошо известно. Для используемого пространства имен http://www.SampleStore.com/Account
вам не нужно определять местоположение, поскольку это только имя собственного пространства имен, определенного в этом файле. Для лучшего понимания того, как определить местоположение схемы и использовать пространство имен по умолчанию, рассмотрите расширение примера, приведенное в Листинге 5.
<!--XML Schema fragment in file schema1.xsd-->
<schema targetNamespace='http://www.SampleStore.com/Account'
xmlns='http://www.w3.org/1999/XMLSchema'
xmlns:ACC= 'http://www.SampleStore.com/Account'
xmlns:PART= 'http://www.PartnerStore.com/PartsCatalog'>
<import namespace='http://www.PartnerStore.com/PartsCatalog'
schemaLocation='http://www.ProductStandards.org/repository/alpha.xsd'/>
<element name='InvoiceNo' type='positive-integer'/>
<element name='ProductID' type='ACC:ProductCode'/>
<simpleType name='ProductCode' base='string'>
<pattern value='[A-Z]{1}d{6}'/>
</simpleType>
<element name='stickyGlue' type='PART:SuperGlueType'/>
Листинг 5 включает еще одну ссылку на пространство имен: http://www.PartnerStore.com/PartsCatalog
. Это пространство имен отлично от targetNamespace
и от стандартных пространств имен. Поэтому оно должно импортироваться с использованием элемента объявления import
, атрибут schemaLocation
которого определяет местоположение файла, содержащего схему. Пространством имен по умолчанию является http://www.w3.org/1999/XMLSchema
, чье объявление xmlns не имеет имени. Каждое неквалифицированное имя, как, например, schema
и element
, принадлежит пространству имен по умолчанию http://www.w3.org/1999/XMLSchema
. Если ваша схема обращается к нескольким именам из одного пространства имен, удобнее описать его как пространство имен по умолчанию.
Конкретный XML-документ может обращаться к именам элементов из множества пространств имен, определенных во множестве схем. Обратиться к сокращенному имени пространства имен можно используя объявленияме xmlns
. Для определения местоположения файлов мы использовали атрибут schemaLocation
из примера пространства имен схемы XML . Заметьте, что этот атрибут отличается от атрибута с тем же именем schemaLocation
в пространстве имен xsd в предыдущих примерах.
<?xml version="1.0"?>
<ACC:rootElement xmlns:ACC='http://www.SampleStore.com/Account'
xmlns:PART='http://www.PartnerStore.com/PartsCatalog'
xmlns:xsi='http://www.w3.org/1999/XMLSchema-instance'
xsi:schemaLocation='http://www.PartnerStore.com/PartsCatalog'
http://www.ProductStandards.org/repository/alpha.xsd
http://www.SampleStore.com/Account
http://www.SampleStore.com/repository/schema1.xsd'>
<ACC:InvoiceNo>123456789</ACC:InvoiceNo>
Определить элемент означает определить его имя и модель содержания. В XML Schema модель содержания элемента определяется с помощью его типа. При этом отдельные элементы XML-документа могут иметь только значения, удовлетворяющие типам, определенным в их схеме.
Простые типы Спецификация XML Schema определяет набор простых типов, приведенный в Tаблице 2: Предопределеные простые типы. |
Тип может быть простым или сложным. Простой тип не может содержать элементы или атрибуты. Сложный тип может содержать вложенные элементов и атрибуты. (Примеры приведенные выше в этой статье являются простыми типами (см. ProductCode
)). Спецификация XML Schema включает также предопределенные простые типы (см. справа Простые типы). Производный простой тип может принимать значения внутри множества допустимых значений своего базового типа. Например, значения производного простого типа ProductCode
представляют собой подмножество значений базового типа string
.
Элемент, не содержащий атрибутов или других элементов может быть определен как имеющий простой тип, предварительно определен или определен пользователем так, как string
, integer
, decimal
, time
, ProductCode
и др.
<element name='age' type='integer'/>
<element name='price' type='decimal'/>
currency
к простому элементу price
из Листинга 7, то это приведет к ошибке. Элемент простого типа не может иметь атрибуты. Если вы хотите добавить атрибут, вы должны определить price
как сложный тип. В примере Листинга 8 мы определили, что тип называется неименованным (an anonymous type), если не задано явного имени. Другими словами, атрибут name элемента complexType
не определен.
<element name='price'>
<complexType base='decimal' derivedBy='extension'>
<attribute name='currency' type='string'/>
</complexType>
</element>
<!-- In XML instance document, we can write:<price currency='US'>45.50</price> -->
XML-документ |
<Book>
|
DTD |
<!ELEMENT Book (Title, Author)>
|
XML Schema |
<element name='Book' type='BookType'/>
|
Хотя код XML в Tаблице 1 соответствует фрагментам и DTD и XML Schema, между ними есть большое различие. В DTD все элементы глобальные, тогда как XML Schema в этой таблице позволяет локальные элементы Title
и Author
в контексте элемента Book
. Для точного дублирования эффекта объявлений DTD в XML Schema элементы Title
и Author
должны иметь глобальную область видимости, как в Листинге 9. Атрибут ref
элемента element
позволяет Вам обращаться к ранее объявленным элементам.
<element name='Title' type='string'/>
<element name='Author' type='string'/>
<element name='Book' type='BookType'/>
<complexType name='BookType'>
<element ref='Title'/>
<element ref='Author'/>
</complexType>
В примерах Таблицы 1 и Листинга 9 BookType
является глобальным и может использоваться для определения других элементов. В отличие от этого, Листинг 10 определяет BookType
локально в элементе Book
и, кроме того, делает его неименованным. Заметьте, что фрагмент XML-документа в Таблице 1 соответствует всем трем фрагментам схемы в Таблице 1, Листинге 9 и Листинге 10.
<element name='Title' type='string'/>
<element name='Author' type='string'/>
<element name='Book'>
<complexType>
<element ref='Title'/>
<element ref='Author'/>
</complexType>
</element>
XML Schema предоставляет гораздо большую гибкость для задания условий, налагаемых на модель содержания элементов, чем DTD. На простейшем уровне, как в DTD, вы можете связывать атрибуты с элементами и определитьколичество вхождений элементов( только одно , нуля или одного (?), нуля или более (*), или одного или более (+) элементов из данного набора. В XML Schema вы можете выразить также дополнительные ограничения, используя, например, атрибуты minOccurs
и maxOccurs
элемента element
, а также с помощью элементов choice
, group
, и all
.
<element name='Title' type='string'/>
<element name='Author' type='string'/>
<element name='Book'>
<complexType>
<element ref='Title' minOccurs='0'/>
<element ref='Author' maxOccurs='2'/>
</complexType>
</element>
В Листинге 11 появление Title
необязательно в Book
(аналогично '?' в DTD). Тем не менее, Листинг 11 также говорит, что должен быть хотя бы один, но не более двух, авторов в элементе Book
. Значением по умолчанию minOccurs
и maxOccurs
будет 1 для элемента element
. Элемент choice
позволяет появится в примере только одному из своих дочерних элементов. Другой элемент, all
, выражает ограничение, определяющее, что все дочерние элементы в группе могут появляться однажды или не появляться вовсе, и что они могут появляться в любом порядке. Листинг 12 выражает ограничение, обязывающее и Title
и Author
появляться в любом порядке в Book
или не появляться вообще. Такие ограничения трудны для выражения в DTD.
<xsd:element name='Title' type='string'/>
<xsd:element name='Author' type='string'/>
<xsd:element name='Book'>
<xsd:complexType>
<xsd:all>
<xsd:element ref='Tile'/>
<xsd:element ref='Author'/>
</xsd:all>
</xsd:complexType>
</xsd:element>
Мы охватили наиболее фундаментальные понятия, необходимые для определения элементов в XML Schema, дав вам представление о его возможностях с помощью простых примеров. Но имеется и множество гораздо более мощных механизмов:
faset
, вы можете получить новые типы, представляющие подмножества значений других типов. В примере для этой статьи тип ProductCode
был определен с использованием типа pattern
. Подтип может также добавить объявления элементов и атрибутов к базовому типу.
InvoiceType
(тип номера счета-фактуры) не может иметь подтипы, то есть никто не сможет определить новую версию InvoiceType
. Вы можете также выразить то, что в конкретном контексте не может быть замещен ни какой подтип типа ProductCode
.
appInfo
, documentation
и annotation
- для аннотирования схем как для читателей (documentation
), так и для приложений (appInfo
).
Вы можете продолжить исследование схемы XML с помощью документации на сайте W3C (см. Ресурсы) и просматривая для лучшего охвата зону dW XML. Сейчас, когда спецификация схемы XML была принята как рекомендация W3C, ее будет использовать все большее и большее число людей.