Главная · Карта сайта · Поиск · Статьи · Компьютерные курсы · Обучающие программы · Открытые проекты · Веб-программирование · Создание интернет-сайта · Полезные ссылки · Глоссарий · Контакты · Декабрь 09 2016 20:19:18
Последнее опубликованное

Что такое Model-View-Controller
Pattern Model-View-Controller

Как создать свой веб-сайт
Как создать свой сайт в интернете

Разное
Статистика

Язык определения XML схем


Что такое язык определения XML схем

Язык определения XML схем или XSD (XML Schema Definition) – расширение XML, призванное стать основным инструментом описания структуры XML документов. Спецификация XSD является одной из рекомендаций консорциума W3C (World Wide Web Consortium), а не инициативой какой-то отдельной IT компании. Можно также сказать, что с использованием XML схемы можно формализовать набор правил, с соблюдением которых необходимо составлять XML документ конкретного назначения. С помощью сервисов XSD можно также проверить, удовлетворяет ли рассматриваемый документ установленным правилам - является ли он валидным конкретной XML схеме. Базовый синтаксис XML определяет то, каким образом в тексте должны выделяться элементы и их атрибуты, а также, правила описания структурных отношений между элементами. Синтаксис XSD декларирует то, какие именно элементы должны содержаться в XML документе, какой набор атрибутов должен или может иметь каждый из них, и где их место в общей иерархии. Стандарт XSD никоим образом не расширяет базовый синтаксис XML, поскольку каждая XML схема является правильно построенным (well-formed) XML документом.

Основные элементы XSD

Поскольку основными объектами любого XML документа являются элементы, их атрибуты и образованная ими иерархическая структура, то вполне логично, что основные типы элементов XSD - это определение элементов (element), их атрибутов (attribute), а также сложный тип (complexType), который описывает составные элементы и простой тип (simpleType), определяющий элементарные типы данных. Далее нужно быть внимательным, чтобы не запутаться в терминологии.

Элемент имеет простой тип (simpleType), если он не имеет атрибутов, а его содержимое (данные между открывающим и закрывающим тэгом) соответствует элементарному типу данных или просто отсутствует. Соответственно, все остальные элементы имеют сложный тип (complexType). Значения всех атрибутов также соответствуют простым типам. Для описания элемента простого типа достаточно определить его имя (атрибут name), а в качестве типа (атрибут type) указать любой простой тип данных, например строковый (string).

Сложный тип (complexType) определяет сложное содержимое (complexContent) или простое содержимое (simpleContent) элемента. Сложное содержимое – это список атрибутов и набор дочерних элементов. Простое содержимое – это также список атрибутов и простой тип содержимого элемента.

Помимо всего прочего, XSD поддерживает наследование типов. Например, можно описать новый сложный тип, набор атрибутов и дочерних элементов которого расширяет (extension) сложное содержимое базового типа. Можно, наоборот, ввести ограничения (restriction) на значения атрибутов и элементов базового типа. Аналогично можно накладывать ограничение на значения простых типов или расширять их область допустимых значений. Надеюсь, что приведенные далее примеры прояснят ситуацию и снимут все вопросы.

Примеры XML схем

XSD и структурированные наборы данных

В статье о применении XML я писал, что довольно часто его используют для обмена структурированными наборами данных между различными информационными ресурсами. Формироваться эти данные могут операторами (людьми, занимающимися вводом данных) вручную или посредством специальных программных утилит. В любом случае, принимающую сторону сам способ создания набора интересует мало: ей важно убедиться, что переданные ей данные соответствуют определенному формату или набору правил. Проверить это достаточно легко, имея XML схему получаемого документа.

Все примеры, как это обычно бывает на сайте codingcraft.ru, сопровождаются специальными демонстрационными программами, с помощью которых в достоверности написанного легко убедиться. Для этой статьи также создана небольшая утилита, которая позволяет загружать XSD, вводить XML и отслеживать факт его валидности выбранной XML схеме.

Скачать демонстрационную программу.
Скачать Microsoft .NET Framework 3.5 SP1.

Пример XML схемы
Пример XML схемы.

Следующий пример – демонстрация того, как можно организовать передачу личной информации о клиенте некоторой автоматизированной системы, требующей электронную регистрацию.

XSD: Файл client_xsd.rar

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="client" type="client_type" />
  <xs:complexType name="client_type">
    <xs:sequence>
      <xs:element name="name" type="xs:string" />
      <xs:element name="phone" type="phone_type" minOccurs="1" maxOccurs="2" />
      <xs:element name="email" type="email_type" minOccurs="0" maxOccurs="1" />
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="phone_type">
    <xs:restriction base="xs:string">
      <xs:pattern value="^\+\d{1,3}\s?\(\d{3}\)\s?\d{3}(-\d{2}){2}$" />
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="email_type">
    <xs:restriction base="xs:string">
      <xs:pattern value="^[A-Za-z0-9]+(\.\w+)*@([A-Za-z0-9]+\w*)((\.[A-Za-z0-9]+\w*))*\.([A-Za-z0-9]){2,6}$" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

По легенде, XML документ должен содержать имя клиента, контактные телефоны и электронную почту. Для этих целей в XML схеме определен элемент для хранения личных параметров пользователя client сложного типа client_type. Содержимым client_type является последовательность (sequence) простых элементов: name, phone и email. Атрибуты minOccurs и maxOccurs определяют минимальное и максимальное количество вхождений каждого из элементов в последовательность. Телефон должен быть обязательно, но максимум их может быть два. Электронная почта является необязательным элементом (minOccurs=0). Значения minOccurs и maxOccurs по умолчанию – единица, т.е. элемент name должен присутствовать обязательно в единственном экземпляре.

Для контроля корректности вводимого номера телефона и адреса электронной почты я использую регулярные выражения. Чтобы подключить проверку на основе регулярных выражений, необходимо определить собственные типы элементарных данных (simpleType): для phone - phone_type, а для email – email_type. Оба типа являются производными от обычного строкового типа (base=”xs:string”) и сужают (restriction) область допустимых значений посредством шаблона регулярного выражения (pattern). Помимо строкового типа, XSD поддерживает другие элементарные типы: целочисленный тип (integer), вещественный (float, double), логический (boolean), дату (date) и т.д.

Если XSD или XML не соответствуют своим базовым синтаксисам, или XML невалиден XSD, на панели управления отладчика соответствующие кнопки-индикаторы становятся красными. Нажав на них, можно посмотреть описание ошибки.

Пример невалидного XML
Пример невалидного XML.

XSD и интерпретатор бизнес - сценариев

Про саму идею создания интерпретатора бизнес – сценариев на базе XML я кратко написал здесь. В этом разделе я лишь приведу пример XSD схемы, с помощью которой можно описать синтаксис такого XML интерпретатора. На основе следующего примера достаточно легко продемонстрировать примеры наследования сложных типов, рекурсивное определение типа элемента, использование групп, перечислений и ссылок.

XSD: Файл task_xsd.rar

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Task" type="Task_type" />
  <xs:complexType name="Task_type">
    <xs:complexContent>
      <xs:extension base="Parametrized_call">
        <xs:sequence>
          <xs:element name="Main" type="Sequence_type" minOccurs="1" maxOccurs="1" />
        </xs:sequence>
        <xs:attribute name="Name" type="xs:string" use="required" />
        <xs:attribute name="Description" type="xs:string" use="optional" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="Parametrized_call">
    <xs:sequence>
      <xs:element name="In" type="Parameters_def_list" minOccurs="0" maxOccurs="1" />
      <xs:element name="Out" type="Parameters_def_list" minOccurs="0" maxOccurs="1" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="Parameters_def_list">
    <xs:sequence>
      <xs:element name="Parameter" type="Parameter_def" minOccurs="1" maxOccurs="unbounded" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="Parameter_def">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="Name" type="xs:string" use="required" />
        <xs:attribute name="Type" type="Value_enum" use="required" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:simpleType name="Value_enum">
    <xs:restriction base="xs:string">
      <xs:enumeration value="String" />
      <xs:enumeration value="Integer" />
      <xs:enumeration value="Double" />
      <xs:enumeration value="Boolean" />
      <xs:enumeration value="Date" />
    </xs:restriction>
  </xs:simpleType>
  <xs:group name="In_Out">
    <xs:sequence>
      <xs:element name="In" type="Parameters_list" minOccurs="0" maxOccurs="1" />
      <xs:element name="Out" type="Parameters_list" minOccurs="0" maxOccurs="1" />
    </xs:sequence>
  </xs:group>
  <xs:complexType name="Parameters_list">
    <xs:sequence>
      <xs:element name="Parameter" type="Parameter_ref" minOccurs="1" maxOccurs="unbounded" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="Parameter_ref">
    <xs:attribute name="Name" type="xs:string" use="required" />
  </xs:complexType>
  <xs:complexType name="Sequence_type">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="Sequence" type="Sequence_type" />
      <xs:element name="Invoke" type="Invoke_type" />
      <xs:element name="Control" type="Invoke_type" />
      <xs:element name="Call" type="Call_type" />
      <xs:element name="While" type="While_type" />
      <xs:element name="If" type="If_type" />
      <xs:element name="Print" type="xs:string" />
    </xs:choice>
  </xs:complexType>
  <xs:simpleType name="Signature_type">
    <xs:restriction base="xs:string">
      <xs:pattern value="^\w+\.\w+\s+\w+$" />
    </xs:restriction>
  </xs:simpleType>
  <xs:complexType name="Invoke_type">
    <xs:group ref="In_Out" />
    <xs:attribute name="Signature" type="Signature_type" />
  </xs:complexType>
  <xs:complexType name="Call_type">
    <xs:group ref="In_Out" />
    <xs:attribute name="Procedure" type="xs:string" />
  </xs:complexType>
  <xs:element name="Expression" type="Invoke_type" />
  <xs:complexType name="While_type">
    <xs:sequence>
      <xs:element ref="Expression" />
      <xs:element name="Do" type="Sequence_type" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="If_type">
    <xs:sequence>
      <xs:element ref="Expression" />
      <xs:element name="Then" type="Sequence_type" />
      <xs:element name="Else" type="Sequence_type" minOccurs="0" maxOccurs="1" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>

XML: Файл task.rar

<Task Name='Example'>
 <In>
  <Parameter Name='S' Type='String'/>
  <Parameter Name='N' Type='Integer'/>
  <Parameter Name='D' Type='Double'/>
 </In>
 <Out>
  <Parameter Name='Result' Type='Boolean'/>
 </Out>
 <Main>
  <Control Signature="ControlAssebmly.ControlType ControlMethod">
   <In><Parameter Name='S'/></In>
   <Out><Parameter Name='R1'/></Out>
  </Control> 
  <While>
   <Expression Signature="ExpressionWhileAssebmly.ExpressionWhileType ExpressionWhileMethod">
    <In>
     <Parameter Name='N'/>
     <Parameter Name='R1'/>
    </In>
   </Expression>
  <Do>
   <If> 
    <Expression Signature="ExpressionIfAssebmly.ExpressionIfType ExpressionIfMethod">
     <In><Parameter Name='D'/></In>
    </Expression>
   <Then>
    <Invoke Signature="InvokeAssebmly.InvokeType InvokeMethod">
     <In><Parameter Name='D'/></In>
     <Out>
      <Parameter Name='D'/>
      <Parameter Name='Result'/>
     </Out>
    </Invoke>  
   </Then>
   <Else>
    <Call Procedure="ProcedureName">
     <In><Parameter Name='R1'/></In>
     <Out>
      <Parameter Name='R1'/>
      <Parameter Name='Result'/>
     </Out>
    </Call>  
   </Else>
   </If>
   <Print>D</Print>
  </Do>
  </While>
 </Main>
</Task>

Для начала следует описать сам пример. Сразу скажу, что это полностью выдуманный пример, для которого не существует никакого интерпретатора. Здесь я попытался с помощью XML описать хранимую функцию некоего фреймворка, которая на вход принимает три параметра S,N,D, а в качестве результата возвращает логическое значение Result. В теле функции происходит инициализация пользовательского элемента управления (Control) и запуск цикла (While) с предусловием (Expression). В теле цикла (Do) выполняется условный оператор (If). В случае истинности условия (Then) выполняется обращение к внешнему компоненту (Invoke). В случае неистинности условия (Else) выполняется обращение к другой хранимой функции (Call). В ходе практически всех операций осуществляется передача входных (In) и получение выходных параметров (Out), которые, как предполагается, могут изменяться в процессе выполнения этих операций. В конце каждой итерации цикла выполняется вывод на печать (Print) параметра D. Если напрячься, то можно для всего этого выдумать какой-нибудь смысл, но пока цель только одна – продемонстрировать на этом примере возможности XSD.

Для корневого элемента Task определен тип Task_type, который является производным от типа Parametrized_call (параметризованный вызов). Тип Task_type расширяет Parametrized_call элементом Main и двумя атрибутами Name и Description. Атрибут use для каждого атрибута определяет его “обязательность”: атрибут Name является обязательным, а атрибут Description (описание) может отсутствовать. Напомню, что конструкция sequence определяет строгую последовательность дочерних элементов: элемент Main должен строго следовать за элементами, определенными в базовом типе Parametrized_call, а именно за элементами In и Out.

Далее, вплоть до определения простого типа Value_enum нет ничего особенного: определяется тип параметризованного вызова (Parametrized_call), тип списка определений параметров (Parameters_def_list) и тип определения параметра (Parameter_def). Тип Value_enum – это перечисление элементарных типов рассматриваемого XML интерпретатора. Он примечателен тем, что ограничивает (restriction) базовый элементарный тип string, но не на основе шаблона, как в предыдущем примере, а на основе перечисления конкретных значений строк {String, Integer, Double, Boolean, Date}.

Типы списка ссылок на параметры (Parameters_list) и тип ссылки на параметр (Parameter_ref) по легенде используются для передачи ссылок на объявленные ранее в элементе Parametrized_call данные. Ссылки на входные (In) и ссылки на выходные (Out) параметры объединены в группу In_Out, с тем, чтобы при объявлении других, более сложных конструкций не повторяться, а ссылаться на описанную ранее группу по ее имени. Можно то же самое реализовать с использованием наследования, как в случае типа Task_type, но для демонстрации применения групп я выбрал именно такую реализацию. Ссылаются на эту группу тип вызова внешнего компонента (Invoke_type) и тип вызова хранимой функции (Call_type). Для описания ссылки на вызываемый внешний программный компонент тип Invoke_type использует переопределенный элементарный тип Signature_type, накладывающий на область допустимых значений строкового типа фильтр на основе регулярного выражения вызова внешней команды.

Самым сложным XSD типом элементов в рассматриваемом примере является тип последовательности инструкций Sequence_type. Во-первых, содержимое этого типа определяется уже не последовательностью (sequence), а многократным выбором (choice) элементов из некоторого множества. Использование конструкции choice позволяет снять ограничение на строгую последовательность элементов. Количество таких выборов регламентируется атрибутами minOccurs и maxOccurs, и в нашем случае оно ничем не ограничено (minOccurs="0" maxOccurs="unbounded"). Во-вторых, здесь приведен пример рекурсивного определения типа, когда элемент типа Sequence_type является одним из возможных дочерних элементов самого себя (под именем Sequence). Также, тип Sequence_type используется в определении типов составных операторов: цикла While и условного оператора If – рекурсия через одно определение. В заключении призываю обратить внимание на то, как определен элемент логического выражения Expression – он определен отдельно, а сложные типы While_type и If_type на него ссылаются посредством атрибута ref.

XSD и описание пользовательского интерфейса

Заключительный пример этого раздела не проработан подробно, а лишь иллюстрирует саму идею описания пользовательского интерфейса с помощью XML. Идея это не нова и про нее можно кратко прочитать здесь. Цель этого примера - показать еще один способ организации множества дочерних элементов в сложном типе. Конструкция all используется именно для описания множества элементов: порядок появления элементов произвольный, но каждый из них может быть представлен не более чем в одном экземпляре. Попытка, например, определить значение атрибута maxOccurs больше 1 приведет к ошибке.

XSD: Файл interface_xsd.rar

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Interface" type="Interface_type" />
  <xs:complexType name="Interface_type">
    <xs:sequence>
      <xs:element name="Windows" type="Windows_list" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="Windows_list">
    <xs:sequence>
      <xs:element name="Window" type="Window_type" minOccurs="1" maxOccurs="unbounded" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="Window_type">
    <xs:all>
      <xs:element name="Menu" type="xs:string" minOccurs="0" maxOccurs="1" />
      <xs:element name="Toolbar" type="xs:string" minOccurs="0" maxOccurs="1" />
      <xs:element name="Statusbar" type="xs:string" minOccurs="0" maxOccurs="1" />
    </xs:all>
  </xs:complexType>
</xs:schema>

XML: Файл interface.rar

<Interface>
 <Windows>
  <Window>
   <Menu/>
   <Toolbar/>
   <Statusbar/> 
  </Window>
 </Windows>
</Interface>

На этом все. Более подробно про XML схемы можно узнать на сайте их авторов:

W3C: http://www.w3.org/TR/#tr_XML_Schema

или в технической документации Microsoft:

MSDN: http://msdn.microsoft.com/ru-ru/library/ms256235(v=vs.90).aspx


Пример работы с XSD на C# можно посмотреть здесь.



Компьютерные курсы и курсы программирования
Основы программирования

Курс для начинающих программистов на C# и VB.NET.

SQL 25™

Построение SQL запросов и работа с базой данных.

C# Quick Guide™

Программирование на C#. Краткое руководство.

RegEx

Применение регулярных выражений.

Plug-in архитектура

Примеры программной Plug-in архитектуры.

XML и его расширения

Язык разметки XML и его расширения с примерами.

HTML и разметка гипертекста

Языки HTML, XHTML и CSS с примерами разметки.

Основы веб-дизайна

Основы веб-дизайна: решения типовых задач верстки.

Программирование на PHP

Руководство по программированию на PHP для начинающих.

Справочные материалы

Шаблоны проектирования
Каталог шаблонов проектирования программных компонентов.

Рефакторинг кода
Каталог приемов рефакторинга программного кода.

Гость
Имя

Пароль



Забыли пароль?
Запросите новый здесь
.
Coding Craft. Все права защищены © 2011. Проект Инициативного Народного Фронта Образования - ИНФО-проект.