Фальстарт

XML и связанные технологии

Константин Александров, 31 августа 2014
Загрузить xml_examples.zip (~4 Кб)
  1. Задачи
  2. Модель данных и разметка XML
  3. Пространства имён
  4. Связанные технологии
    1. XPath — адресация частей документа
    2. XSLT — преобразование XML
    3. XSD — система типизации

Задачи

Язык XML предназначен для хранения документов в виде, удобном для обмена и обработки. Это текстовый формат — читать и редактировать документ может человек без специального ПО. Язык фиксирует набор элементарных составных частей и правила построения документа, но не накладывает ограничений на его содержимое и структуру.

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

Модель данных и разметка XML

XML-разметка является текстовым представлением строго определённой модели данных — DOM. Документ в DOM-модели — это дерево из элементарных структурных единиц — узлов (node). Дочерние узлы упорядочены в рамках родительского. Узлы различаются по типу, который определяет их свойства и способ представления в XML-разметке. Вот основные типы:

Так они выглядят при сериализации в XML:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <stat>
  3. <!-- Комментарий: Данные для гистограммы -->
  4. <hist title="Гистограмма" y-max="20">
  5. <descr>
  6. Описание - <bold>текст</bold> с XML-разметкой
  7. и экранированными спецсимволами:
  8. 1 &lt; 2 &amp;&amp; 5 &gt; 3
  9. </descr>
  10. <block label="10-20">5</block>
  11. <block label="20-30">12</block>
  12. <block label="30-40">11</block>
  13. <block label="40-50">18</block>
  14. <block label="50-60">4</block>
  15. </hist>
  16. <!-- Комментарий: Данные для графика -->
  17. <graph title="График" x-max="8" y-max="8">
  18. <descr><![CDATA[
  19. Описание без возможности использования
  20. XML-разметки, спецсимволы не экранируются:
  21. 1 < 2 && 5 > 3
  22. ]]></descr>
  23. <point x="0" y="0"/>
  24. <point x="1" y="1"/>
  25. <point x="3" y="5"/>
  26. <point x="4" y="4.7"/>
  27. <point x="6.5" y="2.1"/>
  28. <point x="8" y="2"/>
  29. </graph>
  30. </stat>

XML-документ имеет единственный корневой элемент. Каждый элемент описывает объект определённого типа, в зависимости от которого он может быть пустым, либо иметь свойства: скалярные атрибуты, скалярные элементы и их списки, вложенные элементы-объекты. Например, объект перенос строки в XHTML не содержит свойств и представляется пустым элементом <br/>, а объект описание с форматированием из приведённого примера XML-документа — контейнерным элементом <descr>, имеющим дочерние текстовые узлы и элементы форматирования <bold>.

Используемые в разметке XML символы являются служебными, их включение в явном виде в документ может привести к нарушению однозначности разметки: <el attr="a + "b""/> (кавычки в значении атрибута), <el>a<b</el> (угловые скобки в тексте). Для их экранирования в тексте и в значениях атрибутов предусмотрен механизм ссылки на символ (character reference), адресующий символ по коду в таблице Unicode: ссылки в десятичном &#38; и в шестнадцетиричном представлении &#x26; эквивалентны и указывают на символ & (амперсанд). Механизм ссылки на сущность (entity reference) позволяет включить в разметку адресуемую по имени DTD-сущность — именованный фрагмент XML-разметки. Синтаксис ссылки на сущность аналогичен ссылке на символ: &amp; также указывает на символ &. Набор доступных сущностей определяется в DTD-схеме, ассоциированной с XML-документом. Например, для XHTML-документов, обычных web-страниц, определены свои характерные сущности: длинное тире &mdash;, русские типографские кавычки &laquo; и &raquo; и прочие. Предопределённый набор сущностей доступен для любого XML-документа:

Ссылка на DTD-сущность Экранируемый символ
&amp; &
&lt; <
&gt; >
&quot; "
&apos; '

Описанные механизмы экранирования не распространяются на секции CDATA и комментарии — всё содержимое этих блоков включается в XML в явном виде до признака завершения блока.

Пространства имён

Пространства имён (namespaces) — это механизм уточнения имён элементов и атрибутов идентифицируемым по URI пространством имён. URI должен быть абсолютным, непустым, не содержать требующих экранирования символов. Чаще всего используют HTTP URI: http://www.w3.org/2000/svg. Вовсе не обязательно размещать по этому адресу какой-либо ресурс: обработка документа не предполагает выполнения запросов к URI пространства имён, однако хорошей практикой является размещение по URI XSD-схемы, содержащей определения входящих в пространство элементов.

Объявление пространства имён в XML-документе выполняется добавлением служебного атрибута с URI в качестве значения и действует для текущего и всех нижележащих элементов. Пространство имён по умолчанию, применяемое к элементам без префикса, объявляется с помощью атрибута xmlns: <el xmlns="URI"/>, а для его сброса используется пустой атрибут: <el xmlns=""/>. Связь префикса с пространством имён объявляется с помощью одноимённого атрибута со служебным префиксом xmlns: <ns:e xmlns:ns="URI"/>. Использование префикса в имени элемента или атрибута — это только способ явного задания пространства имён, при обработке XML-документа наличие префикса и его имя больше нигде не учитываются.

Пример запроса, включающего элементы и атрибуты из разных пространств имён, в том числе не имеющие пространства имён:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <s:Envelope
  3. xmlns:s="http://www.w3.org/2003/05/soap-envelope"
  4. xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
  5. xmlns:stat="http://remote.com/StatSvc">
  6. <s:Header>
  7. <wsa:MessageID>uuid:123-ABC</wsa:MessageID>
  8. <wsa:To s:mustUnderstand="1">http://remote.com/StatSvc</wsa:To>
  9. <wsa:Action>http://remote.com/StatSvc/submit</wsa:Action>
  10. <wsa:FaultTo>
  11. <wsa:Address>http://falstart.com/FaultSvc</wsa:Address>
  12. </wsa:FaultTo>
  13. </s:Header>
  14. <s:Body>
  15. <stat:submit>
  16. <stat>
  17. <hist title="Гистограмма" y-max="20">
  18. <!-- Данные гистограммы ... -->
  19. </hist>
  20. </stat>
  21. </stat:submit>
  22. </s:Body>
  23. </s:Envelope>

Пространства имён — логически простое, но при этом очень мощное расширение базового стандарта XML. Задачи инструмента намного шире и значительнее, чем просто разрешение конфликтов имён: позволяя определять ограниченные именованные множества однозначно адресуемых элементов и атрибутов, он делает XML универсальным конструктором языков разметки. Такие языки могут иметь разный уровень абстракции, назначение, предполагать разные способы обработки и, возможно, совместно использоваться в одном XML-документе.

Приведенный в примере запрос состоит из нескольких «слоёв», каждый из которых обрабатывается на своём уровне. Элементы конверта Envelope, заголовка Header и тела Body определены в базовом протоколе обмена SOAP 1.2. Протокол предусматривает возможность расширения и определяет атрибут mustUnderstand для пометки элементов расширения, которые должны обязательно поддерживаться принимающей стороной. Библиотеки для построения SOAP-сервисов реализуют подобные проверки протокола, обрабатывая элементы из его пространства имён унифицированным образом, независимо от конкретного сервиса и используемых расширений.

Элементы в заголовке относятся к расширению WS-Addressing. Их обработка выполняется на следующем этапе после признания запроса корректным SOAP-сообщением. Этот слой также может отдельно обрабатываться, например, межсетевым экраном для пропуска парного входящего запроса с отчётом об ошибке на адрес из FaultTo.

При разработке своих форматов хранения и обмена на основе XML использование пространств имён является хорошей практикой. Такое решение при незначительном усложнении приносит значительную пользу. Исключениями являются разве что совсем синтетические случаи использования промежуточных внутренних XML-документов с очень простым и постоянным форматом.

Связанные технологии

Для решения задач по обработке XML-документов есть много стандартизованных технологий, для работы с ними нужно понять их идеологию и научиться формулировать свои задачи в их терминах. Далее кратко описаны назначение и подходы к наиболее базовым, универсальным и распространённым технологиям. Описание сопровождается примерами, цель которых — показать, как просто, дёшево и технологично можно решать задачи без тучи невнятного кода на каком-либо языке программирования.

XPath — адресация частей документа

XPath — это язык выбора узлов XML-документа, также поддерживающий базовые возможности обработки строк, чисел, логических значений. XPath оперирует с DOM-моделью документа и применим к любым данным, которые можно представить в виде DOM — дерева элементов, атрибутов, текстовых узлов. Он предоставляет функциональность поиска, проверки узлов и выполнения несложных вычислений другим технологиям, в частности XSLT. XPath реализуют различные библиотеки по обработке XML во многих языках программирования.

Примеры XPath-выражений и результат их применения к приведённому ранее примеру XML-документа:

/stat/hist/descr
Описание гистограммы — элемент descr
/stat/hist/descr//text()
Набор всех текстовых узлов описания без элементов форматирования
/stat/*
Набор всех непосредственных дочерних элементов stat: hist и graph
//block
Набор всех элементов документа block
//hist/block[1]
Первый блок гистограммы
//hist/block[last()]
Последний блок гистограммы
//block[count(preceding-sibling::block) mod 2 = 0]
Набор нечётных столбцов гистограммы
/stat/graph/point[@x = 0]/@y
Значение графика в точке 0
//block|//point
Объединённый набор всех столбцов гистограммы и всех точек графика
count(//block[. > 10])
Количество столбцов гистограммы со значением больше 10
//block[. > 10][1]
Первый из всех столбцов гистограммы со значениями больше 10
//block[1][. > 10]
Первый столбец гистограммы, если его значение больше 10

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

Выражение пути (path expression) — основной тип выражения в XPath, результатом вычисления которого является набор узлов, иногда пустой. Наборы узлов можно объединять, применять к ним функции, использовать в качестве операндов математических операторов и операторов сравнения, при этом значения автоматически приводятся к требуемым типам посредством неявного вызова функций string, number или boolean. Абсолютный путь начинается с / и вычисляется от корневого узла документа вместо контекстного. Путь состоит из шагов (step), разделённых /, каждый из которых содержит:

Например, шаг preceding-sibling::block[. < 10], возвращающий набор предшествующих контекстному узлу элементов block со значением меньше 10, состоит из оси preceding-sibling, проверки узла block и предиката . < 10.

Для основных осей есть сокращения. Ось непосредственных дочерних узлов используется по умолчанию: parent/child. Ось атрибутов обозначается @: element/@attribute. Остальные оси указываются явно по именам: preceding::block. Сокращения предусмотрены и для целых шагов:

Сокращение Значение Пример
. контекстный узел block[. > 10]
.. родительский узел block/..
// контекстный и все нижележащие узлы stat//block

Выражение пути вычисляется последовательно, по шагам. На каждом шаге перебираются входные узлы: от узла выполняется переход по оси ко множеству связанных узлов, оно фильтруется по базовой проверке узла и предикату, результат добавляется в выходной набор узлов шага. Этот набор является входом следующего шага. Набор узлов в XPath не может содержать дубли, поэтому путь //block/../block, как и //block, вернёт набор всех узлов block документа.

XSLT — преобразование XML

XSLT — это язык на базе XML для преобразования XML в XML или в текст. Половина XSLT — это XPath: на нём пишутся все выражения для поиска, проверки и любых вычислений.

Ниже приведено XSLT-преобразование для визуализации графика и гистограммы из первого примера XML-документа. Преобразование трансформирует XML с исходными сырыми данными в SVG — формат векторной графики, также основанный на XML.

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet
  3. xmlns="http://www.w3.org/2000/svg"
  4. xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  5. version="1.0">
  6. <xsl:variable name="W" select="'400'"/>
  7. <xsl:variable name="H" select="'200'"/>
  8. <xsl:template match="/stat">
  9. <svg version="1.1" baseProfile="full"
  10. height="{$H}" width="{$W}">
  11. <rect x="0" y="0" width="{$W}" height="{$H}" fill="#181A26"/>
  12. <text x="0" y="0" dy="1em" fill="##EEEEEE">
  13. <xsl:value-of select="hist/@title"/> и
  14. <xsl:value-of select="graph/@title"/>
  15. </text>
  16. <!-- Гистограмма -->
  17. <pattern id="dots" patternUnits="userSpaceOnUse"
  18. width="5" height="5">
  19. <rect x="4" y="4" width="1" height="1" fill="#4EEE94"/>
  20. </pattern>
  21. <xsl:variable name="hfy" select="$H div hist/@y-max"/>
  22. <xsl:variable name="w" select="$W div count(hist/block)"/>
  23. <xsl:for-each select="hist/block">
  24. <xsl:variable name="h" select=". * $hfy"/>
  25. <rect x="{$w * (position() - 1)}" y="{$H - $h}"
  26. width="{$w}" height="{$h}" stroke-width="2"
  27. fill="url(#dots)" stroke="#4EEE94"/>
  28. </xsl:for-each>
  29. <!-- График -->
  30. <xsl:variable name="fx" select="$W div graph/@x-max"/>
  31. <xsl:variable name="fy" select="$H div graph/@y-max"/>
  32. <xsl:variable name="path">
  33. <xsl:text>M</xsl:text>
  34. <xsl:for-each select="graph/point">
  35. <xsl:value-of select="concat(' ', @x * $fx,
  36. ' ', $H - @y * $fy, 'L')"/>
  37. </xsl:for-each>
  38. </xsl:variable>
  39. <path d="{$path}" fill="none"
  40. stroke="#DAA520" stroke-width="4"/>
  41. </svg>
  42. </xsl:template>
  43. </xsl:stylesheet>

Любой XML-документ, независимо от содержания, может ссылаться на таблицу стилей для его визуализации с помощь общего механизма xml-stylesheet, который также позволяет ассоциировать с документом XSLT-преобразование. Поддержка такой возможности реализована практически во всех современных web-браузерах. Например, к XML-документу со статистикой можно следующим образом подключить рассмотренное XSLT-преобразование:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <?xml-stylesheet type="text/xsl" href="stat_to_svg.xslt"?>
  3. <stat>
  4. <!-- ... -->
  5. </stat>

При открытии документа web-браузером будет выполнено XSLT-преобразование, а полученная SVG-разметка будет отрисована в графическом виде:

Результат применения XSLT к исходным данным и отрисовки полученной SVG-разметки web-браузером
Результат применения XSLT к исходным данным и отрисовки полученной SVG-разметки web-браузером

XSD — система типизации

XSD — это язык на основе XML для описания и ограничения структуры XML-документа.

Ниже приведён пример XSD-схемы, определяющей формат XML-документа со статистикой.

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  3. <xs:element name="stat">
  4. <xs:complexType>
  5. <xs:sequence>
  6. <xs:element name="hist" type="HistType"/>
  7. <xs:element name="graph" type="GraphType"/>
  8. </xs:sequence>
  9. </xs:complexType>
  10. </xs:element>
  11. <xs:complexType name="AbstractStat" abstract="true">
  12. <xs:sequence>
  13. <xs:element name="descr" type="FormattedTextType"/>
  14. </xs:sequence>
  15. <xs:attribute name="title" type="xs:string" use="required"/>
  16. <xs:attribute name="y-max" type="xs:float" use="required"/>
  17. </xs:complexType>
  18. <xs:complexType name="HistType">
  19. <xs:complexContent>
  20. <xs:extension base="AbstractStat">
  21. <xs:sequence>
  22. <xs:element type="HistBlockType"
  23. name="block" maxOccurs="unbounded"/>
  24. </xs:sequence>
  25. </xs:extension>
  26. </xs:complexContent>
  27. </xs:complexType>
  28. <xs:complexType name="GraphType">
  29. <xs:complexContent>
  30. <xs:extension base="AbstractStat">
  31. <xs:sequence>
  32. <xs:element type="GraphPointType"
  33. name="point" maxOccurs="unbounded"/>
  34. </xs:sequence>
  35. <xs:attribute name="x-max" type="xs:float" use="required"/>
  36. </xs:extension>
  37. </xs:complexContent>
  38. </xs:complexType>
  39. <xs:complexType name="HistBlockType">
  40. <xs:simpleContent>
  41. <xs:extension base="xs:float">
  42. <xs:attribute name="label" type="xs:string"/>
  43. </xs:extension>
  44. </xs:simpleContent>
  45. </xs:complexType>
  46. <xs:complexType name="GraphPointType">
  47. <xs:attribute name="x" type="xs:float" use="required"/>
  48. <xs:attribute name="y" type="xs:float" use="required"/>
  49. </xs:complexType>
  50. <xs:complexType mixed="true" name="FormattedTextType">
  51. <xs:all>
  52. <xs:element name="bold" minOccurs="0"
  53. type="FormattedTextType"/>
  54. <xs:element name="italic" minOccurs="0"
  55. type="FormattedTextType"/>
  56. </xs:all>
  57. </xs:complexType>
  58. </xs:schema>

Практически во всех современных XML-редакторах имеется встроенная поддержка XSD. Например, IDE Eclipse на основе определений из XSD выполняет проверку XML-документа на лету, поддерживает подсказки и автодополнение.

Поддержка XSD в IDE Eclipse
Поддержка XSD в IDE Eclipse

  1. В данном случае сериализация — преобразование логического представления документа в текстовый вид с XML-разметкой.
  2. Использование относительных URI пространств имён признано устаревшим. Равенство URI пространств имён определяется строковым сравнением, поэтому крайне не рекомендуется использовать в URI символы, допускающие разные представления, т.к. это может привести к ошибкам: http://test.org/~key и http://test.org/%7Ekey будут идентификаторами разных пространств имён.
  3. Хотя обычно XPath рассматривается только применительно к задачам обработки XML, нет никаких логических ограничений на его применение к любым данным, которые можно представить в виде DOM. Некоторые библиотеки поставляют фиксированную логику только для синтаксического разбора и выполнения XPath, предоставляя возможность самостоятельного определения слоя доступа к данным. Так, например, можно использовать XPath для адресации файлов и папок в файловой системе.
  4. Поведение этих и других стандартных функций описано в разделе Core Function Library спецификации XPath 1.0
  5. Базовая спецификация W3C XSLT 1.0 включают поддержку методов вывода xml, html и text, версия 2.0 дополнительно поддерживает xhtml. Большинство реализаций XSLT-процессоров предоставляют возможности расширения, что позволяет поддержать нестандартный выходной формат, например, бинарный.