Идентичное преобразование
Идентичное преобразование
Наличие в XSLT шаблонов, выполняемых по умолчанию, иногда приводит к тому, что процессоры ведут себя не совсем логично с человеческой точки зрения. Например, в простейшем случае может понадобиться переименовать все элементы с именами bold в элементы с именами b. Однако результатом обработки документа
<а>
text a
<bold>
text b
<bold/>
</bold>
<c>
text c
</c>
</a>
преобразованием
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="bold">
<b><xsl:apply-templates/></b>
</xsl:template>
</xsl:stylesheet>
будет документ вида
text a
<b>
text b
<b/>
</b>
text c
Как можно заметить, в выходящем документе элементы а и с "пропали", но при этом их содержимое осталось нетронутым. Все дело во встроенных шаблонах, которые по умолчанию рекурсивно обрабатывают содержимое элементов и копируют текстовые узлы, если иного не определено.
Для того чтобы избежать подобного рода казусов, можно использовать идентичное преобразование, которое в случае отсутствия шаблонов для обработки тех или иных узлов копирует их в выходящий документ как есть. Идентичное преобразование записывается в следующем виде.
Листинг 5.11. Идентичное преобразование
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Единственный шаблон этого преобразования при помощи элемента xsl:copy рекурсивно создает в выходящем документе копии узлов и атрибутов. На практике идентичное преобразование используется очень часто, и потому мы настоятельно рекомендуем сохранить его в отдельном файле и импортировать при потребности.
Поясним, что это преобразование выполняет не просто копирование документа (для этого было бы достаточно элемента xsl:copy-of). Идентичное преобразование переопределяет встроенные шаблоны; теперь, если для обработки какого-либо узла в преобразовании не определено подходящего шаблона, он вместе со всеми своими потомками будет скопирован в выходящий документ без изменений.
Идентичное преобразование очень полезно в тех случаях, когда требуется изменить только некоторые части документа, оставив остальное в неприкосновенности. Например, в предыдущем примере нам нужно было только переименовать все документы bold. Искомое преобразование, импортирующее идентичное преобразование из файла identity.xsl, будет записано следующим образом.
Листинг 5.12
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="identity.xsl"/>
<xsl:template match="bold">
<b>
<xsl:apply-templates/>
</b>
</xsl:template>
</xsl:stylesheet>
Результат будет иметь вид:
<a>
text a
<b>
text b
<b/>
</b>
<c>
text c
</c>
</a>
Другим примером использования идентичного преобразования может послужить случай, когда нужно просто удалить из документа некоторые узлы. Например, нам необходимо избавиться от комментариев (быстро и без шума).
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="identity.xsl"/>
<xsl:template match="comment()"/>
</xsl:stylesheet>