При помощи элемента XSLT 1.0
можно указать, что следует делать в случае отсутствия элемента расширения. Этот элемент заключается в элемент расширения и используется в случае его недоступности.У элемента
нет атрибутов, он содержит тело шаблона.В следующем примере я создам элемент
внутри элемента
из предыдущего примера. В случае отсутствия элемента
элемент
прекратит обработку и выдаст сообщение:
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:lxslt="http://xml.apache.org/xslt"
xmlns:redirect="org.apache.xalan.lib.Redirect"
extension-element-prefixes="redirect">
Could not create multiple output documents.
На этом мы заканчиваем введение в работу с данными в документах XML. В следующей главе мы разберем эту тему и узнаем, как изменять содержимое документа и создавать новые элементы, атрибуты и инструкции обработки.
Глава 6Преобразование в XML, HTML, XHTML, RTF
Предположим, web-узел вашей компании использует основанное на XML программное обеспечение фирмы Commerce One, в котором для безопасной коммуникации через Интернет применяется Java Message Service (JMS). Ваша деятельность была настолько успешной, что вы только что поглотили своего конкурента. К сожалению, для своего узла в Интернете ваш бывший конкурент использует другой основанный на XML продукт, RosettaNet. Как вам теперь преобразовать заказ на покупку xCBL Commerce One, написанный на XML, в заказ на покупку RosettaNet, также написанный на XML, но совершенно на другом диалекте?
Разумеется, применить XSLT. Такого рода XML-XML преобразования становятся все более и более распространенными. Все больше компаний применяют JMS для безопасных коммуникаций через Интернет, и поскольку JMS выполняется в Java, будет разумным связать JMS с основанными на Java процессорами XSLT, такими, как Xalan или Saxon.
В этой книге мы уже рассматривали преобразование XML в HTML, XML и простой текст, но в текущей главе сделаем это более подробно. Мы также рассмотрим здесь новый тип преобразования — из XML в JavaScript. В главе 10 мы познакомимся с преобразованиями из XML в базу данных на основе SQL, а в главе 11 — с преобразованиями из XML в XSL-FO.
Основная задача XSLT состоит не просто в замене одного элемента на другой, но в полной реорганизации содержимого XML-документа. Например, вам может потребоваться реорганизовать
planets.xml
в терминах плотности планет при помощи XSLT для создания нового XML-документа:
.983
Mercury
.0553
58.65
1516
.943
Venus
.815
116.75
3716
1
Earth
1
1
2107
Мы рассмотрим преобразование, которое полностью меняет содержимое
planets.xml
, оставляя только небольшой код HTML и код JavaScript для отображения нескольких кнопок в браузере.До сих пор мы создавали новые элементы только при помощи элементов буквального результата, то есть рассматривая новые элементы как текст и встраивая их в таблицу стилей. Но, как мы увидим в этой главе, не всегда возможно знать имена создаваемых новых элементов. Можно состыковать вместе создаваемые элементы по ходу дела, рассматривая их как сырой текст, но это явная недоработка, поскольку разметка трактуется как текст. В этой главе мы начнем применять элементы XSLT
,
,
и
для создания новых элементов, атрибутов, инструкций обработки и комментариев на этапе выполнения. Хорошее знание этих элементов необходимо при реорганизации содержимого XML.Мы также рассмотрим использование режимов XSLT для осуществления нескольких преобразований с документом и сориентируемся, как применять только один из нескольких подходящих шаблонов.
В большей части этой главы исследуются возможности элемента
, с краткого обзора которого я и начну.Элемент
С элементом
мы впервые познакомились в главе 2 и использовали его, главным образом, для задания типа результирующего документа. Этот тип может задать, например, будет ли процессор XSLT записывать инструкцию обработки XML,
, в начале документа, а также задать тип MIME (такой, как «text/xml
» или «text/html
») документов, отправляемых процессором XSLT из web-сервера браузеру. Кроме того, если вы установите выходной тип в HTML, большинство процессоров XSLT смогут распознать, что не всем элементам HTML необходимы закрывающие или открывающие теги и т.п.В следующем списке перечислены атрибуты
:•
cdata-section-elements
(необязательный). Задает имена тех элементов, чье содержимое должно выводиться как разделы CDATA
. Принимает значения списка QName
, разделенного символами-разделителями;•
doctype-public
(необязательный). Задает открытый идентификатор, который будет использован в объявлении
в выходных данных. Устанавливается в строковое значение;•
doctype-system
(необязательный). Задает системный идентификатор, который будет использован в объявлении
в выходных данных. Устанавливается в строковое значение;•
encoding
(необязательный). Задает кодировку символов. Устанавливается в строковое значение;•
indent
(необязательный). Определяет, будет ли выходной документ выровнен с отражением структуры вложенности. Устанавливается в yes
или no
;•
media-type
(необязательный). Задает тип MIME вывода. Устанавливается в строковое значение;•
method
(необязательный). Задает формат вывода. Принимает значения «xml
», «html
», «text
» или допустимое имя QName
;•
omit-xml-declaration
(необязательный). Определяет, будет ли включено в вывод объявление XML. Устанавливается в «yes
» или «no
»;•
standalone
(необязательный). Определяет, будет ли включено в вывод отдельное объявление XML, и если да — устанавливает его значение. Устанавливается в yes
или no
;•
version
(необязательный). Задает версию вывода. Принимает значение допустимого NMToken.Чаще, всего используется атрибут
method
, поскольку именно он определяет требуемый тип выходного дерева. Официально методом вывода до умолчанию является HTML, при условии, что выполняются все три следующих условия:• корневой узел результирующего дерева имеет дочерний элемент;
• в названии элемента документа результирующего дерева присутствует часть «
html
» (в любой комбинации верхнего и нижнего регистров) и пустой URI пространства имен;• все текстовые узлы перед первым дочерним элементом корневого узла содержат только символы-разделители.
Если выполняются все три этих условия, то по умолчанию метод вывода устанавливается в HTML. В ином случае методов вывода по умолчанию является XML.
Тем не менее, не стоит полагаться на установки метода вывода по умолчанию, лучше явно присвоить этому атрибуту значение. Три распространенных значения атрибута
method
— «html
», «xml
» и «text
», и мы познакомимся с ними в следующих разделах.Метод вывода: HTML
Для метода вывода HTML процессор XSLT должен предпринять определенные действия. Например, для этого метода атрибут
version
определяет версию HTML. Значение по умолчанию — 4.0.Этот метод не должен добавлять завершающий тег для пустых элементов. (Для HTML 4.0 пустыми элементами являются
,
,
,
,
,
,
, ![]()
,
,
,
,
и
.) Метод вывода HTML должен распознавать названия элементов HTML независимо от регистра.В соответствии с W3C, метод вывода HTML не должен скрывать содержимое элементов
или
. Например, следующий элемент буквального результата:
if (х < у) {...}
или следующий, использующий раздел CDATA:
должен быть преобразован в:
if (х < у) {...}
Метод вывода HTML не должен также подавлять символы <, встречающиеся в значениях атрибутов.
При установке метода вывода в HTML процессор может учесть атрибут выравнивания. Если этот атрибут установлен в
yes
, процессор XSLT может добавить (или удалить) символы-разделители для выравнивания результирующего документа, поскольку это не влияет на отображение документа в браузере. Для метода вывода HTML значением по умолчанию является «yes».Как вы могли предположить, метод вывода HTML завершает инструкции обработки при помощи
>
, а не ?>
, а также поддерживает отдельные атрибуты, как и HTML. Например, тегбудет преобразован в:
Для этого метода можно установить атрибут
media-type
, значением по умолчанию для которого является «text/html
». Метод HTML не должен убирать символ &, который появляется в значении атрибута, если сразу за ним следует фигурная скобка. Атрибут encoding
задает используемую кодировку. Если присутствует элемент
, этот метод вывода должен добавить элемент <МЕТА>
сразу же после тега
, определяя кодировку символов:
<МЕТА http-equiv="Content-Type" content="text/html; charset=utf-8">
.
.
.
При помощи атрибутов
doctype-public
или doctype-system
можно вывести объявление типа документа непосредственно перед первым элементом, как мы увидим при преобразовании XML в XHTML.Таковы правила вывода HTML. Ниже приведен пример преобразования из XML в HTML с небольшими отклонениями. В этом случае таблица стилей будет фактически генерировать код JavaScript, демонстрируя создание JavaScript при помощи XSLT. В частности, мы прочитаем
planets.xml
и создадим новый документ HTML, отображающий три кнопки — по одной для каждой из трех планет в planets.xml
. При щелчке на кнопке на странице будет выведена масса соответствующей планеты.Все, что нам понадобится (листинг 6.1), — это два элемента
: один для прохода в цикле по трем планетам и создания для каждой кнопки HTML; и один для прохода по планетам и создания для каждой функции JavaScript. В качестве имен функций JavaScript я воспользуюсь названием планет; при вызове функция выведет массу соответствующей планеты. Заметьте, что для создания нужного кода JavaScript нужно всего лишь применить элемент
для получения названий и масс планет. Я также применю два новых элемента XSLT,
и
, которые мы рассмотрим позже в этой главе, для создания нового элемента и задания для него набора атрибутов.Листинг 6.1. Преобразование в JavaScript
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
The Mass Page
function () {
display.innerHTML = 'The mass of
equals
Earth masses.'
}
The Mass Page
BUTTON
()
Результат, включая элемент
для нового кода JavaScript (листинг 6.2).Листинг 6.2. Результирующий документ с JavaScript
The Mass Page
function Mercury() {
display.innerHTML =
'The mass of Mercury equals .0553 Earth masses.'
}
function Venus() {
display.innerHTML = 'The mass of Venus equals .815 Earth masses.'
}
function Earth() {
display.innerHTML = 'The mass of Earth equals 1 Earth masses.'
}
The Mass Page
Как видите, при помощи XSLT я написал код JavaScript для прохода в цикле по планетам. Этот документ HTML показан на рис. 6.1. При щелчке на кнопку выводится масса соответствующей планеты.
Рис. 6.1. Преобразование XML в HTML при помощи JavaScript
Метод вывода: XML
Формально при использовании метода вывода XML процессор XSLT создает хорошо сформированный внешний объект XML, который можно разобрать на общих условиях. Если корневой узел результирующего дерева имеет единственный дочерний узел-элемент и не имеет текстовых дочерних узлов. Тогда объект будет также хорошо сформированным документом XML.
При использовании метода вывода XML атрибут
version
устанавливает версию XML результата. Заметьте, что если процессор XSLT не поддерживает эту версию XML, он будет использовать ту версию XML, которую поддерживает. По умолчанию установлено значение 1.0.Атрибут
encoding
устанавливает кодировку для результирующего документа. Процессоры XSLT должны поддерживать, по крайней мере, значения «UTF-8» и «UTF-16». Если процессор XSLT работает с другими значениями и не поддерживает указанную кодировку, он может сгенерировать ошибку. Если он этого не сделает, процессор должен использовать вместо нее UTF-8 иди UTF-16. Процессор XSLT не должен использовать кодировку, которая не была принята консорциумом W3C (см. www.ww3.org/TR/REC-xml). Если никакой атрибут кодировки не указан, по умолчанию процессор XSLT должен выбрать «UTF-8» или «UTF-16».ОБРАБОТКА НЕИЗВЕСТНЫХ СИМВОЛОВ
Если результирующий документ содержит символ, который не может быть представлен в кодировке, используемой процессором XSLT для вывода, символ допустимо вывести как ссылку на символ. Если это невозможно, процессор XSLT должен сгенерировать ошибку.
Как и в случае с методом вывода HTML, если атрибут
indent
установлен в «yes», метод вывода XML может добавить или удалить символы-разделители в результирующее дерево для того, чтобы выровнять результат. Значение по умолчанию — no. Заметьте, что если символы-разделители отбрасываются, информационное множество результирующего XML-документа должно быть таким же, как если бы символы-разделители вообще не добавлялись и не удалялись для выравнивания документа.ВЫРАВНИВАНИЕ ДОКУМЕНТОВ СО СМЕШАННЫМ СОДЕРЖИМЫМ
Для документов со смешанным содержимым лучше не устанавливать атрибут indent в «yes», поскольку это вносит путаницу в работу процессора XSLT.
При помощи атрибута
cdata-section-elements
можно задать разделенный символами-разделителями список имен элементов, чье содержимое должно трактоваться как разделы CDATA
. Например, если установить атрибут cdata-section-elements
в «DATA
»:
то следующий элемент буквального результата:
<:DOCUMENT>
будет преобразован в:
]]>
Кроме того, метод вывода XML будет выводить в результирующий документ объявление XML, если только атрибут
omit-xml-declaration
не будет установлен в yes
. Как правило, объявление XML, помещаемое в результирующий документ, обычно включает версию XML (что обязательно) и информацию о кодировке (хотя формально информация о кодировке в документах XML не обязательна). Если задан атрибут standalone
, результирующий документ должен включать объявление отдельного документа с тем же значением, что и значение у атрибута standalone
.При использовании атрибута
doctype-system
процессор создает объявление типа документа непосредственно перед первым элементом. В этом случае имя, следующее за
, будет именем корневого элемента. Заметьте, что если вы также используете атрибут doctype-public
, процессор XSLT выведет «PUBLIC
», вслед за ним открытый идентификатор и затем системный идентификатор. Если вы не используете атрибут doctype-public
, процессор выведет «SYSTEM
» и вслед за ним системный идентификатор. Теоретически атрибут doctype-public
должен игнорироваться, если не задан также атрибут doctype-system
, хотя большинство процессоров, кажется, не следуют этому правилу. Мы увидим, как работать с атрибутами doctype-public
и doctype-system
в этой главе при преобразовании XML в XHTML.Наконец, для метода вывода XML значением по умолчанию для атрибута
media-type
является «text/xml
».Вы уже встречали в этой книге многие XML-XML преобразования. Например, преобразование из главы 4 просто копировало один документ XML в другой. Обратите внимание на метод вывода, который установлен в XML:
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Этот пример был приведен в начале главы, в нем
planets.xml
реорганизован на основе плотности планет:
.983
Mercury
.0553
58.65
1516
.943
Venus
.815
116.75
3716
1
Earth
1
1
2107
Вот таблица стилей (листинг 6.3), создающая это преобразование.
Листинг 6.3. Реорганизация planets.xml на основе плотности
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Следующий пример впервые был приведен в главе 5. В этом случае я только перечислил планеты из
planets.xml
, но в выходном документе я хотел видеть не просто фразу «The first three planets are: Mercury Venus Earth» (первые три планеты: Меркурий Венера Земля), a «The first three planets are: Mercury, Venus, and Earth.». Для этого я применил элементы
:
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
The Planets
The first three planets are:
.
and
.
И вот результат:
The Planets
The first three planets are: Mercury, Venus, and Earth.
Хотя многие книги рассматривают главным образом преобразования из XML в HTML, важно понять, что преобразования XML-XML завоевывают все большую популярность, поэтому на них я также останавливаю ваше внимание.
Метод вывода: текст
Этот метод вывода представляет простой текст. В данном случае выходной документ являет собой только простой текст дерева документа. То есть процессор XSLT создает результирующее дерево, выводя строковое значение каждого текстового узла, без каких-либо сокращений.
Значением по умолчанию для атрибута
media-type
является «text/plain
». Атрибут encoding
устанавливает кодировку, используемую процессором XSLT для преобразования последовательностей символов в последовательности байтов. Заметьте, что если результирующий документ содержит символ, который не может быть представлен в выходной кодировке, процессор XSLT должен сгенерировать ошибку.В листинге 6.4
planets.xml
преобразуется в простой текст при помощи метода текстового вывода.Листинг 6.4. Преобразование в простой текст
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
's mass is
Earth masses. Its radius is
miles. Its day is
Earth days long.
И вот результат — просто чистый текст, никакой разметки, никаких пропущенных символов, никаких инструкций обработки:
Mercury's mass is .0553 Earth masses. Its radius is 1516 miles. Its day is 58.65 Earth days long.
Venus's mass is .815 Earth masses. Its radius is 3716 miles. Its day is 116.75 Earth days long.
Earth's mass is 1 Earth masses. Its radius is 2107 miles. Its day is 1 Earth days long.
С другой стороны, метод текстового вывода предназначен не только для создания простого текста, он также применяется для любых текстовых форматов, отличных от XML и HTML. Как мы видели в главе 2, с его помощью можно создавать форматированные документы в формате Rich Text Format (RTF). Rich Text Format использует встроенные текстовые коды, задающие формат документов, и при помощи метода текстового вывода вы можете самостоятельно поместить эти коды в документы.
Следующий пример таблицы стилей первоначально был приведен в главе 2, где она использовалась с целью перевода planets.xml в формат RTF, для понимания которого вы теперь лучше вооружены. В этом случае я преобразую
planets.xml
в planets.rtf
, используя коды RTF как элементы буквального результата:
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
{\rtf1\ansi\deff0{\fonttbl
{\\fcharset0 Courier New:}}
\viewkind4\ucl\pard\lang1033\b\ The Planets Table\par
\b0 Name\tab Mass\tab Rad.\tab Day\par
\par
}
\tab
\tab
\tab
\tab
\par
Результирующий документ RTF,
planets.rtf
, показан на рис. 6.2 в редакторе Microsoft Word 2000.Рис. 6.2. Файл planets.rtf в Microsoft Word
Заметьте, что методом вывода является текст, а не что-нибудь наподобие «
rtf
»:
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
{\rtf1\ansi\deff0{\fonttbl
{\\fcharset0 Courier New:}}
\viewkind4\ucl\pard\lang1033\b\ The Planets Table\par
.
.
.
Отметьте также, что я поместил коды RTF сразу же после элемента
, поскольку документы RTF должны с самого начала начинаться с кодов RTF; если бы я начал вставлять коды RTF на следующей строке, как, например:
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
{
\rtf1\ansi\deff0{\fonttbl
{\\fcharset0 Courier New:}}
\viewkind4\ucl\pard\lang1033\b\ The Planets Table\par
.
.
.
то выходной файл RTF начинался бы с символа новой строки, что привело бы к ошибке в приложении, работающем с файлом RTF (например, вероятно, Microsoft Word).
Вывод в формате XHTML
W3C представил XHTML как последователя HTML, но ни в XSLT 1.0, ни в рабочем проекте XSLT 1.1 нет никакой специальной поддержки для преобразований из XML в XHTML. Предполагается, что надлежащая поддержка будет включена в XSLT 2.0. Тем не менее, при помощи процессоров XSLT все равно можно создавать документы XHTML.
ПОДРОБНЕЕ О XHTML
Если вы хотите узнать больше о XHTML, обратитесь к источникам: W3C рекомендация XHTML 1.0 по адресу www.w3.org/TR/xhtml1/, а также рекомендация XHTML 1.1 по адресу www.w3.org/TR/xhtml11/.
Помимо заботы о том, что ваш документ должен удовлетворять правилам XHTML (таким, как отсутствие отдельных атрибутов, заключение в кавычки всех значений атрибутов, использование для разметки символов в нижнем регистре, наличие для каждого открывающего тега закрывающего, проверка того, что документ является хорошо сформированным XML, и т.д.), основная задача — гарантировать, что в результирующем документе появится элемент .
Ниже приведены элементы
, которые следует использовать с тремя типами XHTML 1.0 — строгим (strict), переходным (transitional) и кадровым (frameset):
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
А вот элемент
для XHTML 1.1:
PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
ЭЛЕМЕНТЫ И HTML 4.01
Строго говоря, даже документы HTML должны начинаться с элемента . Официально существует три формы HTML 4.01: строгая (strict), переходная (transitional) и кадровая (frameset). Вот полные элементы для этих версий: , и . Если вы генерируете совершенно правильные документы HTML, не забудьте добавить в них этот элемент. Дополнительную информацию можно получить по адресу www.w3.org/TR/html40/struct/global.html.
При установке метода вывода в XML для создания элемента
можно воспользоваться атрибутами doctype-system
и doctype-public
элемента
. Вот пример элемента
, создающего элемент
для переходного XHTML 1.0:
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
indent="yes"/>
В листинге 6.5 приведена полная таблица стилей
planets.html
, использующая этот элемент
для преобразования planets.xml
в допустимый документ XHTML.Листинг 6.5. Преобразование planets.xml в XHTML
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
indent="yes"/>
The Planets Table
The Planets Table
Name
Mass
Radius
Day
Вот результирующий файл XHTML:
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
The Planets Table
The Planets Table
Name
Mass
Radius
Day
Mercury
.0553 (Earth = 1)
1516 miles
58.65 days
Venus
.815 (Earth = 1)
3716 miles
116.75 days
Earth
1 (Earth = 1)
2107 miles
1 days
Полученный документ,
planets.html
, является и хорошо сформированным, и допустимым документом XHTML 1.0 — в соответствии с программой допустимости W3C для HTML и XHTML, расположенной по адресу: http://validator.w3.org/file-upload.html. Заметьте, что, поскольку документы XHTML являются в то же время хорошо сформированными XML-документами, мы воспользовались методом вывода XML, — поэтому преобразование не было слишком сложным; единственной сложностью оказалось создание элемента
.Изменение структуры документа на основе входных данных