XSLT

Холзнер Стивен

Глава 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 для осуществления нескольких преобразований с документом и сориентируемся, как применять только один из нескольких подходящих шаблонов.

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

 

Элемент <xsl:output>

 

С элементом мы впервые познакомились в главе 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 не должен скрывать содержимое элементов

или следующий, использующий раздел CDATA:

должен быть преобразован в:

Метод вывода 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">

 

 

  

   

     </p> <p class="paragraph">      The Mass Page </p> <p class="paragraph">     

   

   

  

   

    

The Mass Page

    

   

    

    

    

    

   

   

   

  

 

 

  BUTTON

 

  ()

 

Результат, включая элемент

 

 

 

  

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">

 

 

 

   </p> <p class="paragraph">     The Planets </p> <p class="paragraph">    

  

    The first three planets are:

   

  

 

 

  

  .

  and

  .

 

И вот результат:

  </p> <p class="paragraph">   The Planets </p> <p class="paragraph">  

 

  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">

ЭЛЕМЕНТЫ <!DOCTYPE> И HTML 4.01

Строго говоря, даже документы HTML должны начинаться с элемента <!DOCTYPE>. Официально существует три формы HTML 4.01: строгая (strict), переходная (transitional) и кадровая (frameset). Вот полные элементы <!DOCTYPE> для этих версий: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">, <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> и <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">. Если вы генерируете совершенно правильные документы 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"/>

 

 

  

    </p> <p class="paragraph">      The Planets Table </p> <p class="paragraph">     

   

   

    

     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">

 

   </p> <p class="paragraph">    The Planets Table </p> <p class="paragraph">  

 

 

 

   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, — поэтому преобразование не было слишком сложным; единственной сложностью оказалось создание элемента .

 

Изменение структуры документа на основе входных данных

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

У вас уже есть небольшой опыт в этой области, поскольку мы работали с шаблонами значений атрибутов в главе 3. Как вы помните, при помощи таких шаблонов можно присвоить атрибуту значение выражения XPath, если заключить это выражение в фигурные скобки, { и }. Например, чтобы установить атрибут NAME в строковое значение элемента , дочернего элемента контекстного узла, это значение можно присвоить так: NAME={DESCRIPTION}. Теперь мы можем более подробно рассмотреть всю тему создания новых элементов и атрибутов «с ходу», начав с .

 

Элемент <xsl:element>: создание новых элементов на этапе выполнения

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

У этого элемента три атрибута:

• name (обязательный). Имя создаваемого элемента. Принимает значение шаблона значений атрибута, возвращающего QName;

• namespace (необязательный). URI пространства имен нового элемента. Принимает значение шаблона значений атрибута, возвращающего URI;

• use-attribute-sets (необязательный). Задает наборы атрибутов, содержащие атрибуты этого элемента. Принимает значение списка элементов QName, разделенных символами-разделителями.

Элемент содержит тело шаблона.

Пусть, например, мне нужно хранить названия планет в атрибутах NAME, а не в элементе в planets.xml:

 

  .0553

  58.65

  1516

  .983

  43.4

 

 .

 .

 .

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

 

  .0553

  58.65

  1516

  .983

  43.4

 

 .

 .

 .

В этом случае я не знаю имени выходного элемента до времени выполнения, потому и не могу просто применить элемент буквального результата. Я мог бы скомпоновать новый элемент, трактуя его как текст (что и показано в примере ниже, где я вывожу символы, подобные «<», при помощи атрибута disable-output-escaping элемента ): 

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 

 

  

  

  

 

 

  <

  

  >

 

  </

  

  >

 

 

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

Листинг 6.6. Применение <xsl:element>

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 

 

 

  

  

 

 

  

  

  

 

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

 

  .0553

  58.65

  1516

  .983

  43.4

 

 

  .815

  116.75

  3716

  .943

  66.8

 

 

  1

  1

  2107

  1

  128.4

 

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

 

Элемент <xsl:attribute>: создание новых атрибутов

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

У элемента два атрибута:

• name (обязательный). Имя нового атрибута. Принимает значение шаблона значений атрибута, возвращающего QName;

• namespace (необязательный). Пространство имен нового атрибута. Устанавливается в URI.

Этот элемент содержит в себе тело шаблона, которое устанавливает значение атрибута.

В листинге 6.7 я создаю новые элементы с атрибутами, которые соответствуют различным названиям планет (значения берутся из атрибута COLOR исходных элементов ).

Листинг 6.7. Применение <xsl:attribute>

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 

  

   

     </p> <p class="paragraph">      Planets </p> <p class="paragraph">     

   

   

   

   

  

 

 

  

  

   

   

  

 

Как можно видеть в приведенном ниже результате, я создал новые атрибуты «с ходу», используя названия планет:

<НТМL>

 

   </p> <p class="paragraph">    Planets </p> <p class="paragraph">   

 

 

 

  

 

  

 

  

 

 

Элемент <xsl:comment>: создание комментариев

По ходу дела можно также создавать и комментарии при помощи элемента . Этот элемент не имеет атрибутов и содержит тело шаблона, задающего текст комментария.

В листинге 6.8 я создаю комментарии для замены элементов ; текст комментария включает название планеты.

Листинг 6.8. Применение <xsl:comment>

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 

  

   

     </p> <p class="paragraph">      Planets </p> <p class="paragraph">     

   

  

   

   

 

 

 

  This was the element

 

Вот результат:

 

   </p> <p class="paragraph">    Planets </p> <p class="paragraph">   

 

 

 

  

  

 

 

Элемент <xsl:processing-instruction>: создание инструкций обработки

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

• name (обязательный). Задает имя инструкции обработки. Принимает значение шаблона значений атрибута, возвращающего NCName.

В следующем примере я удалил инструкцию из начала planets.xml:

 

  Mercury

  .0553

  58.65

  1516

  .983

  43.4

 

 

  Venus

  .815

  116.75

  3716

  .943

  66.8

 

 .

 .

 .

Для того чтобы снова добавить эту инструкцию обработки, можно применить элемент (листинг 6.9). Пункты type и href в инструкции обработки, например , в действительности не являются атрибутами, поэтому их значения нужно устанавливать не при помощи , а используя простой текст.

Листинг 6.9. Применение <xsl:processing-instruction>

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 

 

  

   type="text/xml" href="planets.xsl"

  

  

 

 

 

  

 

 

Вот результат, где инструкция обработки снова на месте:

 

  Mercury

  .0553

  58.65

  1516

  .983

  43.4

 

 

  Venus

  .815

  116.75

  3716

  .943

  66.8

 

 .

 .

 .

 

Элемент <xsl:document>: создание нескольких выходных документов

В рабочем проекте XSLT 1.1 был представлен новым элемент, , предназначенный для поддержки нескольких выходных документов, — и, скорее всего, этот элемент будет добавлен в XSLT 2.0. Он имеет следующие атрибуты:

• href (обязательный). Указывает место, в которое должен быть помещен новый документ. Устанавливается в абсолютный или относительный URI, без идентификатора фрагмента;

• method (необязательный). Устанавливает метод вывода, используемый для создания результирующего документа. Устанавливается в «xml», «html», «text» или QName, которое не является NCName;

• version (необязательный). Задает версию выходного документа. Устанавливается в NMTOKEN;

• encoding (необязательный). Задает кодировку выходного документа. Устанавливается в строку; 

• omit-xml-declaration (необязательный). Принимает значения «yes» или «no» для того, чтобы пропускать или не пропускать объявление XML;

• cdata-section-elements (необязательный). Определяет имена тех элементов, чье содержимое вы хотите вывести как разделы CDATA. Принимает значение разделенного символами-разделителями списка QName;

• doctype-public (необязательный). Определяет открытый идентификатор, который будет использован в объявлении вывода. Устанавливается в строковое значение;

• doctype-system (необязательный). Определяет системный идентификатор, который будет использован в объявлении вывода. Устанавливается в строковое значение;

• encoding (необязательный). Задает кодировку символов. Устанавливается в строковое значение;

• indent (необязательный). Определяет выравнивание вывода для отображения структуры вложенности. Устанавливается в «yes» или «no»;

• media-type (необязательный). Задает тип MIME вывода. Устанавливается в строковое значение;

• standalone (необязательный). Определяет, нужно ли включать в вывод отдельное объявление, и если да, задает его значение. Устанавливается в «yes» или «no».

Этот элемент содержит тело шаблона.

В следующем примере, основанном на упрощенной таблице стилей, я создаю в документе HTML две рамки (frame), и два HTML-документа, которые будут в них отображаться, frame1.html и frame2.html. Первую рамку и документ, который в ней появится, frame1.html, я создам при помощи следующим образом (заметьте, что здесь я устанавливаю атрибут version в «1.1», поскольку мы используем возможность, входящую только в рабочий проект XSLT 1.1, но «1.1», вероятно, не будет правильным значением атрибута version в долгосрочном периоде; если элемент будет включен в XSLT 2.0, версию следует установить в «2.0»):

 

   </p> <p class="paragraph">    Two Frames </p> <p class="paragraph">   

 

    

 

   

    

      </p> <p class="paragraph">       Frame 1 </p> <p class="paragraph">      

    

   

    

This is frame 1.

   

   

  

  .

  .

  .

После этого я могу создать вторую рамку и документ для вывода в нее, frame2.html (листинг 6.10).

Листинг 6.10. Применение <xsl:document>

 

  </p> <p class="paragraph">    Two Frames </p> <p class="paragraph">   

 

   

  

   

    

      </p> <p class="paragraph">       Frame 1 </p> <p class="paragraph">     

    

   

    

This is frame 1.

   

  

 

  

 

  

   

     </p> <p class="paragraph">       Frame 2 </p> <p class="paragraph">      

    

    

     

This is frame 2.

    

   

  

 

ПРИМЕР ТОЛЬКО ДЛЯ XSLT 1.1

Обратите внимание на то, что этот пример предназначен только для рабочего проекта XSLT 1.1. Ни один из известных мне доступных процессоров XSLT пока не обрабатывает элемент <xsl:document>.

 

Элемент <xsl:namespace>: создание объявлений пространств имен

В XSLT 2.0 включен еще один новый элемент: , позволяющий добавлять в результирующий документ объявления пространств имен. Однако на текущий момент больше об этом элементе ничего не известно, так что я не могу дать здесь более подробную информацию. Следите за web-узлом W3C.

 

Элемент <xsl:attribute-set>: создание наборов атрибутов

Иногда при создании нового элемента возникает потребность добавить в него сразу несколько атрибутов. Существует простой способ сделать это при помощи элемента . У этого элемента два атрибута:

• name (обязательный). Имя набора атрибутов. Устанавливается в QName;

• use-attribute-sets (необязательный). Имена других наборов атрибутов, которые вы хотите включить в этот набор. Устанавливается в список QName, разделенных символами-разделителями.

Элемент содержит элементы , по одному для каждого нового создаваемого атрибута. При использовании для создания нового набора атрибутов элемента нужно задать имя набору. Затем при создании нового элемента для использования набора атрибутов это имя можно присваивать атрибуту use-attribute-sets элементов , , и даже самого элемента .

Ранее в текущей главе мы уже рассматривали один пример применения наборов атрибутов в JavaScript при создании шаблона. В том примере я при помощи набора атрибутов задавал все атрибуты HTML-кнопок планет и затем создавал их, используя этот набор атрибутов в элементе :

 

   

   

The Mass Page

  

   

    

   

  

   

  

  

 

 

 BUTTON

 

 ()

В результирующем документе такой набор атрибутов был добавлен каждой кнопке HTML:

<Р>

   

   

    

   

   

   

  

 

   

   

    

    

    

   

  

 

 .

 .

 .

После этого я устанавливаю нужные правила шаблона (листинг 6.13), оба для режима обработки «fancy», который выделяет выходные данные полужирным, и не задаю никакого специального режима обработки.

Листинг 6.13. Применение режимов

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 

  

   

     </p> <p class="paragraph">      The Planets Table </p> <p class="paragraph">    

   

   

    

     The Planets Table

    

   

     

     

      

      

      

     

    

    

Name Mass Radius Day

   

 

 

 

  

   

   

    

   

   

   

  

 

   

   

    

    

    

   

  

 

 

 

 

 

  

  

  

 

 

 

 

  

 

 

  

 

  

 

 

 

 

 

  

  

   

   

 

 

 

  

  

  

  

 

 

 

  

  

  

   

  

 

Вот результат. Заметьте, что одни только данные Земли выделены полужирным:

 

   </p> <p class="paragraph">    The Fancy Planets Table </p> <p class="paragraph">   

 

 

  

   The Fancy 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

 

Этот документ показан на рис. 6.4.

Рис. 6.4. Применение режимов обработки 

Режимы также очень удобны в том случае, когда требуется обработать один и тот же документ более одного раза; классический пример — создание оглавления.

Следующий пример демонстрирует создание оглавления. Я добавил в planets.xml оглавление в элементе (table of contents, оглавление), имеющем три элемента для каждой из планет. Заметьте, что здесь мне необходимо применить два шаблона, выбирающие элементы , — один для создания оглавления и еще один для копирования всех элементов в результирующий документ — я использую режимы для того, чтобы их различать. Начну с установки режима в «toc» и применения шаблона, который поддерживает этот режим и создает оглавление:

 xmlns:xsl="http//www.w3.org/1999/XSL/Transform">

 

 

  

   

   

   

   .

   .

   .

 

 

 

  

  

  

 

 .

 .

 .

Затем я применяю общий шаблон без каких-либо режимов обработки ко всем элементам и атрибутам, копируя их в результирующий документ (листинг 6.14).

Листинг 6.14. Создание оглавления

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 

 

  

   

   

   

  

  

 

 

  

  

 

 

 

  

  

  

 

И, наконец, результат, выводящий planets.xml с оглавлением:

 

  Mercury

  Venus

  Earth

 

 

  Mercury

  .0553

  58.65

  1516

  .983

  43.4