Языки информационного обмена

Лабораторная работа № 2

Показывать лекцию целиком

Содержание работы

Примеры выполнения лабораторной работы можно скачать здесь
  • Изучить конструкции языка XML, способы описания структуры документа средствами DTD, описания схемы документа на языке XSD. Изучить способы обработки документов XML.
  • Написать по созданной в лабораторной работе № 1 статистической и динамической модели XML документ.
  • Описать структуру документа средствами DTD.
  • Описать схему документа на языке XSD
  • Преобразовать документ средствами XSLT
  • Преобразовать документ с помощью DOM
  • Оформить отчет, включающий постановку задачи, тексты XML, DTD, XSD, XSLT документов, демонстрацию работы программ.
  • Защитить лабораторную работу.
  • Методические указания.

    Синтаксис XML

    Любой XML-документ состоит из следующий частей:

  • Необязательный пролог.
  • Тело документа.
  • Необязательный эпилог, следующего за деревом элементов.
  • Рассмотрим каждую из частей более подробно.

    Пролог

    Пролог состоит из нескольких частей:

  • необязательное объявление XML (XML Declaration) которое заключено между символами <?...?>. Объявление содержит:
  • пометку xml и номер версии (version) спецификации XML;
  • указание на кодировку символов (encoding), в которой написан документ (по умолчанию encoding="UTF-8");
  • параметр standalone который может принимать значения "yes" или "no" (по умолчанию standalone="yes"). Значение "yes" показывает, что в документе содержатся все требуемые декларации элементов, a "no" - что нужны внешние определения DTD.

    Все это вместе может выглядеть следующим образом:

    <?xml version ="1.0" encoding-"windows-1251" standalone="yes"?>.

    Важно отметить, что в объявлении XML только атрибут version является обязательным, все остальные атрибуты могут быть опущены и, следовательно, принимать значения по умолчанию. Так же нужно помнить, что все эти атрибуты следует указывать только в приведенном выше порядке.

  • комментарии.
  • команды обработки.
  • символы пустых пространств.
  • Необязательное объявление типа документа, DTD (Document Type Declaration) которое заключено между символами <!DOCTYPE...> и может занимать несколько строк. В этой части объявляются теги, использованные в документе, или приводится ссылка на файл, в котором записаны такие объявления.

    После объявление типа документа так же могут следовать комментарии, команды обработки и символы пустых пространств.

    Поскольку все эти части необязательны, пролог может быть опущен.

    Тело документа

    Тело документа, состоит из одного или больше элементов. В правильно оформленном XML документе элементы формируют простое иерархическое дерево, в котором обязательно присутствует корневой элемент (root element) в который вложены все остальные элементы документа. Имена элементов должны быть уникальны в пределах документа. Имя корневого элемента считается именем всего документа и указывается во второй части пролога после слова Doctype.

    Элемент начинается открывающим тегом, затем идет необязательное содержимое элемента, после чего записывается закрывающий тег (в отличие от HTML наличие закрывающего тега обязательно, исключением являются элементы без содержания, так называемые пустые элементы, которые могут быть записаны в сокращенной форме: <имя_элемента/> ). В качестве содержимого элемента могут выступать:

  • другие элементы
  • символьные данные
  • ссылки на символы

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

    # код_символа_в_Unicode;.

    Код символа можно записать и в шестнадцатеричном виде. В этом случае перед ним ставится символ "x":

    #xШестнадцатеричный_код_символа;.
  • ссылки на сущности

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

    имя_сущности;.

    Ссылки на сущности указывают программе-анализатору подставить вместо них строку символов заранее заданную в определении типа документа.

  • комментарии

    Если надо вставить в текст документа комментарий либо сделать какой-то фрагмент "невидимым" для программы-анализатора, то его оформляют следующим образом:

    <!--…текст комментария…-->
  • разделы CDATA

    Секция CDATA используется, для того чтобы задать область документа, которую при разборе анализатор будет рассматривать как простой текст, игнорируя любые инструкции и специальные символы. Программа-анализатор не разбивает секцию CDATA на элементы, а считает ее просто набором символов. В отличие от комментариев, содержание данной секции не игнорируется, а передается без изменений на выход программы анализатора, благодаря чему его можно использовать в приложении.

    Секция CDATA начинается со строки <![CDATA[ после которой записывается содержимое секции. Завершается секция двумя закрывающими квадратными скобками и знаком "меньше":

    <![CDATA[ содержание секции ]]>
  • инструкции по обработке.

    Инструкции по обработке содержат указания программе анализатору документа XML. Инструкции по обработке заключаются между символами <? и ?>. Сразу за начальным вопросительным знаком записывается имя программного модуля, которому предназначена инструкция. Затем, через пробел, идет сама инструкция, передаваемая программному модулю. Сама инструкция это обычная строка, которая не должна содержать набор символов "?>", означающий конец инструкции. Примером инструкции по обработке может служить строка объявления XML:

    <?xml version="1.0" encoding="windows-1251"?>

    Эта инструкция предназначена программе, обрабатывающей документ XML. Инструкция передает ей номер версии и кодировку, в которой записан документ.

  • Открывающие теги либо теги пустых элементов в XML могут содержать атрибуты, представляющие собой пару имя=значение. В одном открывающем теге разрешается использовать только один экземпляр имени атрибута. Атрибуты могут содержать ссылки на объекты, ссылки на символы, текстовые символы. В отличие от языка HTML, в XML значения атрибутов обязательно надо заключать в апострофы ('), либо в кавычки ("). Таким образом, атрибут может быть записан в одном из двух форматов:

    имя_атрибута="значение_атрибута"
    имя_атрибут= 'значение_атрибута'.

    Описание структуры документа средствами DTD

    Для связывания декларации DTD с экземпляром документа в версии XML 1.0 предлагается специальная декларация DOCTYPE.

    Декларация DOCTYPE содержит ключевое слово DOCTYPE, за которым следует имя корневого элемента документа, а затем конструкция с декларациями содержания.

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

    Блок внутренней декларации разметки тега DOCTYPE состоит из левой квадратной скобки, списка деклараций и правой квадратной скобки:

    <! DOCTYPE root_element_name  […здесь находятся декларации внутреннего подмножества ... ]>

    Для внешних DTD декларация DOCTYPE состоит из обычного ключевого слова и имени корневого элемента, за которым следует еще одно ключевое слово SYSTEM либо PUBLIC, обозначающее источник внешнего определения DTD, а за ним - локализация этого определения.

    Допустимое в документе XML содержание определяется с помощью четырех типов декларации разметки в DTD. В следующей далее таблице показаны связанные с этими декларациями ключевые слова и их значения. Первые два типа связаны с информацией, которую мы рассчитываем найти в документе XML, - элементами и атрибутами. Последние два типа используются для поддержки. Особенно облегчают жизнь разработчика словаря XML сущности. Как правило, они состоят из содержания, которое настолько часто используется в DTD или документе, что оправдывает создание специальной декларации. Применение этой декларации напоминает оператор include в языках C/C++, когда в качестве замены для содержания используется имя. Нотации описывают содержание, разработанное не на языке XML. Используются они для того, чтобы объявить конкретный класс данных и связать его с внешней программой.

    Конструкция DTD Значение
    ELEMENT Декларация типа элемента XML
    ATTLIST Декларация атрибутов, которые могут быть назначены конкретным типам элементов, а также разрешенных значений этих атрибутов
    ENTITY Декларация повторно используемого содержания
    NOTATION Декларация форматирования для внешнего содержания, которое не должно быть проанализировано (например, двоичные данные), а также для внешних приложений, обрабатывающих содержание

    Рассмотрим более подробно первые два типа декларации разметки в DTD.

    В документе XML должен быть описан каждый элемент. Объявление элемента начинается с символов <!ELEMENT, после которых через пробел идет имя элемента и его содержимое. Заканчивается объявление символом "больше". По своему содержанию элементы делятся на четыре группы.

  • Пустой элемент - может иметь атрибуты, но не содержит текст или порожденные элементы. Объявляется следующим образом: после имени элемента указывается ключевое слово EMPTY.
    Пример:
    <!ELEMENT element_name EMPTY>
  • Элемент содержит только порожденные элементы, но не текст. Объявляется следующим образом: после имени элемента в скобках через запятую перечисляются все вложенные элементы. Причем вложенные элементы должны следовать в XML документе в том порядке, в каком они перечислены в объявлении.
    Пример:
    <ELEMENT element_name ( elem_1,elem_2)>
  • Элемент содержит не только порожденные элементы, но и текст. Объявляется следующим образом: после имени элемента в скобках указывается ключевое слово #PCDATA, после которого через запятую, как и в предыдущем случае, перечисляются все вложенные элементы (если они имеются).
    Пример:
    <ELEMENT element_name (#PCDATA, elem_1,elem_2)>
    <ELEMENT element_name (#PCDATA)>
  • Элемент, открытый для любого содержания. Объявляется следующим образом: после имени элемента указывается ключевое слово ANY.
    Пример:
    ELEMENT element_name  ANY>
  • Иногда из нескольких вложенных элементов или списков (список элементов указанных в скобках) может встретиться только один. В таком случае их имена перечисляются через вертикальную черту( | ). Например:

    <!ELEMENT element_name (elem_1,(elem_2|elem_3))> - элемент element_name должен
      содержать элемент elem_1, а затем либо elem_2, либо elem_3. 
        Элементы появляются именно в таком порядке.

    Если вложенный элемент можно записать в объявляемом элементе несколько раз, то необходимо это указать использую звездочку, плюс или вопросительным знак.

    ? - элемент или список может встретиться нуль или один раз;

    * - элемент или список может встретиться нуль или несколько раз;

    + - элемент или список может встретиться один или несколько раз.

    После объявления элемента объявляются его атрибуты. Все атрибуты одного элемента объявляются сразу, одним списком. Список начинается с символов <!ATTLIST, после них через пробел следует имя элемента, к которому относятся атрибуты. Затем идет имя атрибута, его тип или список значений, которые он может принимать (все значения перечисляются через вертикальную черту, в скобках), признак обязательности присутствия атрибута в элементе или значение по умолчанию (это значение будет использовано, если атрибут не записан явно в XML документе).

    Тип атрибута записывается одним из ключевых слов:

  • CDATA - строка символов.
  • ID - уникальный идентификатор, однозначно определяющий элемент, в котором встретился этот атрибут; значения такого атрибута не должны повторяться в документе. Они играют ту же роль, что и первичные ключи в таблицах баз данных.
  • IDREF - идентификатор, содержащий одно из значений атрибутов типа id, используется в качестве ссылки на другие элементы.
  • IDREFS - идентификатор, содержащий набор значений атрибутов типа id, перечисленных через пробелы; тоже используется в качестве ссылки сразу на несколько элементов.
  • ENTITY - имя непроверяемой анализатором сущности объявленных в этом же описании DTD.
  • ENTITIES - имена непроверяемых сущностей.
  • NMTOKEN - слово, содержащее только символы, применяемые в именах. Атрибуты этого типа могут содержать имена других элементов или атрибутов, например, для того чтобы ссылаться на них.

  • NMTOKENS - слова, перечисленные через пробелы.
  • NOTATION - обозначение расшифрованное в описании DTD.
  • Признак обязательности записывается с использование ключевых слов:

  • #REQUIRED - атрибут надо обязательно записывать в элементе;
  • #IMPLIED - атрибут необязателен, у него нет значения по умолчанию;
  • #FIXED - у атрибута есть только одно значение, которое записывается тут же, через пробел.
  • Пример:
    <!ATTLIST city type (город | поселок | деревня) "город">
    <!ATTLIST pre xml:lang NMTOKEN "ru_RU">
     <!ATTLIST pre xml:space (default | preserve) "preserve">

    Описание схемы документа на языке XSD

    Связать XML документ с его XSD схемой можно разными способами:

  • подать файлы со схемой на вход анализатора.
  • задать файлы со схемой как свойство анализатора.
  • указать прямо в документе XML.
  • Рассмотрим 3 способ более подробно.

    Если элементы документа не принадлежат никакому пространству имен и записаны без префикса, то в корневом элементе документа записывается атрибут noNamespaceSchemaLocation, указывающий расположение файла со схемой в форме URI:

    < root_element_name xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance 
      xsi:noNamespaceSchemaLocation="file_name.xsd">

    В этом случае в схеме не должно быть целевого пространства имен.

    Если же элементы документа относятся к некоторому пространству имен, то применяется атрибут schemaLocation, в котором через пробел перечисляются пространство имен и расположение файла со схемой, описывающей это пространство имен.

    Элементы, из которых будет состоять документ XML, объявляются в схеме компонентом element:

    <xsd:element_name="имя элемента" tуре="тип элемента" 
    minOccurs="Haменьшее число появлений элемента в документе" 
    maxOccurs="наибольшее число появлений" />

    Значение по умолчанию необязательных атрибутов minOccurs и maxOccurs равно 1. Это означает, что если эти атрибуты отсутствуют, то элемент должен появиться в документе XML ровно один раз.

    Указание типа элемента в атрибуте type удобно, если это встроенный простой тип или тип, определенный заранее. Тогда в атрибуте type можно записать только имя типа.

    Если же тип элемента определяется здесь же, то определение типа элемента лучше вынести:

    <xsd:element name="имя элемента">

    Определение типа элемента

    </xsd:element>

    Объявление атрибута элемента тоже несложно:

    <xsd:attribute name=" имя атрибута" type="тип атрибута" 
      use="обязательность атрибута" 
        default="значение по умолчанию" />

    Необязательный атрибут use принимает три значения:

  • optional - описываемый атрибут необязателен (это значение по умолчанию);
  • required - описываемый атрибут обязателен;
  • prohibited - описываемый атрибут неприменим. Это значение полезно при определении подтипа, чтобы отменить некоторые атрибуты базового типа.
  • Определение типа атрибута, - а это должен быть простой тип, - можно вынести в содержимое элемента attribute:

    <xsd:attribute name="имя атрибута">

    Тип атрибута

    </xsd:attribute>

    Определение простых типов

    Простой тип в схемах XML определяется компонентом схемы simpleType, имеющим вид

    <xsd:simpleType name="имя типа" >Определение типа</xsd:simpleType"

    Определение новых типов простых элементов

    Кроме встроенных типов в схемах XML можно определить новые типы простых элементов. Они вводятся как

  • сужение (restriction) встроенного или ранее определенного простого типа,
  • список (list) простых типов
  • объединение (union) простых типов.
  • Сужение простого типа определяется компонентом restriction, в котором атрибут base указывает сужаемый простой тип, а в содержимом задаются ограничения, выделяющие определяемый простой тип.

    Теги задающие ограничения, называются фасетками ( facets ). Вот их список:

  • <maxExclusive> - наибольшее значение, которое уже не входит в определяемый тип;
  • <maxInclusive> - наибольшей значение определяемого типа;
  • <minExclusive> - наименьшее значение, уже не входящее в определяемый тип;
  • <minInclusive> - наименьшее значение определяемого типа;
  • <totalDigits> - общее количество цифр в определяемом числовом типе - сужении типа decimal;
  • <fractionDigits> - количество цифр в дробной части числа;
  • <length> - длина значений определяемого типа;
  • <maxLength> - наибольшая длина значений определяемого типа;
  • <minLength> - наименьшая длина значений определяемого типа;
  • <enumeration> - одно из перечислимых значений;
  • <pattern> - регулярное выражение;
  • <whitespace> - применяется при сужении типа string и определяет способ преобразования пробельных символов <'>\n<'>, <'>\r<'>, <'>\t. Атрибут value этого тега принимает одно из трех значений:
  • preserve - не убирать пробельные символы;
  • replace - заменить пробельные символы пробелами;
  • collapse - после замены пробельных символов пробелами убрать начальные и конечные пробелы, а из нескольких подряд идущих пробелов оставить только один.
  • В тегах-фасетках можно записывать следующие атрибуты, называемые базисными фасетками ( fundamental facets ):

  • ordered - задает упорядоченность определяемого типа, принимает одно из трех значений:
  • false - тип неупорядочен;
  • partial - тип частично упорядочен;
  • total - тип полностью упорядочен;
  • bounded - задает ограниченность или неограниченность типа значением true или false;
  • cardinality - задает конечность или бесконечность типа значением finite или countably infinite;
  • numeric - показывает, числовой этот тип или нет, значением true или false.
  • Список определяется компонентом list, в котором атрибутом itemType указывается тип элементов определяемого списка. Тип элементов списка можно определить и в содержимом элемента list.

    При определении списка можно применять фасетки <length>, <minLength>, <maxLength>, <enumeration>, <pattern>.

    Простой тип-объединение определяется компонентом union, в котором атрибутом memberTypes можно указать имена объединяемых типов. Например:

    <xsd: union memberTypes="xsd: string xsd; integer lisstOfInteger" />

    Другой способ - записать в содержимом компонента union определения простых типов, входящих в объединение.

    Определение сложных типов

    Тип элемента называется сложным, если в элемент вложены другие элементы и/или в открывающем теге элемента есть атрибуты.

    Сложный тип определяется компонентом complexType, имеющим вид:

    <xsd:complexType name="имя типа" >

    Определение типа

    </xsd:complexType>

    Необязательный атрибут name задает имя типа, а в содержимом компонента complexType описываются элементы, входящие в сложный тип, и/или атрибуты открывающего тега.

    Определение сложного типа можно разделить на три группы:

  • определение типа пустого элемента (элемента, не содержащего тела, а содержащего только атрибуты в открывающем теге).

    Каждый атрибут объявляется одним компонентом attribute, например:

    <xsd:complexType name="imageType">
    <xsd:attribute name="href" type="xsd:anyURI" />
    </xsd:complexType>
  • определение типа элемента с простым телом (элемента, содержащего тело простого типа и атрибуты в открывающем теге).

    Этот тип отличается от простого типа только наличием атрибутов и определяется компонентом simpleContent. В теле этого компонента должен быть либо компонент restriction, либо компонент extension. Атрибутом base задают тип (простой) тела описываемого элемента.

    В компоненте extension указываются атрибуты открывающего тега описываемого элемента.

    В компоненте restriction, кроме атрибутов, описывается простой тип содержимого элемента и/или фасетки, ограничивающие тип, заданный атрибутом base.

  • определение типа элемента, содержащего вложенные элементы.

    Если значениями определяемого сложного типа будут элементы, содержащие вложенные элементы, то перед тем, как перечислять их описания, надо выбрать модель группы (model group) вложенных элементов. Дело в том, что вложенные элементы, составляющие определяемый тип, могут появляться или в определенном порядке, или в произвольном порядке, кроме того, можно выбирать только один из перечисленных элементов. Эта возможность и называется моделью группы элементов. Она определяется одним из трех компонентов: sequence, all или choice.

    Компонент sequence применяется в том случае, когда перечисляемые элементы должны записываться в документе в определенном порядке.

    Если же вместо компонента xsd:sequence записать компонент xsd:all, то элементы можно перечислять в любом порядке.

    Компонент choice применяется в том случае, когда надо выбрать один из нескольких элементов.

  • Определение типа элемента со сложным телом

    При определении сложного типа можно воспользоваться уже определенным, базовым, сложным типом, расширив его дополнительными элементами, или, наоборот, удалив из него некоторые элементы. Для этого необходимо применить компонент complexContent. В этом компоненте, так же как и в компоненте simpleContent, записывается либо компонент extension, если надо расширить базовый тип, либо компонент restriction, если нужно его сузить. Базовый тип указывается атрибутом base, так же как и при записи компонента simpleContent, но теперь это должен быть сложный, а не простои тип. При сужении базового типа компонентом restriction надо перечислить те элементы, которые останутся после сужения.

  • Преобразование документов средствами XSLT

    Язык преобразований XSLT - это одна из реализации XML. Все элементы XML, объявленные в языке XSLT, относятся к пространству имен http://www.w3.org/1999/XSL/Transform. Обычно они записываются с префиксом xsl. Если принят этот префикс, то корневой элемент документе XSLT - таблицы стилей- будет называться xsl:stylesheet у которого есть один обязательный атрибут version, указывающий версию языка.

    Таблицу стилей можно записать в файл с расширением xsl. Ссылку на таблицу стилей можно поместить в документ XML как одну из инструкций по обработке, а именно инструкцию xml-stylesheet. Пример такой ссылки приведен ниже.

    <?xml version="1.0"" encoding="windows-1251" ?>
    <?xml-stylesheet type="text/xsl" href="simple.xsl"?>
    <book>
    <!-- содержание -->
    </book>

    "Увидев" инструкцию по обработке xml-stylesheet, программа-обработчик XML, если она, кроме того, является процессором XSLT, выполнит преобразование, заданное в таблице стилей.

    Так же таблицу стилей можно записывать не в отдельный файл, а непосредственно в преобразуемый документ XML. Для этого в элементе xsl:stylesheet предусмотрен атрибут-идентификатор id, на который можно ссылаться обычным образом из инструкции по обработке xml-stylesheet.

    <?xml version="1.0" encoding="windows-1251" ? >
    <?xml-stylesheet type="text/xsl" href=v#simple"?>
    <book>
    <xsl:stylesheet version="1.0" id="simple" 
                     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- преобразования -->
    </xsl:stylesheet>
    <!-- содержание -->
    </book>

    Рассмотрим некоторые элементы языка XSLT.

    Декларация xsl:import

    Элемент xsl:import записывается очень просто:

    <хsl:import href="адрес URI таблицы стилей" />

    Его можно записать только непосредственно в корневом элементе xsl:stylesheet и только в самом начале таблицы стилей. Элементов xsl: import может быть несколько.

    Процессор XSLT отыскивает таблицу стилей по указанному атрибутом href адресу и подставляет ее на место элемента xsl:import перед преобразованием.

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

    Декларация xsl:include

    Второй элемент, включающий внешние таблицы стилей в данную таблицу, - это элемент xsl:include. Он записывается точно так же, как элемент xsl:import, и оказывает такое же действие:

    <xsl:include href="адрес URI таблицы стилей" />

    Его можно записать не только непосредственно в корневом элементе xsl:stylesheet, но, в отличие от элемента xsl:import, в любом месте таблицы стилей. Второе отличие от элемента xsl:import заключается в том, что порядок записи элементов xsl:include в таблице стилей не имеет значения.

    Декларация xsl:variable

    Элемент xsl:variable определяет имя объекта. Оно записывается обязательным атрибутом name. Имя объекта должно быть уточненным именем XML типа QName. Кроме того, атрибутом select переменной можно задать сам объект, а атрибутом as определить тип объекта. Например:

    <xsl:variable name="var1" select="count(//person) " as="xs:integer" />

    Имя var1 будет хранить число элементов person. Объект может быть получен из содержимого элемента xsl: variable:

    <xsl: variable name="var2">10</xsl:variable>

    или создан конструктором последовательности:

    <xsl:variable name="var3">
    <xsl:value-of select="count (//person) " /> 
    <xsl:variable>

    Если объект не получен из атрибута select или содержимого элемента xsl: variable, то по умолчанию имя связывается с пустой строкой.

    Для того чтобы получить объект, связанный с именем, определенным элементом xsl: variable, перед именем надо поставить знак доллара: $varl, $var2. При этом следует учитывать область действия имени.

    Область действия имени простирается на весь элемент, в котором оно определено, начиная с места определения и включая вложенные элементы, если только в них не определено то же самое имя.

    Имена, определенные непосредственно в корневом элементе xsl:stylesheet, называются глобальными именами, остальные - локальными именами.

    Хотя слово "variable" и переводится с английского языка как "переменная", имя, созданное элементом xsl: variable - это не имя переменной, его значение нельзя изменить. Это только название некоторого объекта, которое удобно использовать в тех случаях, когда объект надо использовать во многих местах таблицы стилей, а его вычисление сложно или громоздко.

    Декларация xsl:param

    Элемент xsl:param записывается или непосредственно в элементе xsl:stylesheet, чтобы задать параметр преобразования, или в элементе xsl:template, чтобы задать параметр правила, или в элементе xsl:function как аргумент функции. У него один обязательный атрибут name, определяющий имя параметра. Кроме него, часто присутствует необязательный атрибут select, в котором записывается выражение для получения значения параметра:

    <xsl:param name="pl" select="10 + 20" />

    Если атрибут select отсутствует, то значение параметра берется из содержимого элемента, которым может быть конструктор последовательности узлов и атомарных значений:

    <xsl:param name="p2">10</xsl:param>

    Если отсутствует и атрибут select, и содержимое элемента, то параметр получает значение пустой строки.

    Дли получении значения параметра надо записывать его имя со знаком доллара: $p1, $p2. Например:

    <xsl:when test= "$p1=10 ">

    Правила, определяющие область видимости параметров, такие же, как и у имен объектов, определенных декларацией xsl:variable.

    Еще один необязательный атрибут as содержит желательный тип, к которому будет приведено значение параметра.

    Наконец, последний атрибут required, принимающий значения yes или nо (по умолчанию), указывает обязательность параметра. Если параметр обязателен, required="yes", то элемент xsl:param должен быть пустым и не содержать атрибут select. В таком случае он получит определенное значение при вызове функции или элементом xsl:with-param при вызове шаблона.

    Элемент xsl:with-param

    Элемент xsl:with-param ссылается на некоторый параметр, имя которого записано в обязательном атрибуте name. Необязательным атрибутом select можно задать выражение, результат вычисления которого будет новым значением параметра:

    <xsl:with-param name="pl" select="100 * 20" />

    Новое значение можно задать и в содержимом элемента:

    <xsl:with-param name="pl">100</xsl:with-param>

    Элемент xsl:with-param используется только в инструкциях xsl:apply-templates, xsl:apply-imports, xsl:call-template.

    Инструкция xsl:value-of

    Элемент xsl:value-of вычисляет выражение, записанное в его обязательном атрибуте select, и преобразует его в строку. Например, выше мы определили имя объекта var2. Чтобы получить значение объекта var2, надо записать:

    <xsl:value-of select="$var2" />

    Если в результате вычисления выражения получается последовательность, то процессор XSLT версии 1.0 выберет из нее только первый элемент, преобразованный в строку.

    Инструкции управления xsl:if, xsl:for-each, xsl:choose

    Элемент xsl:if запускает конструктор последовательности, содержащийся в его теле, только если истинно выражение, записанное в обязательном и единственном атрибуте test:

    <xsl:if test="$x > $у">
    <xsl:value-of select="$x"o/> больше <xsl:value-of select="$y" />
    </xsl:if>  '

    У элемента xsl:for-each в обязательном и единственном атрибуте select записывается выражение, дающее в результате последовательность. Для каждого члена этой последовательности выполняется конструктор, содержащийся в теле элемента xsl:for-each. В результате получается цикл, выполняющийся столько раз, сколько элементов у последовательности, полученной в результате вычисления выражения атрибута select.

    У элемента xsl:choose нет ни одного атрибута, но в его теле записывается один или несколько элементов xsl: when и один необязательный элемент xsl:otherwise:

    <xsl:choose>
    <xsl when test="$day=l">Понедельник</xsl:when>
    <xsl when test="$day=2">Bторник</xsl:when>
    <xsl when test="$day=3">Cреда</xsl:when>
    <xsl when test="$day=4">Четверг</xsl:when>
    <xsl when test="$day=5">Пятница</xsl:when>
    <xsl when test="$day=6">Cy66oтa</xsl:when>
    <xsl when test="$day=7">Bocкpeceнье</xsl:when>
    <xsl otherwise>Ошибка определения дня нeдeли</xsl:otherwise>
    </xsl:choose>

    У элемента xsl:when есть только один обязательный параметр test, содержащий логическое выражение, и тело, содержащее конструктор последовательности.

    Элемент xsl: otherwise не имеет атрибутов, у него есть только тело, содержащее конструктор последовательности.

    В инструкции xsl: choose всегда выполняется не больше одного варианта, Варианты xsl:when просматриваются в порядке их написания в инструкции xsl:choose. Как только будет найден вариант с истинным значением выражения test, он будет выполнен, и результат этого варианта будет результатом всей инструкции. Варианты, следующие за ним по порядку, не рассматриваются. Если ни один вариант не подойдет, то результатом инструкции будет результат конструктора, записанного в элементе xsl:otherwise. Если элемента xsl:otherwise в инструкции нет, то результатом будет пустая строка.

    Декларация xsl:function

    Элемент xsl:function позволяет описывать самые настоящие пользовательские функции. Имя функции записывается в обязательном атрибуте nаmе, (аргументы функции задаются элементами xsl:param, а тело функции - это конструктор последовательности, записанный в содержимом элементе xsl:function. Результатом функции будет последовательность, созданная конструктором. Тип функции можно указать необязательным атрибутом аs.

    Имя функции - это уточненное имя типа QName, причем оно должно обязательно записываться с префиксом.

    Все аргументы функции позиционные, следовательно, все элементы xsl:param должны быть записаны в начале тела функции и порядок их записи имеет значение при вызове функции. У аргументов функции не может быть значений по умолчанию, следовательно, элементы xsl:param должны быть пустыми и у них не должно быть атрибутов select. Например:

    <xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:usr="http://myexamples.com"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl: function nаme= " usr:sum "  as="xsl:integer">
    <xsl:param name="x" as="xsl:integer" />
    <хsl:раrаm name="y" as="xsl:integer" />
    <xsl:value-of select="$x + $y" /> 
    </xsl:function>

    вызвать функцию можно в любом выражении подходящего типа, записав ее имя и аргументы в скобках. Например:

    <хsl:value-of select="10 + 2 * usr:sum(2, 3)" />

    Функция может вызываться рекурсивно.

    Декларация xsl:template

    Элемент xsl:template определяет шаблонное правило преобразования. Своим атрибутом match он задает образец для отбора узлов, подлежащих преобразованию, а в теле содержит конструктор последовательности узлов и атомарных значений, которая и будет результатом преобразования отобранных по образцу узлов.

    <xsl: template match=" Образец" name="Имя">Конструктор</хsl:template>

    Каждый из атрибутов match и name не обязателен, но хотя бы один из них должен присутствовать.

    Атрибут match содержит образец для отбора преобразуемых узлов.

    Атрибут name определяет имя шаблона. Имя шаблона - это обычное уточненное имя XML типа QName. Шаблон можно вызвать по имени элементом xsl:call-template, а если он не содержит атрибута match, то такой вызов обязателен, поскольку неизвестны узлы, к которым его надо применить, и он не будут применяться автоматически. Очень часто именованный шаблон содержит параметры, заданные элементами xsl:param, и вызывается с различным параметрами совсем как обычная функция.

    У элемента xsl: template могут быть дополнительные атрибуты mode, as, priority.

    Атрибут mode определяет режим обработки.

    Атрибут as указывает желаемый тип результата (полученная последовательность будет приведена к этому типу).

    Атрибут priority назначает правилу приоритет, который будет учитываться при отборе правил, применимых к некоторому узлу.

    При вызове именованного шаблона элементов xsl:call-template атрибуты match, mode и priority игнорируются.

    Если у именованного шаблона нет атрибута match, то у него не должно быть и атрибутов mode и priority, в них просто нет никакого смысла.

    Инструкция xsl:apply-templates

    Элемент xsl:apply-templates, записываемый чаще всего внутри элемента xsl: template, в простейшем виде пуст:

    <xsl:apply-templates />

    Он предписывает обработать рекурсивно все узлы-потомки узлов, отобранных родительским элементом xsl:template.

    У элемента xsl:apply-templates есть необязательные атрибуты select и mode.

    Атрибут select, значением которого должно быть выражение, дающее последовательность узлов, ограничивает обработку только указанными в нем узлами.

    Атрибут mode выбирает режим обработки из режимов, уже определенных в элементах xsl:template. Режим - это любое имя типа QName, но два режима предопределены. Это текущий режим, отмечаемый словом #current, и режим по умолчанию, принимаемый при отсутствии атрибута mode, или отмечаемый явно словом #default.

    Содержимым элемента xsl: apply-templates могут служить элементы xsl:sort и xsl:with-param.

    Инструкция xsl:for-each-group

    Элемент xsl:for-each-group отбирает последовательность узлов и атомарных значений своим обязательным атрибутом select и группирует ее элементы по признаку, заданному выражением, записанным в атрибуте group-by. Этот признак называется ключом группы. Ключ группы вычисляется заново для каждого элемента последовательности. В результате исходная последовательность, отобранная атрибутом select, разбивается на несколько последовательностей. В следующем примере в одну группу собираются все узлы-элементы name с одинаковым значением атрибута surname:

    <xsl:for-each-group select="name" group-by="@surname">

    Выражение, являющееся значением атрибута group-by, может давать несколько ключей группы, и один узел может попасть сразу в несколько групп. Например:

    <xsl:for-each-group select="name" group-by="(@second, @surname)">

    Второй способ разбить последовательность на группы дает атрибут group-adjacent. Он собирает в группу все подряд идущие элементы последовательности с одинаковым значением ключа. Такой отбор возможен, если в атрибуте group-adjacent содержится только один ключ группы. Процессор XSLT следит за тем, чтобы значением атрибута group-adjacent был один и только один ключ группы.

    Третий и четвертый способы применимы к последовательностям, состоящим только из узлов, без атомарных значений. Эти способы применяют атрибут group-starting-with или атрибут group-ending-with. Значением этих атрибутов может быть не любое выражение, а только образец. В одну группу собираются все подряд идущие узлы, первый (последний) из которых удовлетворяет образцу. Остальные узлы из этой группы не будут удовлетворять образцу. Если несколько подряд идущих элементов последовательности удовлетворяют образцу, то они попадут в разные группы.

    Итак, группы узлов создаются одним из четырех атрибутов элемента xsl:for-each-group: group-by, group-adjacent, group-starting-with, group-ending-with. В каждом элементе xsl:for-each-group должен быть один и только один из этих атрибутов. Полученные группы существуют и могут использоваться только в содержимом элемента xsl:for-each-group. В теле элемента xsl:for-each-group записывается конструктор последовательности, который выполняется по одному разу для каждой группы.

    Для удобства работы с группами в язык XSLT введены функции current-group() и current-group-key ().Их можно использовать только в теле элемента xsl:for-each-group. У обеих функций нет аргументов. Результатом функции current-group() будет последовательность- текущая группа, а результатом функции current-group-key() - значение ключа текущей группы.

    Последовательность преобразований

    Теперь, после краткого описания основных элементов языка XSLT, можно понять, каким образом они выполняют преобразование документа XML.

    Документ XSLT - таблица стилей -состоит из шаблонных правил преобразования, записанных элементами xsl:template. В каждом правиле атрибутом match перечисляется последовательность исходных узлов, для преобразования которых предназначено данное правило, а в содержимом элемента хml:template задается конструктор последовательности преобразованных узлов. Из каждого узла исходного дерева получается один или несколько узлов преобразованного дерева. Порядок записи правил не имеет значения, поскольку для каждого узла исходного дерева просматривается вся таблица стилей в поисках подходящего правила.

    Применение правил преобразования

    Обычно просмотр исходного документа XML начинается с его корневого узла. Для него подбирается правило преобразования, конструктор которого явно или неявно создает корневой узел преобразованного документа. Затем конструктор создает последовательность узлов, которые будут потомками корневого узла нового документа.

    Если для какого-то узла дерева документа в таблице стилей не оказалось соответствующего ему правила, то к нему применяется встроенное в процессор XSLT правило по умолчанию. Правила по умолчанию опираются на вид узла.

    Для корневого узла и узла-элемента правило по умолчанию означает просмотр его потомков.

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

    Для узла-комментария, инструкций по обработке и узла пространства имен по умолчанию создается пустая последовательность узлов.

    С другой стороны, для какого-то исходного узла в таблице стилей может оказаться несколько подходящих правил преобразования. Одним из них всегда будет правило по умолчанию. Как бы то ни было, к узлу всегда применяется только одно правило. Оно отбирается так:

  • во-первых, из всех импортированных правил отбирается то, которое записано в таблицу стилей в последнюю очередь;
  • во-вторых, импортированное правило отбрасывается, если есть подходящее правило в самой таблице стилей;
  • в-третьих, отбирается правило с наибольшим значением атрибута priority. Если атрибут priority отсутствует, то правилу назначается приоритет по умолчанию, вычисляемый по виду образца, записанного в атрибуте match.
  • Создание преобразованных узлов

    После того как к текущему узлу подобрано правило его преобразования, выполняется конструктор последовательности узлов и атомарных значений, записанный в этом правиле. Определение конструктора носит чрезвычайно общий характер.

    Конструктор последовательности - это последовательность узлов таблицы стилей, имеющих общий родительский узел, применение которой дает последовательность узлов и атомарных значений. Общий родительский узел, о котором идет речь в определении, - это чаще всего узел-элемент xsl:template, хотя им могут служить элементы xsl:variable, xsl:param и многие другие элементы XSLT.

    В конструкторе последовательности могут встречаться четыре вида узлов:

  • текстовые узлы, которые будут просто скопированы в конструируемую последовательность.
  • узлы-инструкции XSLT, генерирующие последовательности узлов и атомарных значений;
  • внешние, не XSLT -инструкции с именами из пространства имен, отличного от пространства имен XSLT. Они тоже генерируют последовательности узлов и атомарных значений;
  • элементы из пространства имен, отличного от пространства имен XSLT, не являющиеся внешними инструкциями. Они становятся узлами-элементами конструируемой последовательности.
  • Узлы-инструкции, входящие в конструктор, выполняются и вместе с остальными узлами конструктора образуют одну последовательность узлов и/или атомарных значений. Все подряд идущие атомарные значения из созданной конструктором последовательности преобразуются в строки и собираются в один текстовый узел, в котором они записываются через пробел. Затем в полученной последовательности узлов все подряд идущие текстовые узлы собираются в один текстовый узел без всяких разделителей.

    Итак, после применения каждого правила получается последовательность узлов, а после использования всех правил таблицы стилей ко всем выбранным узлам исходного дерева получается набор таких последовательностей. Осталось собрать из этого набора последовательностей одно или несколько деревьев, которые и будут результатом преобразования. Они создаются или явно элементами xsl:result-document, или неявно начальным правилом преобразования.

    Очень часто преобразованное дерево выводится на какое-то устройство в виде документа HTML, XHTML, XML или просто в виде плоского ASCII-текста. В самом простом случае выполняется сериализация, для которой в языке XSLT предусмотрен элемент xsl:output.

    Преобразование документов с помощью DOM

    W3C DOM представляет собой не зависящее от языка или платформы определение. W3C DOM модель устанавливает стандартную функциональность для навигации по документу и манипулирования содержанием и структурой документов, написанных на языках XML и HTML.

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

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

    Основные типы интерфейсов которые поддерживает объектная модель:

    Интерфейс Document

    Узел Document содержит следующей дочерние узлы: Element (не более чем один), ProcessingInstruction (команда приложения), Comment (комментарий), vDocumentType (тип документа).

    Документ представляет собой единое целое. Методы создания документа не предоставляются, эта задача возлагается на агента пользователя. Объектная модель документа не предоставляет способа сохранения сформированного документа, эта задача отводится агенту пользователя. Большинство документов построенных с помощью скрипта исчезает при закрытии окна браузера клиента вследствие того что скрипты клиентов используемые в браузерах не имеют доступа к жесткому диску сервера.

    Значение свойства Name интерфейса Document равно #document, а значение свойства Value интерфейса Document равно null.

    Документ может иметь только один узел Element, а именно корневой узел.

    Интерфейс Node

    Все типы узлов объектной модели документа наследуют основной набор свойств от интерфейса Node.

    Интерфейс NodeList

    Доступ к узлам NodeList можно получить с помощью метода item, который в качестве аргумента использует index. Длину списка можно определить методом length. Интерфейс NodeList хранит запись дочерних узлов конкретного узла и их позиции. Он является основой структуры дерева документа в памяти компьютера.

    DOM в браузерах Internet Explorer 5

    В браузерах Internet Explorer 5 и выше находятся встроенные библиотеки DOM и поддержка XSL. Для сценариев на стороне клиента доступно множество объектов для работы с XML-документом, самые важные из них, объекты XMLDOMDocument, XMLDOMNode, XMLDOMNodeList, XMLDOMParseError представляющие интерфейс для доступа ко всему документу, отдельным его узлам и поддеревьям, предоставляющие необходимую для отладки информацию о произошедших ошибках анализатора соответственно.

    Объект XMLDOMNode реализует базовый DOM интерфейс Node, предназначен для манипулирования с отдельным узлом дерева документа. Его свойства и методы позволяют получать и изменять полную информацию о текущем узле - его тип (является ли текущий узел элементом, комментарием, текстом и т.д.), название, полное название (вместе с Namespace префиксом), его содержимое, список дочерних элементов и т.д.
    Объект XMLDOMDocument представляет верхний уровень объектной иерархии и содержит методы для работы с документом: его загрузки, анализа, создания в нем элементов, атрибутов, комментариев и т.д. Многие свойства и методы этого объекта реализованы также в класса Node, т.к. документ может быть рассмотрен как корневой узел с вложенными в него поддеревьями.
    Объект XMLDOMNodeList представляет собой список узлов - поддеревья и содержит методы, при помощи которых можно организовать процедуру обхода дерева.
    Объект XMLDOMParserError объект позволяет получить всю необходимую информацию об ошибке, произошедшей в ходе разбора документа. Все свойства этого объекта доступны только для чтения.

    Создание XML документа с использованием Microsoft Visual Studio .Net

    Microsoft Visual Studio .Net позволяет достаточно легко создавать XML документы и XSD схемы к ним. Для того чтобы создать XML документ необходимо в среде разработки Visual Studio .Net выполнить команду меню File | New | File… в появившемся диалоговом окне New File в наборе Templates выделить значок XML File. В результате на основном рабочем поле появится следующего вида страница:

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

    Заполнить XML документ данными можно с помощью раздела Data. Для этого в низу окна нужно найти кнопку "Data". В результате страница приобретет примерно следующий вид:

    Введенные таким образом данные будут добавлены в XML документ.

    Для того чтобы для созданного XML документа написать XSD схему необходимо на рабочем поле щелкнуть правой кнопкой мыши и в выпадающем списке выбрать Create Schema. В результате появится:

    Тип элементов и атрибутов можно выбрать из выпадающего списка.

    Контрольные вопросы:

  • Что такое языки разметки. Стилистическая, структурная и семантическая разметки.
  • История развития языков разметки: SGML, HTML, XML.
  • Что такое XML. Как появился XML. XML в качестве данных
  • Структура XML документа. Правильно оформленные и верные документы.
  • Анализатор XML. Событийно управляемые анализаторы. Древовидные анализаторы.
  • Зачем нужно определение типа документа ( DTD ). Общие принципы написания определений DTD:
  • Недостатки и особенности определений DTD.
  • Моделирование данных с использованием XML. Информационная модель.
  • Отображение на XML. Схемы.
  • Объектная модель документа (DOM).
  • Пространство имен и схемы.
  • Связи и запросы.
  • Трансформация документа XML.
  • Дизайн документов XML.
  • Вернуться к учебному плану