Поясним, что это преобразование выполняет не просто копирование документа (для этого было бы достаточно элемента xsl:copy-of
). Идентичное преобразование переопределяет встроенные шаблоны; теперь, если для обработки какого-либо узла в преобразовании не определено подходящего шаблона, он вместе со всеми своими потомками будет скопирован в выходящий документ без изменений.
Идентичное преобразование очень полезно в тех случаях, когда требуется изменить только некоторые части документа, оставив остальное в неприкосновенности. Например, в предыдущем примере нам нужно было только переименовать все документы bold
. Искомое преобразование, импортирующее идентичное преобразование из файла identity.xsl
, будет записано следующим образом.
Листинг 5.12
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Результат будет иметь вид:
text a
text b
text c
Другим примером использования идентичного преобразования может послужить случай, когда нужно просто удалить из документа некоторые узлы. Например, нам необходимо избавиться от комментариев (быстро и без шума).
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Разрешение конфликтов в шаблонах
Как правило, каждое преобразование в XSLT определяет, включает или импортирует множество шаблонов, которые обрабатывают указанные части документов. При этом один и тот же узел документа может соответствовать нескольким шаблонным правилам. К примеру, элемент content
может быть обработан любым из следующих трех шаблонов.
Листинг 5.14. Конфликтующие шаблоны
Ситуация, когда для обработки узла может быть применено несколько правил, называется конфликтом шаблонов. Конфликты такого рода неизбежны практически в любом преобразовании, к примеру, большинство шаблонов будет вступать в конфликт со встроенными правилами преобразования.
Для того чтобы в конфликтной ситуации решить, какой именно из шаблонов должен быть применен к данному узлу, процессоры используют два простых правила.
□ Шаблоны, имеющие младший порядок импорта, исключаются из рассмотрения. Иными словами, из множества правил, подходящих для обработки текущего узла, остаются только правила, имеющие самый старший порядок импорта.
□ Из оставшегося множества выбирается шаблон с наивысшим приоритетом. Если таких шаблонов несколько, процессор может либо выдать ошибку, либо применить тот, который описан в преобразовании последним.
Во втором из этих двух правил, мы встретились с понятием приоритета шаблона. Приоритет шаблона это не что иное, как численное значение, которое может быть указано в атрибуте priority
элемента xsl:template
. В том случае, если значение этого атрибута не определено, приоритет шаблонного правила вычисляется следующим образом.
□ Прежде всего, шаблон, который обрабатывает несколько альтернатив, перечисленных через знак " |
", будет рассматриваться как множество шаблонов, обрабатывающих каждую из возможностей. Например, шаблон с атрибутом match="b|bold|B"
будет рассматриваться как три одинаковых шаблона с атрибутами match="b"
, match="bold"
и match="B"
соответственно.
□ Если паттерн состоит из имени ( QName
) или конструкции processing-instruction( литерал )
, которым предшествует дескриптор оси дочернего узла или атрибута ( ChildOrAttributeAxisSpecifier
), приоритет шаблона равен 0
. Такие паттерны могут иметь следующий вид:
• QName
или child:: QName
— выбор дочерних элементов;
• @ QName
или attribute:: QName
— выбор атрибутов;
• processing-instruction( литерал )
или child::processing-instruction( литерал )
— именной выбор дочерних инструкций по обработке.
Примеры паттернов с приоритетом, равным 0
:
• content
— выбор дочернего элемента content
;
• fo:content
— выбор дочернего элемента content
с префиксом пространств имен fo
;
• child::processing-instruction('арр')
— выбор дочерних инструкций по обработке, которые имеют вид ;
• @xsd:name
— выбор атрибута xsd:name
текущего узла;
• @select
— выбор атрибута select
текущего узла.
□ Если паттерн состоит из конструкции NCName:*
, которой предшествует ChildOrAxisSpecifier
, приоритет шаблона будет равен -0.25
. Такие паттерны могут иметь следующий вид:
• префикс :*
или child:: префикс :*
— выбор всех дочерних элементов в определенном пространстве имен;
Читать дальше