XSLT - Стивен Холзнер
Шрифт:
Интервал:
Закладка:
<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
Это правило приведено здесь только для гарантии того, что каждый элемент, от корня и ниже, будет обрабатываться при помощи <xsl:apply-templates/>, если не предоставить другого правила, которое перекроет правило по умолчанию.
Правило по умолчанию для текстовых узлов можно выразить следующим образом: функция XSLT text выбирает текст узла, так что текст текстового узла добавляется в выходной документ:
<xsl:template match="text()">
<xsl:value-of select="."/>
</xsl:template>
Правило по умолчанию того же вида применяется к атрибутам, которые добавляются в выходной документ при помощи следующего правила, где выражение "@*" выбирает любой атрибут:
<xsl:template match="@*">
<xsl:value-of select="."/>
</xsl:template>
По умолчанию инструкции обработки не вставляются в выходной документ, поэтому их правило по умолчанию можно выразить просто при помощи следующей функции-инструкции обработки XSLT, которая выбирает инструкции обработки (как мы увидим в главе 8):
<xsl:template match="processing-instruction()"/>
То же верно для комментариев — их правило по умолчанию может быть выражено при помощи функции XSLT comment, которая также будет рассмотрена в главе 8:
<xsl:template match="comment()"/>
Подведем итоги рассмотрения правил по умолчанию: если вообще не задать никаких правил, все разбираемые символьные данные входного документа будут вставлены в выходной документ. Вот как выглядит таблица стилей, в которой не задано никаких явных правил:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
</xsl:stylesheet>
А вот результат применения этой таблицы стилей к planets.xml. Заметьте, что правило по умолчанию для атрибутов не применялось, потому что они не являются дочерними по отношению к другим узлам:
<?xml version="1.0" encoding="UTF-8"?>
Mercury
.0553
58.65
1516
.983
43.4
Venus
.815
116.75
3716
.943
66.8
Earth
1
1
2107
1
128.4
ПРАВИЛА ПО УМОЛЧАНИЮ И INTERNET EXPLORER
Одна из проблем при работе с XSLT в Internet Explorer 5.5 или младше состоит в том, что браузер не предоставляет никаких правил по умолчанию. Необходимо задавать все правила самостоятельно, если только не установлен процессор MSXML3 в режиме замены (подробнее см. главу 2) или вы не обновили браузер до Internet Explorer 6.0.
Кроме того, узлы-разделители исходного документа сохраняются, поэтому можно считать, что следующее правило также является правилом по умолчанию: <xsl:output preserve-space="*"/>.
Удаление содержимого
Если ваше правило для узла не работает, то есть оно пусто, содержимое выбранного узла не будет скопировано в выходной документ. Таким способом при создании выходного документа можно выборочно удалять содержимое из исходного документа.
Предположим, нам нужно удалить из planets.xml все данные о планетах, за исключением их названий и данных о массе. Следующая таблица стилей выполняет данную задачу.
Листинг 3.7. Удаление содержимого<?xml versiоn="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="PLANETS">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="PLANET">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="NAME">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="MASS">
<xsl:copy>
<xsl:value-of select="."/>
<xsl:value-of select="@UNITS"/>
</xsl:copy>
</xsl:template>
<xsl:template match="RADIUS">
</xsl:template>
<xsl:template match="DAY">
</xsl:template>
<xsl:template match="DENSITY">
</xsl:template>
<xsl:template match="DISTANCE">
</xsl:template>
</xsl:stylesheet>
А вот результирующий документ (отметьте, что я сохранил только элементы <NAME> и <MASS>):
<?xml version="1.0" encoding="UTF-8"?>
<PLANET>
<NAME>Mercury</NAME>
<MASS>.0553(Earth = 1)</MASS>
</PLANET>
<PLANET>
<NAME>Venus</NAME>
<MASS>.815(Earth = 1)</MASS>
</PLANET>
<PLANET>
<NAME>Earth</NAME>
<MASS>1(Earth = 1)</MASS>
</PLANET>
Таким способом можно фильтровать XML-документы, создавая новые XML-документы только с требуемыми данными.
Разрешение конфликтов шаблонов
Еще одним важным аспектом работы с шаблонами является разрешение конфликтов. Если двум шаблонам удовлетворяют один и тот же узел или набор узлов, для определения применяемого шаблона XSLT учитывает их приоритет.
У каждого шаблона есть приоритет по умолчанию, основанный на значении атрибута select. Как правило, чем более сужающим является правило выбора или выражение (например, "PLANET" и "*"), тем выше его приоритет. В главе 4 мы рассмотрим, как процессор определяет приоритеты и как он работает с шаблонами, имеющими одинаковый приоритет.
Приоритет шаблона можно установить при помощи атрибута priority. В приведенном ниже листинге 3.8 правило, созданное элементом <xsl:template priority="1"/>, имеет меньший приоритет, чем правило, созданное элементом <xsl:template priority="2"/>.
Листинг 3.8. Установка приоритета шаблона<?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:apply-templates select="MASS"/></TD>
<TD><xsl:apply-templates select="RADIUS"/></TD>
<TD><xsl:apply-templates select="DAY"/></TD>
</TR>
</xsl:template>
<xsl:template match="MASS" priority="2">
<xsl:value-of select="."/>
(<I>Very</I> heavy)
</xsl:template>
<xsl:template match="MASS" priority="1">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="RADIUS">
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
<xsl:value-of select="@UNITS"/>
</xsl:template>
<xsl:template match="DAY">
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
<xsl:value-of select="@UNITS"/>
</xsl:template>
</xsl:stylesheet>
Процессор XSLT выбирает шаблон с наивысшим приоритетом, который добавляет текст "(<I>Very</I> heavy)" после каждого значения массы. В следующем примере использован шаблон с наивысшим приоритетом:
<HTML>
<HEAD>
<TITLE>
The Planets Table
</TITLE>
</HEAD>
<BODY>
<H1>
The Planets Table
</Н1>
<TABLE BORDER="2">
<TR>
<TD>Name</TD>
<TD>Mass</TD>
<TD>Radius</TD>
<TD>Day</TD>
</TR>
<TR>
<TD>Mercury</TD>
<TD>.0553(<I>Very</I> heavy)</TD>
<TD>1516 miles</TD>
<TD>58.65 days</TD>
</TR>
<TR>