Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

5 Правила шаблона

5.1 Схема обработки

Чтобы в конечном дереве построить фрагмент, обрабатывается перечень исходных узлов. Само конечное дерево строится путем обработки набора, состоящего из одного корневого узла. Перечень исходных узлов обрабатывается посредством помещения в конечное дерево структуры, созданной путем последовательной обработки каждого члена в этом перечне. Обработка узла осуществляется путем нахождения всех правил шаблона, чей образец соответствуют этому узлу, и выбора среди них самого лучшего. Затем обрабатывается шаблон из выбранного правила, причем в качестве текущего узла берется обрабатываемый узел, а как текущий набор узлов используется обрабатываемый перечень исходных узлов. Обычно шаблон содержит инструкции, которые набирают новый набор исходных узлов для дальнейшей обработки. Процесс сравнения, подстановки и нового набора продолжается рекурсивно до тех пор, пока для обработки можно найти новые исходные узлы.

Реализация XMLT может обрабатывать исходный документ любым способом, который дает тот же результат, как если бы выполнялась обработка в соответствии с представленной моделью.

5.2 Образцы

Правило шаблона идентифицирует узлы, к которым оно будет применяться, с помощью образца. Помимо правил шаблона, образцы используются также для нумерации (см. [7.7 Нумерация]) и декларирования ключей (см. [12.2 Ключи]). Образец задает перечень условий для обрабатываемого узла. Узел, который отвечает этим условиям, шаблону соответствует, а узел, который условиям не отвечает, шаблону не соответствует. Синтаксис шаблонов является подмножеством синтаксиса выражений. В частности, в качестве шаблонов могут использоваться пути адресации, которые отвечают определенным ограничениям. Выражение, которое является образцом, обрабатывается всегда как объект типа "набор узлов". Узел соответствует образцу, если он числится в наборе узлов, полученных в результате обработки этого образца как некого выражения в неком возможном контексте. Возможные контексты - это такие контексты, чей узлом контекста является проверяемый узел или один из его предков.

Некоторые примеры шаблонов:

  • para соответствует любому элементу para

  • * соответствует любому элементу

  • chapter|appendix соответствует любому элементу chapter и любому элементу appendix

  • olist/item соответствует любому элементу item с родителем olist

  • appendix//para соответствует любому элементу para, предком которого является элемент appendix

  • / соответствует корневому узлу

  • text() соответствует любому текстовому узлу

  • processing-instruction() соответствует любой инструкции обработки

  • node() соответствует любому узлу за исключением узла атрибута и корневого узла

  • id("W11") соответствует элементу с уникальным ID W11

  • para[1] соответствует любому элементу para, который для своего родителя будет первым непосредственным потомком являющимся элементом para

  • *[position()=1 and self::para] соответствует любому элементу para, являющемуся для своего родителя первым непосредственным элементом-потомком

  • para[last()=1] соответствует любому элементу para, который является для своего родителя единственным непосредственным потомком para

  • items/item[position()>1] соответствует любому элементу item, который имеет родителя items, но не является для этого родителя первым непосредственным потомком item

  • item[position() mod 2 = 1] будет иметь значение true для любого элемента item, который является нечетным непосредственным потомком item своего родителя.

  • div[@class="appendix"]//p соответствует любому элементу p, предком которого является элемент div, имеющий атрибут class со значением appendix

  • @class соответствует любому атрибуту class (но не любому элементу, имеющему атрибут class)

  • @* соответствует любому атрибуту

Образец должен отвечать грамматике Pattern. Pattern представляет собой набор образцов для путей адресации, разделенных символом |. Образец для пути адресации - это некий путь адресации, на всех шагах которого используются лишь оси child или attribute. Хотя образцы и не должны использовать ось descendant-or-self, в образцах могут использоваться как оператор //, так и оператор /. Образцы путей адресации могут начинаться также с вызова функций id или key с фиксированным аргументом. В предикатах образца могут использоваться произвольные выражения так это происходит в предикатах пути адресации.

Образцы
[1]    Pattern    ::=    LocationPathPattern
| Pattern '|' LocationPathPattern
[2]    LocationPathPattern    ::=    '/' RelativePathPattern?
| IdKeyPattern (('/' | '//') RelativePathPattern)?
| '//'? RelativePathPattern
[3]    IdKeyPattern    ::=    'id' '(' Literal ')'
| 'key' '(' Literal ',' Literal ')'
[4]    RelativePathPattern    ::=    StepPattern
| RelativePathPattern '/' StepPattern
| RelativePathPattern '//' StepPattern
[5]    StepPattern    ::=    ChildOrAttributeAxisSpecifier NodeTest Predicate*
[6]    ChildOrAttributeAxisSpecifier    ::=    AbbreviatedAxisSpecifier
| ('child' | 'attribute') '::'

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

Например, образец p соответствует любому элементу p, потому что если взять любой элемент p и обработать выражение p, используя в качестве контекста родителя элемента p, то одним из членов полученного набора узлов будет этот элемент p.

Замечание: Такой образец соответствует даже элементу p, являющемуся элементом этого документа, поскольку корень документа является родителем элемента документа.

Хотя семантика образцов формулируется косвенно в терминах обработки выражений, смысл образца легко понять сразу, не прибегая к терминологии обработки выражений. Символ | в образце обозначает альтернативу. Соответствие образцу с одним или несколькими символами |, разделяющими альтернативы, засчитывается если есть соответствие одной из этих альтернатив. Для образца, состоящего из последовательности StepPattern-ов, разделенных / или //, соответствие проверяется справа налево. Соответствие образцу засчитывается только если есть соответствие самому правому StepPattern, а соответствующий элемент отвечает остальной части образца. Если разделителем является /, то таким элементом может быть только родитель, если же разделителем является //, то в качестве такого элемента может использоваться любой из предков. Соответствие StepPattern, использующему ось child, засчитывается если для данного узла NodeTest дает true, а сам узел не является узлом атрибута. Соответствие StepPattern, использующему ось attribute, засчитывается если для данного узла NodeTest дает true, а сам узел является узлом атрибута. Если присутствует [], то в StepPattern сперва обрабатывается PredicateExpr, причем проверяемый узел используется как узел контекста, а в качестве контекстного набора узлов берутся узлы, которые имеют общего родителя с узлом контекста и соответствуют NodeTest. Однако если проверяемый узел является узлом атрибута, то в этом случае контекстный набор узлов - это все атрибуты, имеющие с проверяемым атрибутом общего родителя и соответствующие NameTest.

Например,

appendix//ulist/item[position()=1]

соответствует узлу тогда и только тогда, когда выполняются все следующие условия:

  • NodeTest item дает true для данного узла, а сам узел не является узлом атрибута, иными словами, данный узел является элементом item

  • обработка PredicateExpr position()=1 дает true, если данный узел берется как узел контекста, а набор элементов item, имеющих с ним общего родителя, берется как контекстный набор узлов

  • данный узел имеет родителя, отвечающего условию appendix//ulist, это будет так, если этот родитель является элементом ulist, предком которого является элемент appendix.

5.3 Определение правил шаблона

<!-- Category: top-level-element -->
<xsl:template
  match = pattern
  name = qname
  priority = number
  mode = qname>
  <!-- Content: (xsl:param*, template) -->
</xsl:template>

Правило шаблона задается элементом xsl:template. Атрибут match соответствует образу, который идентифицирует исходные узел или узлы, к которым это правило применяется. Если элемент xsl:template не имеет атрибута name, атрибут match обязателен (см. [6 Именованные шаблоны]). Если в значении атрибута match содержится VariableReference, фиксируется ошибка. Содержимое элемента xsl:template является шаблоном, который обрабатывается если данное правило шаблона задействовано.

Например, документ XML может содержать:

This is an <emph>important</emph> point.

Приведенное далее правило шаблона соответствует элементам emph и создает объект форматирования fo:inline-sequence, имеющий свойство font-weight со значением bold.

<xsl:template match="emph">
  <fo:inline-sequence font-weight="bold">
    <xsl:apply-templates/>
  </fo:inline-sequence>
</xsl:template>
Примечание: В примерах этого документа префикс fo: используется для пространства имен http://www.w3.org/1999/XSL/Format (пространства имен объектов форматирования, определенных в [XSL]).

Как описано далее, элемент xsl:apply-templates рекурсивно обрабатывает непосредственные потомки данного исходного элемента.

5.4 Использование правил шаблона

<!-- Category: instruction -->
<xsl:apply-templates
  select = node-set-expression
  mode = qname>
  <!-- Content: (xsl:sort | xsl:with-param)* -->
</xsl:apply-templates>

В данном примере для элемента chapter создается блок, а затем обрабатывается его непосредственный потомок.

<xsl:template match="chapter">
  <fo:block>
    <xsl:apply-templates/>
  </fo:block>
</xsl:template>

В отсутствие атрибута select инструкция xsl:apply-templates обрабатывает все непосредственные потомки текущего узла, включая узлы текста. Однако те текстовые узлы, которые были вычищены как описано в главе [3.4 Удаление пробельных символов], обрабатываться не будут. Если очистка узлов с пробельными символами для элемента не была разрешена, то все пробельные символы в содержимом этого элемента будут обрабатываться как текст, и, следовательно, пробельный символ между элементами - непосредственными потомками будет учитываться при вычислении положения элемента - непосредственного потомка, возвращаемого функцией position.

Чтобы обрабатывать не все непосредственные потомки, а лишь узлы, отобранные по некому выражению, может использоваться атрибут select. Значением атрибута select является выражение. После обработки этого выражения должен получиться набор узлов. Если нет указаний по сортировке (см. [10 Сортировка]), собранный перечень узлов обрабатывается в том порядке, как они следуют в документе. В следующем примере обрабатываются все непосредственные потомки author для этого элемента author-group:

<xsl:template match="author-group">
  <fo:inline-sequence>
    <xsl:apply-templates select="author"/>
  </fo:inline-sequence>
</xsl:template>

В следующем примере обрабатываются все содержащиеся в author элементы given-name, которые являются непосредственным потомком author-group:

<xsl:template match="author-group">
  <fo:inline-sequence>
    <xsl:apply-templates select="author/given-name"/>
  </fo:inline-sequence>
</xsl:template>

В данном примере обрабатываются все элементы heading, являющиеся потомками элемента book.

<xsl:template match="book">
  <fo:block>
    <xsl:apply-templates select=".//heading"/>
  </fo:block>
</xsl:template>

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

<xsl:template match="employee">
  <fo:block>
    Employee <xsl:apply-templates select="name"/> belongs to group
    <xsl:apply-templates select="ancestor::department/group"/>
  </fo:block>
</xsl:template>

Для выполнения простого переупорядочения в пределах одного шаблона можно использовать сразу несколько элементов xsl:apply-templates. В следующем примере создаются две таблицы HTML. Первая таблица заполняется отечественными продажами, вторая - международными.

<xsl:template match="product">
  <table>
    <xsl:apply-templates select="sales/domestic"/>
  </table>
  <table>
    <xsl:apply-templates select="sales/foreign"/>
  </table>
</xsl:template>
Замечание: Может оказаться, что шаблону соответствуют два потомка, причем один из них является потомком другого. Как-то особенно такой случай не обрабатывается: оба потомка будут обработаны обычным образом. Например, дан исходный документ
<doc><div><div></div></div></doc>
правило
<xsl:template match="doc">
  <xsl:apply-templates select=".//div"/>
</xsl:template>
будет обрабатывать и внешний, и внутренний элементы div.
Замечание: Обычно xsl:apply-templates используется для обработки только тех узлов, которые являются потомками текущего узла. Такое использование xsl:apply-templates не может привести к появлению бесконечных циклов обработки. Однако когда xsl:apply-templates используется для обработки элементов, не являющихся потомками текущего узла, появляется вероятность возникновения бесконечных циклов. Например,
<xsl:template match="foo">
  <xsl:apply-templates select="."/>
</xsl:template>
Реализации процессора в некоторых случаях могут выявить такие циклы, однако остается вероятность, что стиль попадет в такой бесконечный цикл, который эта реализация не сможет обнаружить. Для безопасности это может представлять угрозу типа "отказ в обслуживании".

5.5 Разрешение конфликтов в правилах шаблона

Может оказаться, что исходный узел соответствует сразу нескольким правилам шаблона. Правило шаблона, которое должно использоваться, определяется следующим образом:

  1. Во-первых, из рассмотрения исключаются все соответствующие узлу правила шаблона, которые имеют более низкий приоритет импорта, чем проверяемое правило шаблона и правила с наивысшим приоритетом импорта.

  2. Затем из рассмотрения исключаются все соответствующие узлу правила шаблона, которые имеют более низкий приоритет чем данное соответствующее правило шаблона и правила с наивысшим приоритетом. Приоритет правила шаблона задается атрибутом priority. Значением этого атрибута должно быть реальное число (положительное или отрицательное), соответствующее сценарию Number с необязательным начальным символом минус (-). Приоритет по умолчанию вычисляется следующим образом:

    • Если образец содержит несколько альтернатив, разделенных символом |, то он обрабатывается также как набор из правил шаблона, по одному на каждую из представленных альтернатив.

    • Если образец имеет вид QName, которому предшествует ChildOrAttributeAxisSpecifier, или имеет вид processing-instruction(Literal), которому предшествует ChildOrAttributeAxisSpecifier, то приоритет считается равным 0.

    • Если образец имеет вид NCName:*, которому предшествует ChildOrAttributeAxisSpecifier, то его приоритет равен -0.25.

    • В противном случае, если образец состоит только из NodeTest, которому предшествует ChildOrAttributeAxisSpecifier, то его приоритет равен -0.5.

    • В остальных случаях приоритет равен 0.5.

    Таким образом, самый общий тип образцов (образец, проверяющий узел определенного типа и с определенным расширенным именем) имеет приоритет 0. Следующий, более общий тип образца (образец, проверяющий узел определенного типа и с расширенным именем и определенным URI пространства имен) имеет приоритет -0.25. Еще более общие образцы (образцы, проверяющие лишь узлы определенных типов) имеют приоритет -0.5. Образцы, еще более специальные, чем самый общий тип образца, имеют приоритет 0.5.

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

5.6 Переопределение правил шаблона

<!-- Category: instruction -->
<xsl:apply-imports />

Правило шаблона, которое должно использоваться для переопределения другого правила шаблона в импортированном стиле (см. [5.5 Разрешение конфликтов в правилах шаблона]), может воспользоваться элементом xsl:apply-imports чтобы вызвать переопределенное правило шаблона.

При обработке стиля в каждой точке имеется некое текущее правило шаблона. Всякий раз, когда по образцу выбирается правило шаблона, для обработки оно становится текущим правилом шаблона. Когда обрабатывается элемент xsl:for-each, то при обработке содержимого этого элемента xsl:for-each текущее правило шаблона становится нулевым.

xsl:apply-imports обрабатывает текущий узел используя лишь те правила шаблона, которые были импортированы в тот элемент стиля, где это текущее правило шаблона находится. Узел обрабатывается в режиме текущего правила шаблона. Если xsl:apply-imports обрабатывается когда текущее правило шаблона нулевое, фиксируется ошибка.

Например, предположим что стиль doc.xsl содержит правило шаблона для элементов example:

<xsl:template match="example">
  <pre><xsl:apply-templates/></pre>
</xsl:template>

Другой стиль может импортировать doc.xsl и поменять обработку элементов example следующим образом:

<xsl:import href="doc.xsl"/>

<xsl:template match="example">
  <div style="border: solid red">
     <xsl:apply-imports/>
  </div>
</xsl:template>

В результате суммарного действия example должен преобразовываться в элемент следующего вида:

<div style="border: solid red"><pre>...</pre></div>

5.7 Режимы

Режимы позволяют обрабатывать элемент несколько раз, получая каждый раз другой результат.

Оба элемента xsl:template и xsl:apply-templates имеют необязательный атрибут mode. Значением атрибута mode является название QName, которое приводится к расширенному имени как было описано в главе [2.4 Полные имена]. Если xsl:template не имеет атрибута match, то он не должен иметь и атрибута mode. Если элемент xsl:apply-templates имеет атрибут mode, то он применяется только к тем правилам шаблона из элементов xsl:template, которые имеют атрибут mode с тем же значением. Если элемент xsl:apply-templates атрибута mode не имеет, то он применяется только к тем правилам шаблона из элементов xsl:template, которые также не имеют атрибута mode.

5.8 Встроенные правила шаблона

Имеется встроенное правило шаблона, позволяющее рекурсивно продолжать обработку в отсутствии успешного сравнения с явным правилом шаблона в стиле. Это правило шаблона используется как для узлов элементов, так и для корневого узла. Далее приведен эквивалент встроенного правила шаблона:

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>

Для каждого метода также есть встроенное правило шаблона, позволяющее рекурсивно продолжать обработку в том же самом режиме, в отсутствии успешного сравнения с образцом из явного правила шаблона в этом стиле. Это правило шаблона применяется как для узлов элементов, так и для корневого узла. Далее приведен эквивалент встроенного правила шаблона для режима m.

<xsl:template match="*|/" mode="m">
  <xsl:apply-templates mode="m"/>
</xsl:template>

Также есть встроенное правило шаблона для текстовых узлов и узлов атрибутов, которое просто копирует текст:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

Для инструкций обработки и комментариев встроенное правило шаблона не должно делать ничего.

<xsl:template match="processing-instruction()|comment()"/>

Встроенное правило шаблона для узлов пространства имен также не должно делать ничего. Нет образца, который бы мог соответствовать узлу пространства имен, поэтому встроенное правило шаблона является единственным правилом шаблона, которое применяется к узлам пространства имен.

Встроенные правила шаблона обрабатываются так, как будто они были неявно импортированы прежде стиля, а потому имеют меньший приоритет импорта, чем все остальные правила шаблона. Таким образом, автор может переопределить встроенное правило шаблона, явно включив новое правило шаблона.

Назад | Содержание | Вперед

 

Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

VPS в России, Европе и США

Бесплатная поддержка и администрирование

Оплата российскими и международными картами

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...