Стивен Холзнер - XSLT
Planet
</Р>
<P>
Planet
</Р>
</HTML>
Как видите, от элемента <PLANETS> ничего не осталось. Все, что осталось, — три элемента буквального результата <P>Planet</P>, которые заменили три элемента <PLANET>.
ПРОПУСК АТРИБУТА SELECT
Если опустить атрибут select, будут обрабатываться только дочерние узлы текущего узла, не включающие атрибуты или узлы пространств имен, так как они не считаются дочерними. Если вы хотите обрабатывать узлы этих видов, необходимо использовать атрибут select, как будет рассмотрено в главе 3.
Все это занимательно, но малопригодно практически. Было бы гораздо лучше, если бы мы, например, могли обратиться к фактическому значению каждого элемента (такому как имя каждой планеты) и работать с этими данными. И это, конечно, возможно.
Доступ к значениям узлов
Получить доступ к значению узла можно при помощи элемента <xsl:value-of>, у которого есть два возможных атрибута:
• select (обязательный). Выходное значение. Устанавливается в выражение;
• disable-output-escaping (необязательный). Указывает, что символы, такие как >, будут отправляться в выходной поток как есть, не изменяясь на >. Значения этого атрибута: yes или no.
Элемент <xsl:value-of> всегда пуст.
При помощи атрибута select можно указать, значение какого узла требуется получить. Например, вам может потребоваться значение узла <NAME> в каждом элементе <PLANET>, то есть текст, заключенный в этом узле. Это можно сделать следующим образом (листинг 2.4).
Листинг 2.4. Использование <xsl:value-of><?xml version="1.0">
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<HTML>
<xsl:apply-templates/>
</HTML>
</xsl:template>
<xsl:template match="PLANETS">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="PLANET">
<P>
<xsl:value-of select="NAME"/>
</P>
</xsl:template>
</xsl:stylesheet>
Значение узла, содержащего текст, будет просто текстом, поэтому результат применения этой таблицы стилей к planets.xml следующий:
<HTML>
<P>Mercury</P>
<P>Venus</P>
<P>Earth</P>
</НТМL>
АТРИБУТ DISABLE-OUTPUT-ESCAPING
Атрибут disable-output-escaping элемента <xsl:value-of> более подробно рассмотрен в главе 3.
Предположим, нам нужно осуществить нечто более сложное — например, преобразовать данные из planets.xml в HTML-таблицу в новом файле planets.html (рис. 2.1), как мы видели в главе 1. Теперь это можно сделать при помощи <xsl:value-of>.
Рис. 2.1. Planets.html в Internet Explorer
Здесь важно учесть один момент. В planets.xml формально не задан порядок элементов <MASS>, <RADIUS>, <DAY> и <DISTANCE>, однако важно, чтобы эти элементы обрабатывались в определенном порядке в соответствии с заголовками таблицы. Поэтому я буду использовать элементы <xsl:value-of> в том порядке, в котором они требуются в таблице HTML.
Таким образом, чтобы создать HTML-таблицу, изображенную на рис. 2.1, я сначала ищу элемент <PLANETS> и затем заменяю его на HTML для создания самой HTML-таблицы. Элемент <PLANETS> — дочерний элемент корневого узла, и поскольку на корневой узел можно сослаться через «/», на элемент <PLANETS> можно сослаться непосредственно через "/PLANETS", без необходимости предварительно применять шаблон для корневого узла. Это пример выражения XPath, большое число подобных мы также увидим в главе 4.
Ниже приведен пример того, как я начал создавать HTML-таблицу путем выбора элемента <PLANETS> непосредственно как "/PLANETS" — заметьте, что для применения шаблонов к любым дочерним узлам <PLANETS> я использовал <xsl:apply-templates>:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/PLANETS">
<HTML>
<HEAD>
<TITLE>
The Planets Table
</TITLE>
</HEAD>
<BODY>
<H1>
The Planets Table
</H1>
<TABLE BORDER="2">
<TR>
<TD>Name</TD>
<TD>Mass</TD>
<TD>Radius</TD>
<TD>Day</TD>
</TR>
<xsl:apply-templates/>
</TABLE>
</BODY>
</HTML>
</xsl:template>
.
.
.
Каждый дочерний узел <PLANET> имеет дочерние узлы <NAME>, <MASS>, <RADIUS> и <DAY>, и я хочу обрабатывать их именно в таком порядке — для того чтобы они добавлялись в HTML-таблицу в соответствии с заголовками таблицы. Для задания порядка их обработки я поместил элементы <xsl:value-of> (листинг 2.5).
Листинг 2.5. planets.xsl<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/PLANETS">
<HTML>
<HEAD>
<TITLE>
The Planets Table
</TITLE>
</HEAD>
<BODY>
<H1>
The Planets Table
</H1>
<TABLE BORDER="2">
<TR>
<TD>Name</TD>
<TD>Mass</TD>
<TD>Radius</TD>
<TD>Day</TD>
</TR>
<xsl:apply-templates/>
</TABLE>
</BODY>
</HTML>
</xsl:template>
<xsl:template match="PLANET">
<TR>
<TD><xsl:value-of select="NAME"/></TD>
<TD><xsl:value-of select="MASS"/></TD>
<TD><xsl:value-of select="RADIUS"/></TD>
<TD><xsl:value-of select="DAY"/></TD>
</TR>
</xsl:template>
</xsl:stylesheet>
Это все, что нам нужно; вот результат:
<HTML>
<HEAD>
<TITLE>
The Planets Table
</TITLE>
</HEAD>
<BODY>
<H1>
The Planets Table
</H1>
<TABLE BORDER="2">
<TR>
<TD>Name</TD>
<TD>Mass</TD>
<TD>Radius</TD>
<TD>Day</TD>
</TR>
<TR>
<TD>Mercury</TD>
<TD>.0553</TD>
<TD>1516</TD>
<TD>58.65</TD>
</TR>
<TR>
<TD>Venus</TD>
<TD>.815</TD>
<TD>3716</TD>
<TD>116.75</TD>
</TR>
<TR>
<TD>Earth</TD>
<TD>1</TD>
<TD>2107</TD>
<TD>1</TD>
</TR>
</TABLE>
</BODY>
</HTML>
Это практически то, что требовалось. Если взглянуть на рис. 2.2, видно, что в этом HTML-файле не выведены значения атрибута UNITS, который присутствует у каждого элемента (кроме атрибута <NAME>) в planets.xml:
Рис. 2.2. Planets.html без атрибутов в Internet Explorer
<?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><!--В перигелии-->
</PLANET>
.
.
.
В главе 3, в которой шаблоны рассмотрены более подробно, будет показано, как извлекать значения атрибутов из элементов XML.
Однако перед тем, как начать углубляться в работу с шаблонами, необходимо еще изучить достаточно много материала о таблицах стилей в общем. Например, в рабочий проект XSLT 1.1 включена поддержка рекомендации XML Base, а это значит, что она также появится и в XSLT 2.0.