Динамическое формирование атрибутов на примере параметров ссылки в теге <a>
Предположим теперь, что в каждой строке таблицы нам нужно сделать ссылку на некоторую страницу и передать на эту страницу два параметра - кличку и вес собаки. Понятно, что для каждой строки эти параметры - свои, и их нельзя прописать явно в XSL-файл. Тем не менее задача легко решается при помощи элемента xsl:attribute.
Мы не будем здесь строить специальный пример, ограничимся только соответствующим фрагментом XSL-файла.
<td>
<!-- Create reference to display details. Parameters - Dog Name and Dog Weight -->
<a target="_blank">
<xsl:attribute name="href">DisplayDetails.html?dogName=<xsl:value-of select="dogName"/>&dogWeight=<xsl:value-of select="dogWeight"/></xsl:attribute>
<xsl:attribute name="title">To view some more details about <xsl:value-of select="dogName"/> click to dog name</xsl:attribute>
<xsl:value-of select="dogName"/>
</a>
</td>
В этом примере в ячейке таблицы мы размещаем ссылку на страницу с подробными описаниями. Ссылка указывается в атрибуте href тега <a>. Поскольку на страницу передаются два параметра, значения которых берутся из XML-файла, этот атрибут формируется динамически. Обратите также внимание - символ &
(амперсанд), разделяющий передаваемые параметры, записывается в XSL-файле в виде &. Во втором атрибуте нам нужна всплывающая подсказка (атрибут title), которая появляется при наведении курсора мыши на ссылку. Текст этой подсказки тоже меняется динамически. Наконец, статический атрибут target
мы разместили непосредственно в теге <a>.
И, наконец, мы ознакомились с комментариями в XSL-файлах. Это вторая строка приведенного фрагмента.
<!-- Create reference to display details. Parameters - Dog Name and Dog Weight -->
На этом мы завершим рассмотрение возможностей чистого XSLT и перейдем к последнему параграфу в этом документе - к динамическому изменению содержимого Web-страницы при помощи возможностей JavaScript и XML/XSLT без каких-либо дополнительных обращений к базе данных.
JavaScript и XML
Объединим теперь наши знания XML с возможностями, которые нам предоставляет JavaScript. Предположим, что нам нужно иметь возможность динамически изменять сортировку столбцов таблицы при щелчке на заголовке того или иного столбца. Понятно, что для этого нам нужно иметь один XML-файл, содержащий строки таблицы, несколько XSL-файлов, каждый из которых содержит требуемую сортировку и нечто, что объединит это все вместе и заставит работать.
Перейдем к реализации этой программы.
В качестве XML-файла возьмем привычный нам файл со списком собак - . Обратите внимание - мы убрали из файла ссылку на XSL-файл - нам нужно менять шаблон преобразования динамически.
Создадим также три XSL-файла, в каждом из которых у нас будет свой элемент xsl:sort, задающий сортировку строк - , , .
Приведем здесь текст элемента xsl:sort для каждого файла
<xsl:sort order="ascending" select="dogName"/>
<xsl:sort order="ascending" select="number(dogWeight)" data-type="number"/>
<xsl:sort order="ascending" select="dogColor"/>
Теперь нам осталось только объединить все это вместе. Ниже мы полностью приводим текст файла , сопроводив его необходимыми комментариями.
<html>
<head>
<script language="JavaScript">
var source;
var style;
Функция инициализации необходимых объектов. В этой же функции выводится первоначальный вариант на экран.
function init() {
Создаем объект для файла - источника данных.
source = new ActiveXObject("Microsoft.XMLDOM");
source.async = false;
Создаем объект для файла с шаблоном преобразования (для файла стиля).
style = new ActiveXObject("Microsoft.XMLDOM");
style.async = false;
Загружаем записи в файл - источник данных.Записи берем из существующего XML-файла.
source.load("ex05-1.xml");
Загружаем файл стиля. Первоначальная сортировка - по цвету.
style.load("ex05-1a.xsl");
Теперь нам нужно вывести информацию на экран. Внимательно проанализируйте синтаксис и запомните его.
document.all.item("xslresult").innerHTML = source.transformNode(style);
return true;
}
Сортируем записи по кличке.
function orderByNick() {
style.load("ex05-1a.xsl");
document.all.item("xslresult").innerHTML = source.transformNode(style);
return true;
}
Сортируем записи по весу.
function orderByWeight() {
style.load("ex05-1b.xsl");
document.all.item("xslresult").innerHTML = source.transformNode(style);
return true;
}
Сортируем записи по цвету.
function orderByColor() {
style.load("ex05-1c.xsl");
document.all.item("xslresult").innerHTML = source.transformNode(style);
return true;
}
</script>
</head>
При загрузке страницы создадим все необходимые объекты и выведем первоначальный вариант на экран.
<body onLoad="init()">
<div id="xslresult">
<!-- Здесь будет размещаться окончательный вариант HTML-содержимого -->
</div>
</body>
</html>
Мы добились своей цели - при щелчке мышью на заголовке столбца строки сортируются в соответствии со значениями в выбранном столбце.
В заключение приведем реальный пример из складской системы. По своим функциональным возможностям этот пример полностью аналогичен предыдущему, детали только в реализации JavaScript-функций и в конкретных данных.
Основная страница - . Эта страница содержит два фрейма - MgrTop.html (страница управления, содержащая все JavaScript-функции) и MgrMain.html - страница-пустышка, в которую в дальнейшем подставляется результат преобразования XML-файла. Страница данных - . Эти данные получены в результате запроса к реальной базе данных. Для разработчиков на Cache приведем текст CSP-страницы, которая служит источником данных - MgrMainXml.csp. Мы пошли на некоторые ухищрения и вместо реальных страниц MgrTop.html и MgrMainXml.csp подгружаем их копии с расширением *.txt для того, чтобы в браузере можно было увидеть непосредственно исходный код страницы. Сами страницы MgrTop.html и MgrMainXml.csp тоже присутствуют в соответствующей директории, при этом MgrTop.html работает в нашем примере, а MgrMainXml.csp, естественно, бесполезна без Cache-сервера.
На этом наше введение в XML-XSLT заканчивается.
Элемент XSL:IF - фильтр
Рассмотрим теперь способы фильтрации строк таблицы. Первый пример использует старый синтаксис. В нем условие фильтрации указывается непосредственно в атрибуте select (, ).
Ниже приведена строка, в которую мы внесли необходимые изменения.
xsl:for-each select="tutorial/enimals/dogs/dog[dogWeight$gt$10] " order-by="number(dogWeight); dogName;">
И таблица результатов.
Кличка | Вес | Цвет |
Шарик | 18 кг | рыжий с черными подпалинами |
Трезор | 25 кг | черный |
Вы видите, что в таблице остались только те собаки, чей вес превышает 10 кг, причем первым стоит Шарик, чей вес меньше.
Все дальнейшие примеры в этом параграфе работают только под управлением XML-парсера версии 3.
Более гибкие возможности нам предоставляет новый синтаксис (, ). Обратите внимание - в новом синтаксисе атрибут order-by
в элементе xsl:for-each не поддерживается, вместо него мы вставили два элемента xsl:sort.
<xsl:sort order="ascending" select="number(dogWeight)"/>
<xsl:sort order="ascending" select="dogName"/>
Кроме того, условие фильтра у нас вынесено в отдельный элемент xsl:if.
<xsl:if test="dogWeight>10">
Не забывайте указывать конечный тег элемента xsl:if.
<xsl:if test="dogWeight>10">
<tr bgcolor="#F5F5F5">
<td><xsl:value-of select="dogName"/></td>
<td align="right"><xsl:value-of select="dogWeight"/> <xsl:value-of select="dogWeight/@caption"/></td>
<td><xsl:value-of select="dogColor"/></td>
</tr>
</xsl:if>
В этом примере таблица результатов полностью аналогична предыдущей.
Кличка | Вес | Цвет |
Шарик | 18 кг | рыжий с черными подпалинами |
Трезор | 25 кг | черный |
Полностью преимущества нового синтаксиса проявляются при использовании функций.
Рассмотрим следующий пример (, ). В этом примере используется функция position(), определяющая порядковый номер фрагмента в исходном XML-файле.
Соответствующий элемент xsl:if.
<xsl:if test="position()<3">
Результат.
Кличка | Вес | Цвет |
Шарик | 18 кг | рыжий с черными подпалинами |
Тузик | 10 кг | белый с черными пятнами |
проверяет, начинается ли строка string с подстроки startSubstring. Пример - , ).
Синтаксис элемента xsl:if.
<xsl:if test="starts-with($varDogName,$varStartWith)">
В этом элементе мы использовали переменные. Значения переменных были инициализированы ранее
<xsl:variable name="varStartWith">Т</xsl:variable>
<xsl:for-each select="tutorial/enimals/dogs/dog">
<xsl:variable name="varDogName"><xsl:value-of select="dogName"/></xsl:variable>
Переменная varStartWith
представляет собой подстроку, с которой должны начинаться требуемые нам клички. Она не меняется, поэтому инициализируется перед циклом. Переменная varDogName содержит кличку собаки, она меняется на каждом шаге цикла и, соответственно, инициализируется в теле цикла.
Результат.
Кличка | Вес | Цвет |
Тузик | 10 кг | белый с черными пятнами |
Трезор | 25 кг | черный |
проверяет, содержит ли строка string подстроку anySubstring. Пример - , .
Синтаксис элемента xsl:if.
<xsl:if test="contains($varDogName,$varStartWith)">
Этот пример полностью аналогичен предыдущему.
Результат.
Кличка | Вес | Цвет |
Бобик | 2 кг | бело-серый |
Трезор | 25 кг | черный |
Соответствующий фрагмент XSL-файла.
<xsl:if test="dogWeight>10">
<xsl:if test="dogWeight<20">
...
</xsl:if>
</xsl:if>
Результат.
Кличка | Вес | Цвет |
Шарик | 18 кг | рыжий с черными подпалинами |
Можно добиться и эффекта оператора OR. Для этого нам нужно включить два цикла, в каждом из которых формируется своя выборка (, ).
Соответствующий фрагмент XSL-файла.
<xsl:for-each select="tutorial/enimals/dogs/dog">
<xsl:sort order="ascending" select="number(dogWeight)"/>
<xsl:if test="dogWeight<10">
<tr bgcolor="#F5F5F5">
<td><xsl:value-of select="dogName"/></td>
<td align="right"><xsl:value-of select="dogWeight"/> <xsl:value-of select="dogWeight/@caption"/></td>
<td><xsl:value-of select="dogColor"/></td>
</tr>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="tutorial/enimals/dogs/dog">
<xsl:sort order="ascending" select="number(dogWeight)"/>
<xsl:if test="dogWeight>15">
<tr bgcolor="#F5F5F5">
<td><xsl:value-of select="dogName"/></td>
<td align="right"><xsl:value-of select="dogWeight"/> <xsl:value-of select="dogWeight/@caption"/></td>
<td><xsl:value-of select="dogColor"/></td>
</tr>
</xsl:if>
</xsl:for-each>
Результат.
Кличка | Вес | Цвет |
Бобик | 2 кг | бело-серый |
Шарик | 18 кг | рыжий с черными подпалинами |
Трезор | 25 кг | черный |
Элемент XSL:IF - улучшение внешнего вида таблиц
Элемент xsl:if можно применять не только для фильтрации строк выборки. Очевидно, что он может быть полезен и во многих других областях. В этом параграфе мы разберем пример использования элемента xsl:if для улучшения внешнего вида таблицы. Заодно мы продемонстрируем реальное использование функции position(). Мы будем использовать эту функцию для того, чтобы чередовать цвет четных и нечетных строк таблицы (, ).
Фрагмент XSL-файла, который отвечает за требуемое чередование.
<tr>
<xsl:if test="position() mod 2 = 0">
<xsl:attribute name="bgcolor">#CCCCCC</xsl:attribute>
</xsl:if>
С элементом xsl:if и с функцией position() мы уже знакомы. Оператор mod
дает нам остаток от деления на 2. А элемент xsl:attribute
позволяет нам динамически подставлять в файл результатов различные атрибуты. Это очень мощный элемент, мы разберем еще одно применение этого элемента в следующем параграфе. А сейчас приведем для полноты картины таблицу результатов.
Кличка | Вес | Цвет |
Шарик | 18 кг | рыжий с черными подпалинами |
Тузик | 10 кг | белый с черными пятнами |
Бобик | 2 кг | бело-серый |
Трезор | 25 кг | черный |
Первые шаги
Разберем теперь более подробно первый пример. Напомним его текст.
<?xml version="1.0" encoding="WINDOWS-1251"?>
<tutorial>
<title>"Заметки об XSL"</title>
<author>Леонов Игорь Васильевич</author>
</tutorial>
Первая строка информирует браузер о том, что файл имеет формат XML. Атрибут version является обязательным. Атрибут encoding не является обязательным, но если у вас в тексте есть русские буквы, то необходимо вставить этот атрибут, в противном случае XML-файл просто не будет обрабатываться, - вы получите сообщение об ошибке.
Следующие строки - это тело XML-файла. Оно состоит из элементов, которые в совокупности образуют древовидную структуру. Элементы идентифицируются тегами и могут быть вложены друг в друга.
Элементы могут иметь атрибуты, значения которых тоже могут обрабатываться в соответствии с шаблоном.
На верхнем уровне XML-файла всегда находится один элемент. То есть файл вида
<?xml version="1.0" encoding="WINDOWS-1251"?>
<tutorial>
<title>"Заметки об XSL"</title>
<author>Леонов Игорь Васильевич</author>
</tutorial>
<tutorial>
<title>"Введение в CSP"</title>
<author>Леонов Игорь Васильевич</author>
</tutorial>
не будет обрабатываться браузером. Для преобразования в корректный XML-файл нужно добавить теги элемента верхнего уровня, например
<?xml version="1.0" encoding="WINDOWS-1251"?>
<knowledgeDatabase>
<tutorial>
<title>"Заметки об XSL"</title>
<author>Леонов Игорь Васильевич</author>
</tutorial>
<tutorial>
<title>"Введение в CSP"</title>
<author>Леонов Игорь Васильевич</author>
</tutorial>
</knowledgeDatabase>
Отметим, что имена тегов чувствительны к регистру символов. Подробнее об этом можно прочесть в любой книге по XML - элементам и атрибутам в этих книгах уделяется достаточно большое внимание.
Перейдем теперь к шаблону преобразования - к XSL-файлу. Задача XSL-файла - преобразовать дерево XML-файла в другое дерево, которое, например, будет соответствовать формату HTML и может быть изображено на экране браузера с учетом форматирования, выбора шрифтов и т.п.
Для того, чтобы браузер выполнил необходимое преобразование, нужно в XML-файле указать ссылку на XSL-файл
<?xml version="1.0" encoding="WINDOWS-1251"?>
<?xml-stylesheet type='text/xsl' href='ex01-1.xsl'?>
Рассмотрим теперь текст XSL-файла
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<p><strong><xsl:value-of select="//title""/></strong></p>
<p><xsl:value-of select="//author"/></p>
</xsl:template>
</xsl:stylesheet>
Первая строка файла содержит тег элемента xsl:stylesheet. Атрибуты элемента - номер версии и ссылка на пространство имен. Эти атрибуты элемента xsl:stylesheet являются обязательными. В нашем случае пространство имен - это все имена элементов и их атрибутов, которые могут использоваться в XSL-файле. Для XSL-файлов ссылка на пространство имен является стандартной.
Заметим, что XSL-файл является одной из разновидностей XML-файлов. Он не содержит пользовательских данных, но формат его тот же самый. Файл содержит элемент верхнего уровня xsl:stylesheet, а далее идет дерево правил преобразования.
В настоящем документе мы не будем подробно пояснять, что означает каждый элемент XSL-файла. Мы будем приводить различные примеры и показывать результат в каждом примере. Читатель сможет самостоятельно сопоставить различные элементы XSL-файла и инициируемые этими элементами преобразования исходного XML-файла с пользовательской информацией.
В дальнейшем тексты XML- и XSL-файлов мы будем приводить в черно-белом варианте. Вы всегда сможете открыть реальный файл и посмотреть все в цвете. При необходимости закомментируйте ссылку на XSL-файл. Синтаксис комментария следующий - <!-- Текст комментария -->. В текст комментария нельзя вставлять символы --.
В первом примере мы посмотрели, как с помощью элемента xsl:value-of можно вывести в HTML-формате содержание элемента (текст, заключенный между тегами). Теперь мы посмотрим, как при помощи того же самого элемента можно вывести значение атрибута элемента.
Рассмотрим следующий XML-файл
<?xml version="1.0" encoding="WINDOWS-1251"?>
<?xml-stylesheet type='text/xsl' href='ex02-1.xsl'?>
<tutorial>
<dog caption="Собака: " name="Шарик">
<dogInfo weight="18 кг" color="рыжий с черными подпалинами"/>
</dog>
</tutorial>
В этом файле информация хранится не в содержании элементов, а в виде значений атрибутов. Файл имеет вид
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<P><B><xsl:value-of select="//dog/@caption"/></B>
<xsl:value-of select="//dog/@name"/>.
<xsl:value-of select="//dogInfo/@weight"/>, <xsl:value-of select="//dogInfo/@color"/>.</P>
</xsl:template>
</xsl:stylesheet>
Обратите внимание на синтаксис ссылки на атрибут элемента - //dog/@name. Имя элемента и имя атрибута разделены парой символов "/@". В остальном синтаксис тот же самый, что и для ссылки на содержание элемента.
Результат имеет следующий вид:
Собака: Шарик. 18 кг, рыжий с черными подпалинами.
Обратим теперь внимание на следующий момент. В XSL-файле мы никак не использовали элемент tutorial. На самом деле можно было использовать полный путь. Перепишем наш XML-файл, увеличив глубину дерева ()
<?xml version="1.0" encoding="WINDOWS-1251"?>
<?xml-stylesheet type='text/xsl' href='ex02-2.xsl'?>
<tutorial>
<enimals>
<dog caption="Собака: " name="Шарик">
<dogInfo weight="18 кг" color="рыжий с черными подпалинами"/>
</dog>
</enimals>
</tutorial>
Файл имеет вид
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<P><B><xsl:value-of select="//enimals/dog/@caption"/></B>
<xsl:value-of select="//enimals/dog/@name"/>.
<xsl:value-of select="//enimals/dog/dogInfo/@weight"/>, <xsl:value-of select="//dogInfo/@color"/>.</P>
</xsl:template>
</xsl:stylesheet>
Результат будет тем же самым.
Собака: Шарик. 18 кг, рыжий с черными подпалинами.
В этом примере мы использовали полную ссылку для значений атрибутов. При выводе одиночных значений оба варианта - полная и сокращенная ссылка - работают одинаково.
На этом мы закончим разбор примеров с выводом одиночных значений и перейдем к выводу табличной информации - к выводу результатов запроса.
Предварительная подготовка
Для того, чтобы работать с данным документом, вам необходимо располагать как минимум браузером Internet Explorer версии 5.0 и выше. При этом будут работать некоторые из приведенных в тексте примеров.
Для того, чтобы у вас работали все примеры, необходимо установить XML-парсер версии 3. Если пример работает только под управлением XML-парсера версии 3, то в каждом случае это оговаривается особо. Отметим, что версии IE вплоть до 5.5 используют более ранние версии парсера, поэтому устанавливать его все равно придется. О более старших версиях IE узнайте самостоятельно.
Дистрибутив XML-парсера версии 3 можно найти по адресу .
После установки парсера вам нужно будет зарегистрировать его в реестре. Для этого в командной строке необходимо выполнить команду: regsvr32 msxml3.dll. Затем необходимо сообщить IE, что вы намерены использовать этот парсер. Для этого нужно запустить утилиту xmlinst. Утилиту xmlinst
можно найти по адресу . Вы можете также попробовать найти ответы на вопросы об установке XML-парсера по адресу .
А теперь перейдем к основной части нашего документа.
Простая таблица
Первый шаг - это, как всегда, добавление шаблона преобразования. Модифицируем наш файл, добавив в него ссылку на шаблон. В результате получим файл .
В этот файл добавлен шаблон преобразования .
Рассмотрим этот шаблон подробнее. Вот его текст.
<?xml version="1.0" encoding="WINDOWS-1251" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<table border="1">
<tr bgcolor="#CCCCCC">
<td align="center"><strong>Кличка</strong></td>
<td align="center"><strong>Вес</strong></td>
<td align="center"><strong>Цвет</strong></td>
</tr>
<xsl:for-each select="tutorial/enimals/dogs/dog">
<tr bgcolor="#F5F5F5">
<td><xsl:value-of select="dogName"/></td>
<td align="right"><xsl:value-of select="dogWeight"/> <xsl:value-of select="dogWeight/@caption"/></td>
<td><xsl:value-of select="dogColor"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Первая строка - новая для вас в XSL-файле (но не в XML-файлах!). Она говорит о том, что в XSL-файле нужно нормально воспринимать русские буквы. Без этой строки браузер не сможет корректно обработать русский текст в XSL-файле. Следующие две строки шаблона являются уже привычными. Следующие шесть строк - это строка, содержащая заголовки столбцов таблицы. Конструкция для извлечения текста заголовков таблицы вам уже знакома. А вот десятая строка тоже является новой:
<xsl:for-each select="tutorial/enimals/dogs/dog">
Этот элемент шаблона позволяет выбрать и просмотреть все группы информации, полный путь к которым задается списком тегов "tutorial/enimals/dogs/dog". Обратите внимание - путь задается полностью, ни один из тегов опустить нельзя. Далее в ячейки таблицы помещается информация о наших собаках. В отличие от первых примеров путь к соответствующей информации тоже задается полностью. Попробуем, например, разместить информацию о кличке чуть-чуть иначе :
<dogName>
<dogNick>Шарик</dogNick>
</dogName>
Если мы в соответствующем XSL-файле поставим ссылку <xsl:value-of select="dogNick"/>, то в соответствующем столбце никакой клички мы не увидим. Ссылка должна быть полной - <xsl:value-of select="dogName/dogNick"/>. Вы можете самостоятельно поэкспериментировать с файлом . Правильный результат приведен ниже.
Кличка | Вес | Цвет |
Шарик | 18 кг | рыжий с черными подпалинами |
Тузик | 10 кг | белый с черными пятнами |
Бобик | 2 кг | бело-серый |
Трезор | 25 кг | черный |
Сортировка
В предыдущих примерах порядок строк в таблице полностью соответствовал группам тегов в XML-файле. Этот порядок можно изменять. Добавим в тег
<xsl:for-each select="tutorial/enimals/dogs/dog">
атрибут order-by
<xsl:for-each select="tutorial/enimals/dogs/dog" order-by="dogName">
Наша таблица примет вид (, ).
Кличка | Вес | Цвет |
Бобик | 2 кг | бело-серый |
Трезор | 25 кг | черный |
Тузик | 10 кг | белый с черными пятнами |
Шарик | 18 кг | рыжий с черными подпалинами |
Более интересные результаты мы получим, если попытаемся отсортировать таблицу по столбцу "Вес". Вначале попробуем сделать по аналогии с предыдущим примером - атрибут order-by="dogName" заменим на order-by="dogWeight". Результат приведен ниже (, ).
Кличка | Вес | Цвет |
Тузик | 10 кг | белый с черными пятнами |
Шарик | 18 кг | рыжий с черными подпалинами |
Бобик | 2 кг | бело-серый |
Трезор | 25 кг | черный |
Таблица действительно отсортирована по столбцу "вес", но это не числовая, а строковая сортировка! Для того, чтобы браузер воспринял значения как числа, ему необходимо об этом сказать, - вместо order-by="dogWeight"
необходимо написать order-by="number(dogWeight)". Теперь мы получили правильный результат (, ).
Кличка | Вес | Цвет |
Бобик | 2 кг | бело-серый |
Тузик | 10 кг | белый с черными пятнами |
Шарик | 18 кг | рыжий с черными подпалинами |
Трезор | 25 кг | черный |
Приведем теперь пример сортировки по нескольким столбцам. Различные элементы в атрибуте order-by должны разделяться символом ";" - order-by="number(dogWeight); dogName" (, ). Таблица приведена ниже.
Кличка | Вес | Цвет |
Трезор | 10 кг | черный |
Тузик | 10 кг | белый с черными пятнами |
Бобик | 18 кг | бело-серый |
Шарик | 18 кг | рыжий с черными подпалинами |
Следующий пример работает только под управлением XML-парсера версии 3. В нем строки сортируются по одному столбцу - по кличке собаки. Этот пример уже приводился выше, однако теперь мы используем новый синтаксис (, ).
Отметим разницу.
При использовании нового синтаксиса используется ссылка на другое пространство имен
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Это очень важный момент, и его никогда нельзя упускать из виду.
Кроме того, мы убрали атрибут order-by в элементе xsl:for-each
и добавили другой элемент
<xsl:sort order="ascending" select="dogName"/>
Если элемент xsl:sort
присутствует в элементе xsl:for-each, то он всегда должен стоять сразу после элемента xsl:for-each. Синтаксис элемента xsl:sort достаточно очевиден. В нем используются два атрибута: атрибут order - способ сортировки (по возрастанию или по убыванию) и атрибут select - имя поля, по которому производится сортировка. Если нам нужно отсортировать по первому элементу, как в данном примере, то вместо "dogName" можно было поставить точку - ".", для других элементов нужно указывать его имя, например "dogColor", если нам нужно отсортировать записи по цвету собаки. На самом деле атрибутов может быть пять - select, lang, data-type, order и case-order, но мы не будем здесь рассматривать все эти атрибуты, поскольку здесь мы не преследуем цель дать полное описание всех элементов, используемых в XSL, и их атрибутов.
Таблица результатов приведена ниже.
Кличка | Вес | Цвет |
Бобик | 2 кг | бело-серый |
Трезор | 25 кг | черный |
Тузик | 10 кг | белый с черными пятнами |
Шарик | 18 кг | рыжий с черными подпалинами |
Разница заключается в одной строке
<xsl:sort order="descending" select="dogName"/>
Мы изменили значение атрибут order - значение ascending
заменено на descending.
Таблица результатов приведена ниже.
Кличка | Вес | Цвет |
Шарик | 18 кг | рыжий с черными подпалинами |
Тузик | 10 кг | белый с черными пятнами |
Трезор | 25 кг | черный |
Бобик | 2 кг | бело-серый |
Покажем теперь сортировку по нескольким полям (, ). Этот пример работает только под управлением XML-парсера версии 3.
В этом примере у нас фигурируют две строки с элементом xsl:sort.
<xsl:sort order="ascending" select="number(dogWeight)" data-type="number"/>
<xsl:sort order="ascending" select="dogName"/>
Строки вначале сортируются по весу собаки, а затем по их кличкам в алфавитном порядке. Обратите внимание - для того, чтобы сортировка выполнялась в числовой последовательности, в элемент xsl:sort мы добавили атрибут data-type. Таблица результатов приведена ниже.
Кличка | Вес | Цвет |
Волчонок | 3 кг | темно-серый |
Трезор | 10 кг | черный |
Тузик | 10 кг | белый с черными пятнами |
Бобик | 18 кг | бело-серый |
Шарик | 18 кг | рыжий с черными подпалинами |
Кличка | Вес | Цвет |
Волчонок | 3 кг | темно-серый |
Тузик | 10 кг | белый с черными пятнами |
Трезор | 10 кг | черный |
Шарик | 18 кг | рыжий с черными подпалинами |
Бобик | 18 кг | бело-серый |
Если мы откроем этот файл
Рассмотрим простой пример XML-файла ().
<?xml version="1.0" encoding="WINDOWS-1251"?>
<tutorial>
<title>"Заметки об XSL"</title>
<author>Леонов Игорь Васильевич</author>
</tutorial>
Если мы откроем этот файл в браузере Internet Explorer, то мы увидим тот же самый текст, который приведен выше, вместе со всеми тегами и служебной информацией. Но нам не нужны теги и служебная информация! Мы хотим видеть только ту информацию, которая относится к делу, а при помощи тегов - управлять внешним видом этой информации. Эта задача решается легко и просто: необходимо к XML-файлу добавить шаблон преобразования - XSL-файл.
Перепишем наш XML-файл в следующем виде ().
<?xml version="1.0" encoding="WINDOWS-1251"?>
<?xml-stylesheet type='text/xsl' href='ex01-1.xsl'?>
<tutorial>
<title>"Заметки об XSL"</title>
<author>Леонов Игорь Васильевич</author>
</tutorial>
И создадим XSL-файл . Текст файла приведен ниже.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<p><strong><xsl:value-of select="//title"/></strong></p>
<p><xsl:value-of select="//author"/></p>
</xsl:template>
</xsl:stylesheet>
Если мы теперь откроем файл ex01-1.xsl в браузере Internet Explorer, то мы увидим, что наша задача решена, - на экране осталась только необходимая нам информация, все теги исчезли. Результат, который вы получите на экране браузера, приведен ниже.
"Заметки об XSL"
Леонов Игорь Васильевич
Легко также увидеть, что порядок вывода строк у нас определяется только содержанием шаблона преобразования - XSL-файла. При необходимости шаблон можно легко поменять, абсолютно не меняя наш основной XML-файл.
Перепишем XML-файл. Информационную часть изменять не будем, а шаблон укажем другой .
<?xml version="1.0" encoding="WINDOWS-1251"?>
<?xml-stylesheet type='text/xsl' href='ex01-2.xsl'?>
<tutorial>
<title>"Заметки об XSL"</title>
<author>Леонов Игорь Васильевич</author>
</tutorial>
Создадим XSL-файл . Текст файла приведен ниже.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<p><strong><xsl:value-of select="//author"/></strong></p>
<p><xsl:value-of select="//title"/></p>
</xsl:template>
</xsl:stylesheet>
Если мы теперь откроем файл ex01-2.xsl в браузере Internet Explorer, то результат будет другим.
Леонов Игорь Васильевич
"Заметки об XSL"
Отметим теперь момент, который является ключевым для разработчиков баз данных. Информация в XML-странице появляется, как правило, в результате запроса к базе данных. Запрос к базе данных в многопользовательской среде - это весьма дорогостоящая операция. Предположим теперь, что у нас нет XML и мы формируем стандартные статические HTML-страницы. В этом случае для решения задачи простого преобразования внешнего представления информации, например, для изменения сортировки, у нас есть два способа решения проблемы: выполнить запрос и сохранить результаты в каком-либо временном буфере на сервере или каждый раз при изменении внешнего представления выполнять новый запрос и формировать HTML-страницу заново.
Первый способ требует трудоемкого программирования, второй способ значительно увеличивает нагрузку на сервер базы данных, производительность которого часто является узким местом системы, - пользователю всегда хочется получать результаты быстрее.
XML и XSL - это исчерпывающее решение описанной выше проблемы. Фактически XML-страница - это и есть временный буфер для результатов запросов. Только вместо нестандартного и трудоемкого программирования мы теперь используем стандартный механизм XSL.
Есть и еще одно соображение, которое может быть существенным для разработчиков баз данных. Большинство современных СУБД могут форматировать результаты запроса к базе данных в виде XML-файла. То есть при построении интерфейса пользователя в рамках технологии XML и XSL мы добиваемся определенной независимости от поставщика СУБД. В части организации вывода - практически полной независимости. А эта часть весьма велика в большинстве прикладных систем, ориентированных на работу с базами данных. Конечно, помимо вывода есть еще ввод и серверная обработка бизнес-логики, но здесь вам придется искать какие-то иные решения.
Вывод результатов запроса
До тех пор, пока мы работаем с несколькими реквизитами одного и того же объекта, разницы между XML и HTML практически нет. Однако стоит нам перейти к информации, содержащей несколько строк, как выгоды XML становятся очевидны. Но прежде чем перейти к выгодам, научимся выводить на экран простую таблицу.
Рассмотрим следующий XML-файл - . Текст его приведен ниже.
<?xml version="1.0" encoding="WINDOWS-1251"?>
<tutorial>
<enimals>
<dogs>
<dog>
<dogName>Шарик</dogName>
<dogWeight caption="кг">18</dogWeight>
<dogColor>рыжий с черными подпалинами</dogColor>
</dog>
<dog>
<dogName>Тузик</dogName>
<dogWeight caption="кг">10</dogWeight>
<dogColor>белый с черными пятнами</dogColor>
</dog>
<dog>
<dogName>Бобик</dogName>
<dogWeight caption="кг">2</dogWeight>
<dogColor>бело-серый</dogColor>
</dog>
<dog>
<dogName>Трезор</dogName>
<dogWeight caption="кг">25</dogWeight>
<dogColor>черный</dogColor>
</dog>
</dogs>
</enimals>
</tutorial>
Предположим, что это результат запроса к базе данных и выведем на экран соответствующую таблицу.
XML и XSLT в примерах для начинающих
Заключительные замечания
В процессе работы над этим документом использовались примеры Microsoft и примеры с сайта . Рекомендую всем, кто интересуется Web-технологиями, посетить этот сайт. Вы найдете там полные руководства и большое количество примеров по HTML, CSS, различным аспектам XML и т.п. Все материалы на английском языке. Многие документы, например, можно скачать в виде архива и держать под рукой.
Книга Эрика Рея "Изучаем XML", Москва, "Символ", 2001. В этой книге - великолепное введение в XML и смежные стандарты (XPath, XSL и т.п.) Объем материала многократно превышает то, что есть в данном обзоре. Плюс качественный разбор основных понятий и идеи возможных применений различных технологий в реальных проектах.
Рекомендую также русскоязычный перевод спецификации "Язык преобразований XSL 1.0" (XSL Transformations 1.0), расположенный по адресу .
Большое спасибо Radj I. Halfin, который подсказал мне решение проблемы с русскими буквами в XSL-файлах.
Надеемся, что информации, приведенной в этом документе в совокупности с вашей фантазией и XSLT Reference, вам будет достаточно для воплощения в жизнь самых смелых замыслов.
A.1 Недостаток обычного пространства имен
В компьютерных дисциплинах термин "пространство имен" обычно сопоставлется с набором имен, то есть, коллекцией, не содержащей дубликатов. Однако, если бы названия, используемые в разметке XML, привязывались к такому пространству имен, это сильно уменьшило бы их полезность. В основном такие названия используются в XML документах для того, чтобы программные модули, такие как процессоры запросов, управляемые стилями машины рендеринга и управляемые схемами программы проверки, могли распознавать логические структуры документа. Рассмотрим следующий пример:
<section><title>Book-SigningEvent</title> <signing> <author title="Mr" name="Vikram Seth" /> <book title="A Suitable Boy" price="$22.95" /></signing> <signing> <author title="Dr" name="Oliver Sacks" /> <book title="The Island of the Color-Blind" price="$12.95" /></signing> </section> |
В данном примере название title появляется в разметке три раза, однако очевидно, что само по себе оно дает недостаточно информации для правильной обработки документа программным модулем.
Другая проблемная область происходит от использования "глобальных" атрибутов, что иллюстрируется следующим примером, в котором фрагмент XML документа необходимо вывести на экран с помощью стиля CSS:
<RESERVATION> <NAME HTML:CLASS="largeSansSerif">Layman, A</NAME> <SEAT CLASS="Y" HTML:CLASS="reallyImportant">33B</SEAT> <DEPARTURE>1997-05-24T07:55:00+1</DEPARTURE></RESERVATION> |
В этом случае атрибут CLASS, описывающий класс пассажира и принимающий такие значения, как "J", "Y" и "C", на всех уровнях семантики отличается от атрибута HTML:CLASS, который используется для моделирования всего синтаксического богатства HTML путем замены ограниченного набора элементов иерархией подклассов.
Язык XML 1.0 не имеет встроенного механизма декларирования "глобальных" атрибутов. Такие конструкции, как атрибут CLASS в HTML, становятся глобальными только при их тщательном описании и соответствующей интерпретации со стороны HTML приложений. Вместе с тем, атрибуты, главной отличительной чертой которых является уникальность имен, как правило, можно найти во многих приложениях.
A.2 Разделы пространства имен XML
Для того, чтобы создание полных и неполных имен могло соответствовать своему назначению, каждое имя, появляющееся в пространстве имен XML, мы сопоставляем с одним из нескольких обычных непересекающихся (то есть, структурирующих) пространств, называемых разделами пространства имен. Перечень этих разделов:
Раздел для всех типов элементов В этом разделе оказываются все типы элементов, заданные в пространстве имен XML. Каждый тип имеет уникальную , сочетание названия пространства имен и локальной части уникальным образом идентифицирует тип элемента.
Раздел глобальных атрибутов В этом разделе содержатся названия всех атрибутов, определенных в данном пространстве имен как глобальные. Единственное, что требуется от глобального атрибута - его имя должно быть уникальным для всего раздела глобальных атрибутов. Данная спецификация не содержит указаний касательно порядка использования таких атрибутов. Сочетание названия пространства имен и названия глобального атрибута идентифицирует глобальный атрибут уникальным образом.
Разделы для каждого типа элементов С каждым типом в разделе всех типов элементов связано пространство имен, в котором располагаются названия неполных атрибутов этого элемента. Это обычное пространство имен, поскольку возникновение одном и том же элементе нескольких атрибутов с одинаковыми именами XML 1.0 запрещено. Сочетание имени атрибута, типа элемента и названия пространства имен уникальным образом идентифицирует каждый неполный атрибут.
В XML документах, отвечающих требованиям данной спецификации, названия всех полных (с префиксом) атрибутов относены к разделу глобальных атрибутов, тогда как названия всех неполных атрибутов помещаются в раздел соответствующего типа элемента.
A.3 Расширенные типы элементов и названия атрибутов
Чтобы было проще задавать правила и выполнять сравнение, для каждого типа элементов и названия атрибутов в XML документе мы определяем расширенный формат, описываемый здесь средствами синтаксиса элементов XML.
[Определение:] Расширенный тип элемента представлен как пустой элемент XML типа ExpEType. Он имеет обязательный атрибут type, определяющий в этом типе , и необязательный атрибут ns, определяющий , если данный элемент является полным.
[Определение:] Расширенное имя атрибута представлено как пустой элемент XML типа ExpAName. Оно имеет обязательный атрибут name, определяющий название. Если атрибут является глобальным, он имеет обязательный атрибут ns, определяющий . В противном случае имеется обязательный атрибут eltype, определяющий тип задействованного элемента, а также необязательный атрибут elns, определяющий название пространства имен для этого элемента, если таковое известно.
Небольшое изменение приведенных ранее примеров проиллюстрирует работу расширенных типов элементов и названий атрибутов. Ниже представлены два фрагмента, сопровождаемые таблицей, показывающей обработку имен:
<!--1 --> <section xmlns='urn:com:books-r-us'> <!-- 2 --> <title>Book-Signing Event</title> <!-- 3 --> <signing> <!-- 4 --> <author title="Mr" name="Vikram Seth" /> <!-- 5 --> <book title="A Suitable Boy" price="$22.95" /> </signing> </section> |
Названия должны обрабатываться следующим образом:
Строка | Имя | Результат |
1 | section | <ExpEType type="section" ns="urn:com:books-r-us" /> |
2 | title | <ExpEType type="title" ns="urn:com:books-r-us" /> |
3 | signing | <ExpEType type="signing" ns="urn:com:books-r-us" /> |
4 | author | <ExpEType type="author" ns="urn:com:books-r-us" /> |
4 | title | <ExpAName name='title' eltype="author" elns="urn:com:books-r-us" /> |
4 | name | <ExpAName name='name' eltype="author" elns="urn:com:books-r-us" /> |
5 | book | <ExpEType type="book" ns="urn:com:books-r-us" /> |
5 | title | <ExpAName name='title' eltype="book" elns="urn:com:books-r-us" /> |
5 | price | <ExpAName name='price' eltype="book" elns="urn:com:books-r-us" /> |
<!-- 1 --> <RESERVATION xmlns:HTML="http://www.w3.org/TR/REC-html40"> <!-- 2 --> <NAME HTML:CLASS="largeSansSerif">Layman, A</NAME> <!-- 3 --> <SEAT CLASS="Y" HTML:CLASS="largeMonotype">33B</SEAT> <!-- 4 --> <HTML:A HREF='/cgi-bin/ResStatus'>Check Status</HTML:A> <!-- 5 --> <DEPARTURE>1997-05-24T07:55:00+1</DEPARTURE></RESERVATION> |
1 | RESERVATION | <ExpEType type="RESERVATION" /> |
2 | NAME | <ExpEType type="NAME" /> |
2 | HTML:CLASS | <ExpAName name="CLASS" ns=http://www.w3.org/TR/REC-html40 /> |
3 | SEAT | <ExpEType type="SEAT" /> |
3 | CLASS | <ExpAName name="CLASS" eltype="SEAT"> |
3 | HTML:CLASS | <ExpAName name="CLASS" ns="http://www.w3.org/TR/REC-html40" /> |
4 | HTML:A | <ExpEType type="A" ns="http://www.w3.org/TR/REC-html40" /> |
4 | HREF | <ExpAName name="HREF" eltype="A" elns="http://www.w3.org/TR/REC-html40" /> |
5 | DEPARTURE | <ExpEType type="DEPARTURE" /> |
A.4 Уникальность расширенных имен атрибутов
Ограничение, описанное ранее в главе "", может быть реализовано непосредственно в виде требования, что элементу не разрешается иметь два атрибута, расширенные имена которых эквивалентны, то есть имеют одинаковую пару атрибут-значение.
BБлагодарности (обсуждение стандарта)
Данный материал является результатом деятельности большого количества людей, особенно членов Рабочей Группы XML из консорциума World Wide Web, Special Interest Group и участников W3C Metadata Activity. Особенно был ценен вклад Чарльза Франксона (Charles Frankston) из компании Microsoft.
CСсылки
RFC2141
IETF (Internet Engineering Task Force) RFC 2141: URN Syntax, ред. R. Moats., май 1997.
RFC2396
IETF (Internet Engineering Task Force) RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax, ред. T. Berners-Lee, R. Fielding, L. Masinter., август 1998.
XML
Extensible Markup Language (XML) 1.0, ред. Tim Bray, Jean Paoli и C. M. Sperberg-McQueen. 10 февраля 1998. Доступна по адресу .
Декларирование пространства имен
[Определение:] Пространство имен декларируется с помощью набора зарезервированных атрибутов. Названием такого атрибута должно быть xmlns, либо оно должно использовать в качестве префикса xmlns:. Указанные атрибуты, как и любые другие атрибуты в XML, могут быть указаны явно, либо быть назначены .
Названия атрибутов для декларации пространства имен |
[1] | NSAttName | ::= | |||
| | |||||
[2] | PrefixedAttName | ::= | 'xmlns:' | [ | NSC: ] |
[3] | DefaultAttName | ::= | 'xmlns' | ||
[4] | NCName | ::= | ( | '_') ()* | /* | XML за вычетом ":" */ |
[5] | NCNameChar | ::= | | | '.' | '-' | '_' | | |
[Определение:] атрибута для ссылки URI является название пространства имен, используемое для его идентифицикации. Чтобы название пространства имен могло служить указанной цели, оно должно обладать свойствами уникальности и постоянства. Не ставится задачи непосредственного получения по этому имени схемы отображения (если таковая существует). Примером синтаксиса, построенного с подобными целями, может служить синтаксис Uniform Resource Names . Однако следует заметить, что и обычными адресами URL можно точно так же манипулировать для достижения тех же самых целей.
[Определение:] Если название атрибута соответствует сценарию , то поле определяет префикс пространства имен. В область видимости того элемента, в котором эта декларация была дана, указанный префикс используется для привязки имен элементов и атрибутов к , указанному в значении декларирующего атрибута. В таких декларациях название пространства имен пустым быть не может.
[Определение:] Если название атрибута соответствует сценарию , то указанное в значении атрибута в область видимости того элемента, где эта декларация была дана, становится названием пространства имен по умолчанию. В декларации по умолчанию значение атрибута может быть нулевым. Пространства имен по умолчанию и переопределение деклараций обсуждаются в главе "".
Пример декларации, связывающей префикс edi с пространством имен, имеющим название http://ecommerce.org/schema:
<x xmlns:edi='http://ecommerce.org/schema'> <!- для элемента "x" и его содержимого префикс "edi" связан с http://ecommerce.org/schema --> </x> |
Ограничение для пространства имен: Начальный "XML"
Префиксы, начинающиеся с последовательности из трех букв x, m, l (в любом регистре), зарезервированы для использования в XML и связанных с ним спецификациях.
DСловарь
При переводе спецификации на русский язык для ряда терминов был выбран следующий вариант перевода:
conformance document - согласованный документ; документ, отвечающий требованиям спецификации
document entity - сущность документа
entity - сущность
markup vocabulary - словарь разметки
namespace - пространство имен
nonterminal - нетерминальная конструкция
production - сценарий
qualified name - полное имя
start-tag - начальный тэг
validating processor - проверяющий процессор (XML)
Если у вас возникли какое-либо замечания, мы будем рады их получить по адресу .
Использование полных имен
В XML документах, отвечающих требованиям данной спецификации, даются для следующих типов элементов:
Типы элементов |
[9] | STag | ::= | '<' ( )* ? '>' | [ | NSC: ] |
[10] | ETag | ::= | '</' ? '>' | [ | NSC: ] |
[11] | EmptyElemTag | ::= | '<' ( )* ? '/>' | [ | NSC: ] |
Пример использования полного имени в качестве типа элемента:
<x xmlns:edi='http://ecommerce.org/schema'> <!-- пространство имен элемента 'price' - http://ecommerce.org/schema --> <edi:price units='Euro'>32.18</edi:price> </x> |
Атрибут либо , либо его название дается как :
Атрибут |
[12] | Attribute | ::= | |||
| | [ | NSC: ] |
Пример использования полного имени в качестве названия атрибута:
<x xmlns:edi='http://ecommerce.org/schema'> <!-- пространство имен атрибута 'taxClass' - http://ecommerce.org/schema --> <lineItem edi:taxClass="exempt">Baby food</lineItem> </x> |
Ограничение пространства имен: Декларированный префикс
Префикс пространства имен, если это ни xml и ни xmlns, должен быть объявлен в атрибуте, и находящемся в начальном тэге либо того элемента, где этот префикс используется, либо элемента, являющегося его предком (то есть, находиться в элементе, в которого действует префиксная разметка). Префикс xml по определению связан с названием пространства имен http://www.w3.org/XML/1998/namespace. Префикс xmlns используется только для привязки к пространству имен, но сам с каким-либо названием пространства имен не связан.
Такое ограничение может привести к трудностям в работе, если атрибут, декларирующий пространство имен, не был представлен непосредственно в XML, а был декларирован во внешней сущности как атрибут по умолчанию. Подобные декларации могут быть недоступны для программ, использующих непроверяющий XML процессор. Многие XML приложения, очевидно включая и те, которые зависят от пространства имен, не могут использовать проверяющий процессор. Для того, чтобы такие приложения работали корректно, декларации пространств имен должны даваться либо непосредственно, либо через атрибуты по умолчанию, объявленные во .
Если название элемента или тип атрибутов появляются в декларациях , они могут быть представлены при этом в виде полного имени.
Полные имена в декларациях |
[13] | doctypedecl | ::= | '<!DOCTYPE' ( )? ? ('[' ( | | )* ']' ?)? '>' |
[14] | elementdecl | ::= | '<!ELEMENT' ? '>' |
[15] | cp | ::= | ( | | ) ('?' | '*' | '+')? |
[16] | Mixed | ::= | '(' ? '#PCDATA' (? '|' ? )* ? ')*' |
| '(' ? '#PCDATA' ? ')' | |||
[17] | AttlistDecl | ::= | '<!ATTLIST' * ? '>' |
[18] | AttDef | ::= | ( | ) |
Область действия пространства имен
Считается, что декларация пространства имен относится к тому элементу, где она была указана, и всем элементам в содержимом этого элемента (если она не была переопределена другой декларацией пространства имен с таким же полем ):
<?xmlversion="1.0"?> <!-- все элементы здесь явно соотнесены с пространством имен HTML --> <html:html xmlns:html='http://www.w3.org/TR/REC-html40'> <html:head><html:title>Frobnostication</html:title></html:head> <html:body><html:p>Moved to </html:html> |
Как показано в следующем примере, в атрибутах одного элемента может быть декларировано сразу несколько префиксов пространства имен:
<?xml version="1.0"?> <!-- оба префикса пространства имен доступны отовсюду --> <bk:book xmlns:bk='urn:loc.gov:books' <bk:title>Cheaper by the Dozen</bk:title> <isbn:number>1568491379</isbn:number> </bk:book> |
Полные имена
[Определение:]
В XML документах, отвечающих требованиям данной спецификации, часть имен (конструкций, соответствующих нетерминальному ) может быть представлено в виде полных имен (qualified names), определяемых следующим образом:
Полное имя |
[6] | QName | ::= | ( ':')? |
[7] | Prefix | ::= | |
[8] | LocalPart | ::= |
Поле определяет в полном имени и должно быть связано со ссылкой URI в . [Определение:] Поле определяет локальную часть (local part) полного имени.
Заметим, что префикс используется только для хранения названия пространства имен. При построении имен, область действия которых выходит за пределы первоначального документа, приложения должны использовать название пространства имен, а не префикс.
Причины возникновения и краткое описание
Мы предвидим появление таких приложений для обработки расширенного языка разметки (XML), когда в одном XML документе (обычно называемом "словарем разметки") собраны элементы и атрибуты, определяемые и используемые во многих программных модулях. Повод для появления такой модульности: если имеется понятный словарь разметки и есть использующее его программное обеспечение, то проще использовать такую разметку еще раз, чем изобретать ее заново.
Подобные документы, содержащие несколько словарей разметки, порождают проблемы распознания и коллизии. Программные модули должны уметь распознавать тэги и атрибуты, для обработки которых они созданы, даже если имеют место "коллизии", когда выясняется, что разметка, разработанная для двух различных программных пакетов, использует одни и те же типы элементов и названия атрибутов.
Подобные соображения выдвигают требование, чтобы конструкции документа использовали универсальные имена, область действия которых выходит за рамки того документа, где они были определены. Данная спецификация описывает механизм - пространства имен XML - позволяющий выполнить это условие.
[Определение:] Пространство имен XML - это идентифицируемая с помощью ссылки URI коллекция имен, используемых в XML документах для обозначения и . Пространство имен XML отличается от тех "пространств имен", которые обычно используются в компьютерных дисциплинах, тем, что в варианте для XML оно имеет внутреннюю структуру, и, с математической точки зрения, набором не является. Данные вопросы обсуждаются в Приложении "".
[Определение:] Используемые для идентификации пространств имен ссылки URI считаются идентичными, если они совпадают с точностью до символа. Заметим, что ссылки URI, не являющиеся идентичными в указанном смысле, в действительности по функциональности могут быть эквивалентны. Примером могут служить ссылки, отличающиеся только регистром, а также ссылки во внешних сущностях, имеющие иной базовый адрес URI.
Названия в пространстве имен XML могут быть представлены в виде (qualified names), содержащих единственный символ двоеточия, делящий такое имя на и . С помощью префикса, привязанного к ссылке URI, осуществляется выбор пространства имен. Сочетание единообразно обрабатываемого URI пространства имен и собственного пространства имен документа формирует идентификатор, уникальный повсюду. Дается методика определения области видимости префикса и значения по умолчанию.
Ссылка URI может содержать символы, недопустимые для имен, поэтому саму ссылку нельзя использовать в качестве префикса пространства имен. Таким образом, префикс пространства имен служит заменителем ссылки URI. Далее описывается построенный на атрибутах синтаксис, позволяющий связь префикса пространства имен со ссылкой URI. Программное обеспечение, поддерживающее указанный сценарий использования пространства имен, должно уметь анализировать и использовать описанные декларации и префиксы.
Пространство имен по умолчанию
Считается, задаваемое относится к тому элементу, где оно декларировано (если этот элемент не имеет ), а также ко всем элементам в содержимом этого элемента, не имеющим префикса. Если поле ссылки URI в декларации пространства имен по умолчанию оказалось пустым, считается, что все элементы без префиксов в области видимости этой декларации вообще не принадлежат ни одному пространству имен. Заметим, что пространства имен, задаваемые по умолчанию, непосредственно на атрибуты не распространяются.
<?xml version="1.0"?> <!-- в данном случае элементы по умолчанию относятся к пространству имен HTML --> <html xmlns='http://www.w3.org/TR/REC-html40'> <head><title>Frobnostication</title></head> <body><p>Moved to <a href='http://frob.com'>here</a>.</p></body> </html> |
<?xml version="1.0"?> <!-- типы элементов без префикса из "books" --> <book xmlns='urn:loc.gov:books' xmlns:isbn='urn:ISBN:0-395-36341-6'> <title>Cheaper by the Dozen</title> <isbn:number>1568491379</isbn:number> </book> |
Более развернутый пример, показывающий область действия пространства имен:
<?xml version="1.0"?> <!-- первоначально по умолчанию используется пространство имен "books" --> <book xmlns='urn:loc.gov:books' xmlns:isbn='urn:ISBN:0-395-36341-6'> <title>Cheaper by the Dozen</title> <isbn:number>1568491379</isbn:number> <notes> <!-- для отдельного комментария пространством имен, используемым по умолчанию, сделать HTML --> <p xmlns='urn:w3-org-ns:HTML'> This is a <i>funny</i> book! </p> </book> |
Пространство имен по умолчанию может быть задано пустой строкой. Это будет иметь тот же самый эффект, словно в пределах видимости этой декларации пространства имен, используемого по умолчанию, вообще не было декларировано.
<?xml version='1.0'?> <Beers> <!-- здесь по умолчанию используется пространство имен HTML --> <table xmlns='http://www.w3.org/TR/REC-html40'> <th><td>Name</td><td>Origin</td><td>Description</td></th> <tr> <!-- внутри ячеек таблицы нет пространства имен, используемого по умолчанию --> <td><brandName xmlns="">Huntsman</brandName></td> <td><origin xmlns="">Bath, UK</origin></td> <td> <details xmlns=""><class>Bitter</class><hop>Fuggles</hop> <pro>Wonderful hop, light alcohol, good summer beer</pro> <con>Fragile; excessive variance pub to pub</con> </details> </td> </tr> </table> </Beers> |
Пространство имен XML обеспечивает простую
Пространство имен XML обеспечивает простую методику получения названий для элементов и атрибутов в документах, использующих расширяемый язык разметки. Осуществляется это путем привязки последних к пространствам имен, идентифицируемым с помощью ссылок URI.
Согласованность документов
В XML документах, отвечающих требованиям данной спецификации, названия атрибутов и типов элементов должны соответствовать сценарию и отвечать требованиям "Namespace Constraints".
Документ XML соответствует требованиям данной спецификации, если в нем все те лексемы, которые, согласно требованиям XML, должны отвечать сценарию из XML, в действительности соответствуют сценарию из этой спецификации.
Для документа согласованность дает следующее:
Названия типов и типов элементов либо не содержат, либо содержат только один символ двоеточия.
Названия сущностей, адресаты PI и названия нотаций не содержат символов двоеточия.
Строго говоря, значения атрибутов, декларируемые для типов ID, IDREF(S), ENTITY(IES) и NOTATION, также относятся к сценарию , а потому тоже не должны содержать символа двоеточия. Однако декларированный тип значений атрибутов доступен только для тех процессоров, которые читают декларации разметки, например для . Таким образом, если не было заявлено использование проверяющего процессора, нельзя гарантировать, что содержимое значения атрибута будет проверено на соответствие требованиям данной спецификации.
Данный документ был рассмотрен членами W3C, другими заинтересованными сторонами и утвержден Директором в качестве Рекомендации W3C. Данный документ является окончательным и может использоваться как нормативный материал для ссылки и цитирования в других документах. Участие W3C в продвижении представленной Рекомендации заключается в привлечении к ней внимания и способствовании ее широкому распространению. Тем самым наращиваются функциональные возможности и повышается степень универсальности Сети.
Перечень ошибок, обнаруженных в данной спецификации, представлен на странице .
Об ошибках, обнаруженных в данном документе, просьба сообщать по адресу .
Уникальность атрибутов
В документе XML, отвечающем требованиям данной спецификации, ни один тэг не может иметь два атрибута
с одинаковыми именами, или
с полными именами, которых совпадает, а привязаны к , которые .
Так, в следующем примере все начальные тэги bad неправильные:
<!--http://www.w3.org связано с n1 и n2 --> <x xmlns:n1="http://www.w3.org" xmlns:n2="http://www.w3.org" > <bad a="1" a="2" /> <bad n1:a="1" n2:a="2" /> </x> |
Однако в другом примере все тэги правильны (во втором случае потому, что пространство имен по умолчанию не относится к названиям атрибутов):
<!-- по умолчанию http://www.w3.org связано с n1 --> <x xmlns:n1="http://www.w3.org" xmlns="http://www.w3.org" > <good a="1" b="2" /> <good a="1" n1:a="2" /> </x> |
World Wide Web Консорциум, 14 января 1999 года
Данный документ представляет собой перевод спецификации Namespaces in XML (W3C Recommendation) на русский язык. При этом нормативным документом считается оригинальная спецификация на английском языке, которую можно найти по адресу Перевод спецификации на русский язык представлен на страницах портала "Россия-Он-Лайн": Перевод выполнен , () Представленный документ может содержать ошибки перевода. |
Данная версия:
Последняя версия:
Предыдущая версия:
Редакторы:
Tim Bray (Textuality)
Dave Hollander (Hewlett-Packard Company)
Andrew Layman (Microsoft)
© 1999 (, , ). Все права защищены. В отношении данного документа действуют правила W3C, касающиеся , , и .
Замечания по нотации и использованию
Отметим, что многие используемые в сценариях этой спецификации нетерминальные конструкции определяются не здесь, а в спецификации XML . Если определенная здесь нетерминальная конструкция имеет то же самое имя, что было определено для нетерминала в спецификации XML, то множество строк, соответствующих сценарию здесь, является лишь подмножеством всех строк, соответствующих сценарию там.
В сценариях этого документа аббревиатура NSC расшифровывается как "Namespace Constraint" (ограничение на пространство имен), одно из правил, которому должны следовать документы, отвечающие требованиям данной спецификации.
Заметим, что все использованные в примерах названия доменов Internet (за исключением w3.org) выбраны случайным образом и их не следует принимать за источник информации.