KnigaRead.com/

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

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Стивен Холзнер, "XSLT" бесплатно, без регистрации.
Перейти на страницу:

 </xsl:template>

</xsl:stylesheet>

Вот как это делается; посмотрите теперь на результирующий документ, в котором значения в различных элементах были преобразованы в атрибуты:

<?xml version="1.0" encoding="UTF-8"?>

<PLANETS>

 <PLANET DAY="58.65" RADIUS="1516" MASS=".0553" NAME="Mercury"/>

 <PLANET DAY="116.75" RADIUS="3716" MASS=".815" NAME="Venus"/>

 <PLANET DAY="1" RADIUS="2107" MASS="1" NAME="Earth"/>

</PLANETS>

Предположим теперь, что нам также нужно включить все единицы измерения. Каждый элемент <MASS>, <NAME> и <RADIUS> содержит атрибут UNITS, задающий единицы измерения, и можно извлечь эти значения. Контекстным узлом является элемент <PLANET>, поскольку шаблон установлен для выбора этого элемента, поэтому на дочерние элементы <MASS>, <NAME> и <RADIUS> можно ссылаться как "MASS", "NAME" и "RADIUS". Для обращения к атрибуту UNITS этих элементов можно использовать синтаксис "MASS/@UNITS", "NAME/@UNITS", и "RADIUS/@UNITS":

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:output method="xml"/>

 <xsl:template match="PLANETS">

  <xsl:copy>

   <xsl:apply-templates select="PLANET"/>

  </xsl:copy>

 </xsl:template>


 <xsl:template match="PLANET">

  <PLANET NAME="{NAME}"

   MASS="{MASS} {MASS/@UNITS}"

   RADIUS="{RADIUS} {RADIUS/@UNITS}"

   DAY="{DAY} {DAY/@UNITS}"/>

 </xsl:template>

</xsl:stylesheet>

И вот результат, включающий единицы измерения:

<?xml version="1.0" encoding="UTF-8"?>

<PLANETS>

 <PLANET DAY="58.65 days" RADIUS="1516 miles"

  MASS=".0553 (Earth = 1)" NAME="Mercury"/>

 <PLANET DAY="116.75 days" RADIUS="3716 miles"

  MASS=".815 (Earth = 1)" NAME="Venus"/>

 <PLANET DAY="1 days" RADIUS="2107 miles"

  MASS="1 (Earth = 1)" NAME="Earth"/>

</PLANETS>

Заметьте, что в шаблонах значений атрибутов нельзя использовать вложенные фигурные скобки, и в выражении, использующем фигурные скобки, — таком как function printHello {cout << 'Hello';} — фигурные скобки необходимо удваивать, для того чтобы процессор XSLT их игнорировал: function printHello {{cout<<'Hello';}}.

Шаблоны значений атрибутов всегда работают с контекстным узлом. Тем не менее, нельзя использовать шаблоны значений атрибутов в произвольном месте таблицы стилей, что зачастую и вызывает затруднения у XSLT-разработчиков. Шаблоны значений атрибутов можно использовать только в следующих местах:

• элементы буквального результата;

• элементы расширения (см. главу 5);

• <xsl:attribute>. Здесь можно использовать атрибуты name и namespace (см. главу 6);

• <xsl:element>. Здесь можно использовать атрибуты name и namespace (см. главу 6);

• <xsl:number>. Здесь можно использовать атрибуты format, lang, letter-value, grouping-separator и grouping-size (см. главу 4);

• <xsl:processing-instruction>. Здесь можно использовать атрибут name (см. главу 6);

• <xsl:sort>. Здесь можно использовать атрибуты lang, data-type, order и case-order (см. главу 5).

В главе 6 эта тема рассмотрена более подробно: мы узнаем, как создавать атрибуты (и новые элементы) с нуля. Дополнительная информация об использовании выражений XPath в шаблонах значений атрибутов приведена в главе 7.

Обработка символов-разделителей

Поначалу символы-разделители (whitespace) доставляют авторам XSLT много хлопот. В главе 2 объяснялось, что «чистые» узлы-разделители — это текстовые узлы, содержащие только символы-разделители (пробелы, возвраты каретки, переводы строки и символы табуляции). Эти узлы по умолчанию копируются из исходного документа.

Заметьте, что в таблице стилей также могут быть узлы-разделители:

<xsl:template match="PLANETS">

 <xsl:copy>

  <xsl:apply-templates select="PLANET"/>

 </xsl:copy>

</xsl:template>

В нашем случае пробелы используются для выравнивания элементов таблицы стилей, а возвраты каретки — для разрежения кода. Чистые узлы-разделители, такие, как этот, не копируются из таблицы стилей в выходной документ. Заметьте, однако, что разделитель из следующего элемента <TITLE> копируется в выходной документ, так как это не чистый узел-разделитель (он также содержит текст «The Planets Table»):

<xsl:template match="/PLANETS">

 <HTML>

  <HEAD>

   <TITLE>

    The Planets Table

   </TITLE>

   .

   .

   .

Если вы хотите убрать этот разделитель и сохранить выравнивание, можно использовать пустые элементы <xsl:text>, так чтобы символы-разделители стали чистыми узлами-разделителями:

<xsl:template match="/PLANETS">

 <HTML>

  <HEAD>

   <TITLE>

    <xsl:text/>The Planets Table<xsl:text/>

   </TITLE>

   .

   .

   .

Чистые узлы-разделители не копируются из таблицы стилей в выходной документ, если только они не находятся внутри элемента <xsl:text>, или у элемента, в который они вложены, атрибут xml:space не установлен в «preserve» (сохранить).

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

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:output method="xml"/>

 <xsl:template match="*">

  <xsl:copy>

   <xsl:apply-templates/>

  </xsl:copy>

 </xsl:template>

</xsl:stylesheet>

и примените ее к planets.xml; все символы-разделители будут также скопированы в результирующий документ:

<?xml version="1.0"?>

<?xml-stylesheet type="text/xml" href="planets.xsl"?>

<PLANETS>

 <PLANET>

  <NAME>Mercury</NAME>

  <MASS UNITS="(Earth = 1)">.0553</MASS>

  <DAY UNITS="days">58.65</DAY>

  <RADIUS UNITS="miles">1516</RADIUS>

  <DENSITY UNITS="(Earth = 1)>.983</DENSITY>

  <DISTANCE UNITS="million miles">43.4</DISTANCE><!--B перигелии-->

 </PLANET>

 .

 .

 .

Тем не менее, иногда требуется удалить разделители, используемые при форматировании входных документов — это можно сделать при помощи элемента <xsl:strip-space>.

Элементы <xsl:strip-space> и <xsl:preserve-space>

Элемент <xsl:strip-space> дает указание процессору XSLT убрать все чистые узлы-разделители (также называемые «потребляемыми», expendable, узлами-разделителями) из. выходного документа. Чистый узел-разделитель состоит только из символов-разделителей и не содержит текст какого-либо другого вида. У этого элемента только один атрибут:

• elements (обязательный). Задает элементы, из которых нужно убрать символы-разделители. Представляет, собой список разделённых символами-разделителями NameTest (именами или обобщёнными именами с символами подстановок).

Элемент не включает содержимого. Например, чтобы удалить все узлы-разделители из planets.xml, можно применить <xsl:strip-space elements="*"/> следующим образом:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

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

 <xsl:strip-space elements="*"/>

 <xsl:output method="xml"/>

 <xsl:template match="*">

  <xsl:copy>

   <xsl:apply-templates/>

  </xsl:copy>

 </xsl:template>

</xsl:stylesheet>

Вот результирующий документ, полученный после применения этой таблицы стилей к planets.xml. Обратите внимание на то, что убраны все символы-разделители, в том числе все символы новой строки:

<?xml version="1.0" encoding="utf-8"?><PLANETS><PLANET><NAME>Mercury</NAME><MASS>.0553</MASS><DAY>58.65</DAY><RADIUS>1516</RADIUS><DENSITY>.983</DENSITY><DISTANCE>43.4</DISTANCE></PLANET><PLANET><NAME>Venus</NAME><MASS>.815</MASS><DAY>116.75</DAY><RADIUS>3716</RADIUS><DENSITY>.943</DENSITY><DISTANCE>66.8</DISTANCE></PLANET><PLANET><NAME>Earth</NAME><MASS>1</MASS><DAY>1</DAY><RADIUS>2107</RADIUS><DENSITY>1</DENSITY><DISTANCE>128.4</DISTANCE></PLANET></PLANETS>

Заметьте, что таким образом удаляются только чистые узлы-разделители. Например, текст элемента <TITLE>Volcanoes for Dinner</TITLE> не содержит чистых текстовых узлов-разделителей, поэтому текст «Volcanoes for Dinner» будет сохранен в выходном документе вместе с пробелами. Так будет даже тогда, когда текст будет содержать несколько пробелов подряд, как в «Volcanoes for Dinner».

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*