XML и связанные технологии
xml_examples.zip
(~4 Кб)Задачи
Язык XML предназначен для хранения документов в виде, удобном для обмена и обработки. Это текстовый формат — читать и редактировать документ может человек без специального ПО. Язык фиксирует набор элементарных составных частей и правила построения документа, но не накладывает ограничений на его содержимое и структуру.
Задача статьи — рассказать о полезных возможностях общеизвестного и распространённого языка XML и связанных технологий, не ограничиваясь описанием XML как рядового текстового формата с угловыми скобочками.
Модель данных и разметка XML
XML-разметка является текстовым представлением строго определённой модели данных — DOM. Документ в DOM-модели — это дерево из элементарных структурных единиц — узлов (node). Дочерние узлы упорядочены в рамках родительского. Узлы различаются по типу, который определяет их свойства и способ представления в XML-разметке. Вот основные типы:
- элемент — имеет имя и дочерние узлы; узлы остальных перечисленных типов являются листовыми (оконечными) и обязательно лежат под родительским элементом. В XML представлен в виде именованных открывающего
<element>
и закрывающего</element>
тегов, для пустого элемента они могут сворачиваться:<empty/>
. - атрибут — имеет имя, уникальное в рамках родительского элемента, и скалярное значение, обычно небольшой длины. Выводится в открывающем теге родительского элемента:
<el attribute="value"/>
. - текст — неименованное скалярное значение произвольной длины. Выводится внутри родительского элемента, служебные символы разметки заменяются на
&
-последовательности:<el>text: 1 < 2</el>
. - секция
CDATA
— текст, символы разметки в котором не заменяются при выводе, обрамляется<![CDATA[
и]]>
. - комментарий — любой текст, не содержащий два дефиса под ряд:
--
. При выводе обрамляется<!--
и-->
.
Так они выглядят при сериализации в XML:
- <?xml version="1.0" encoding="UTF-8"?>
- <stat>
- <!-- Комментарий: Данные для гистограммы -->
- <hist title="Гистограмма" y-max="20">
- <descr>
- Описание - <bold>текст</bold> с XML-разметкой
- и экранированными спецсимволами:
- 1 < 2 && 5 > 3
- </descr>
- <block label="10-20">5</block>
- <block label="20-30">12</block>
- <block label="30-40">11</block>
- <block label="40-50">18</block>
- <block label="50-60">4</block>
- </hist>
- <!-- Комментарий: Данные для графика -->
- <graph title="График" x-max="8" y-max="8">
- <descr><![CDATA[
- Описание без возможности использования
- XML-разметки, спецсимволы не экранируются:
- 1 < 2 && 5 > 3
- ]]></descr>
- <point x="0" y="0"/>
- <point x="1" y="1"/>
- <point x="3" y="5"/>
- <point x="4" y="4.7"/>
- <point x="6.5" y="2.1"/>
- <point x="8" y="2"/>
- </graph>
- </stat>
XML-документ имеет единственный корневой элемент. Каждый элемент описывает объект определённого типа, в зависимости от которого он может быть пустым, либо иметь свойства: скалярные атрибуты, скалярные элементы и их списки, вложенные элементы-объекты. Например, объект перенос строки в XHTML не содержит свойств и представляется пустым элементом <br/>
, а объект описание с форматированием из приведённого примера XML-документа — контейнерным элементом <descr>
, имеющим дочерние текстовые узлы и элементы форматирования <bold>
.
Используемые в разметке XML символы являются служебными, их включение в явном виде в документ может привести к нарушению однозначности разметки: <el attr="a + "b""/>
(кавычки в значении атрибута), <el>a<b</el>
(угловые скобки в тексте). Для их экранирования в тексте и в значениях атрибутов предусмотрен механизм ссылки на символ (character reference), адресующий символ по коду в таблице Unicode: ссылки в десятичном &
и в шестнадцетиричном представлении &
эквивалентны и указывают на символ &
(амперсанд). Механизм ссылки на сущность (entity reference) позволяет включить в разметку адресуемую по имени DTD-сущность — именованный фрагмент XML-разметки. Синтаксис ссылки на сущность аналогичен ссылке на символ: &
также указывает на символ &
. Набор доступных сущностей определяется в DTD-схеме, ассоциированной с XML-документом. Например, для XHTML-документов, обычных web-страниц, определены свои характерные сущности: длинное тире —
, русские типографские кавычки «
и »
и прочие. Предопределённый набор сущностей доступен для любого XML-документа:
Ссылка на DTD-сущность | Экранируемый символ |
---|---|
& | & |
< | < |
> | > |
" | " |
' | ' |
Описанные механизмы экранирования не распространяются на секции 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-документа наличие префикса и его имя больше нигде не учитываются.
Пример запроса, включающего элементы и атрибуты из разных пространств имён, в том числе не имеющие пространства имён:
- <?xml version="1.0" encoding="UTF-8"?>
- <s:Envelope
- xmlns:s="http://www.w3.org/2003/05/soap-envelope"
- xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
- xmlns:stat="http://remote.com/StatSvc">
- <s:Header>
- <wsa:MessageID>uuid:123-ABC</wsa:MessageID>
- <wsa:To s:mustUnderstand="1">http://remote.com/StatSvc</wsa:To>
- <wsa:Action>http://remote.com/StatSvc/submit</wsa:Action>
- <wsa:FaultTo>
- <wsa:Address>http://falstart.com/FaultSvc</wsa:Address>
- </wsa:FaultTo>
- </s:Header>
- <s:Body>
- <stat:submit>
- <stat>
- <hist title="Гистограмма" y-max="20">
- <!-- Данные гистограммы ... -->
- </hist>
- </stat>
- </stat:submit>
- </s:Body>
- </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), разделённых /
, каждый из которых содержит:
- ось (axis), задаёт направление поиска от текущего узла: атрибуты, непосредственные дочерние узлы, все узлы-потомки, родитель, все предки, предшествующие, последующие.
- правило проверки узла (node test) — первичное условие отбора из заданного осью множества узлов по имени
element
,attribute
для именованных узлов, по типуtext()
,comment()
для безымянных или*
— выбрать все узлы. - опциональный предикат (predicate) — логические выражения для расширенной фильтрации
Например, шаг 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.
- <?xml version="1.0" encoding="UTF-8"?>
- <xsl:stylesheet
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- version="1.0">
- <xsl:variable name="W" select="'400'"/>
- <xsl:variable name="H" select="'200'"/>
- <xsl:template match="/stat">
- <svg version="1.1" baseProfile="full"
- height="{$H}" width="{$W}">
- <rect x="0" y="0" width="{$W}" height="{$H}" fill="#181A26"/>
- <text x="0" y="0" dy="1em" fill="##EEEEEE">
- <xsl:value-of select="hist/@title"/> и
- <xsl:value-of select="graph/@title"/>
- </text>
- <!-- Гистограмма -->
- <pattern id="dots" patternUnits="userSpaceOnUse"
- width="5" height="5">
- <rect x="4" y="4" width="1" height="1" fill="#4EEE94"/>
- </pattern>
- <xsl:variable name="hfy" select="$H div hist/@y-max"/>
- <xsl:variable name="w" select="$W div count(hist/block)"/>
- <xsl:for-each select="hist/block">
- <xsl:variable name="h" select=". * $hfy"/>
- <rect x="{$w * (position() - 1)}" y="{$H - $h}"
- width="{$w}" height="{$h}" stroke-width="2"
- fill="url(#dots)" stroke="#4EEE94"/>
- </xsl:for-each>
- <!-- График -->
- <xsl:variable name="fx" select="$W div graph/@x-max"/>
- <xsl:variable name="fy" select="$H div graph/@y-max"/>
- <xsl:variable name="path">
- <xsl:text>M</xsl:text>
- <xsl:for-each select="graph/point">
- <xsl:value-of select="concat(' ', @x * $fx,
- ' ', $H - @y * $fy, 'L')"/>
- </xsl:for-each>
- </xsl:variable>
- <path d="{$path}" fill="none"
- stroke="#DAA520" stroke-width="4"/>
- </svg>
- </xsl:template>
- </xsl:stylesheet>
Любой XML-документ, независимо от содержания, может ссылаться на таблицу стилей для его визуализации с помощь общего механизма xml-stylesheet
, который также позволяет ассоциировать с документом XSLT-преобразование. Поддержка такой возможности реализована практически во всех современных web-браузерах. Например, к XML-документу со статистикой можно следующим образом подключить рассмотренное XSLT-преобразование:
- <?xml version="1.0" encoding="UTF-8"?>
- <?xml-stylesheet type="text/xsl" href="stat_to_svg.xslt"?>
- <stat>
- <!-- ... -->
- </stat>
При открытии документа web-браузером будет выполнено XSLT-преобразование, а полученная SVG-разметка будет отрисована в графическом виде:

XSD — система типизации
XSD — это язык на основе XML для описания и ограничения структуры XML-документа.
Ниже приведён пример XSD-схемы, определяющей формат XML-документа со статистикой.
- <?xml version="1.0" encoding="UTF-8"?>
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
- <xs:element name="stat">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="hist" type="HistType"/>
- <xs:element name="graph" type="GraphType"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:complexType name="AbstractStat" abstract="true">
- <xs:sequence>
- <xs:element name="descr" type="FormattedTextType"/>
- </xs:sequence>
- <xs:attribute name="title" type="xs:string" use="required"/>
- <xs:attribute name="y-max" type="xs:float" use="required"/>
- </xs:complexType>
- <xs:complexType name="HistType">
- <xs:complexContent>
- <xs:extension base="AbstractStat">
- <xs:sequence>
- <xs:element type="HistBlockType"
- name="block" maxOccurs="unbounded"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="GraphType">
- <xs:complexContent>
- <xs:extension base="AbstractStat">
- <xs:sequence>
- <xs:element type="GraphPointType"
- name="point" maxOccurs="unbounded"/>
- </xs:sequence>
- <xs:attribute name="x-max" type="xs:float" use="required"/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="HistBlockType">
- <xs:simpleContent>
- <xs:extension base="xs:float">
- <xs:attribute name="label" type="xs:string"/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- <xs:complexType name="GraphPointType">
- <xs:attribute name="x" type="xs:float" use="required"/>
- <xs:attribute name="y" type="xs:float" use="required"/>
- </xs:complexType>
- <xs:complexType mixed="true" name="FormattedTextType">
- <xs:all>
- <xs:element name="bold" minOccurs="0"
- type="FormattedTextType"/>
- <xs:element name="italic" minOccurs="0"
- type="FormattedTextType"/>
- </xs:all>
- </xs:complexType>
- </xs:schema>
Практически во всех современных XML-редакторах имеется встроенная поддержка XSD. Например, IDE Eclipse на основе определений из XSD выполняет проверку XML-документа на лету, поддерживает подсказки и автодополнение.

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