Вопрос о применять-шаблоне XSLT

Я смущен оператором применять-шаблона XSLT. Например, здесь в w3school.

http://www.w3schools.com/xsl/xsl_apply_templates.asp

Для операторов,


  
  
  

My CD Collection

мои беспорядки,

(1) из чего функция ? Это не содержит определенного шаблона для вызова. Я думаю, что это соответствует, (возвратит) все непосредственно ребенок элемента тока (непрямой ребенок текущего узла не будет возвращен, текущий узел является корневым узлом), не уверенный, корректен ли я?

(2) после того, как все подобранные узлы возвращаются в (1), каков следующий процессор XSLT шага, сделает?

(3) в этом specifc образце корневой узел является каталогом или другим более высоким уровнем корня? и почему?

заранее спасибо, George

21
задан George2 29 December 2009 в 09:25
поделиться

4 ответа

Некоторые вещи, которые облегчат понимание ответов:

В первую очередь, узлы и элементы не одно и то же . Элементы - это узлы, но узлы не обязательно являются элементами. Вы часто находите людей, использующих термины взаимозаменяемыми. На самом деле в XML существует четыре вида узлов: элементы, текстовые узлы, инструкции по обработке и комментарии. (Атрибуты на самом деле не являются узлами, к которым я приду через секунду)

В XSLT корень XML-документа не является его верхним элементом; корень - это абстракция, которая на самом деле не существует. Элемент верхнего уровня является дочерним по отношению к корню. Например, вот хорошо сформированный XML документ, чей корень имеет пять дочерних узлов, включая элемент верхнего уровня:

<?xml-stylesheet href="mystyle.css" type="text/css"?>
<!-- this is a perfectly legitimate XML document -->
<top_level_element/>

Five? Похоже, что их всего три. Думаю, я позволю вам самим разобраться, что же такое остальные два. Подсказка: в этом примере может быть семь узлов.

Выражение XPath / находит корень документа, а не элемент верхнего уровня. В приведенном выше случае для поиска элемента верхнего уровня используется /top_level_element, или /*. (Для поиска элемента верхнего уровня всегда безопасно использовать /*, так как корень документа должен иметь дочерний элемент)

Так что, вооруженный этим знанием, давайте посмотрим, что делает applied-templates. В основном он выполняет двухступенчатый процесс: Во-первых, он строит набор узлов. Затем, и для каждого из них, он находит соответствующий шаблон (из числа шаблонов в XSLT-файле) и применяет к нему этот шаблон. Как Вы заметили в одном из комментариев, он концептуально очень похож на цикл.

На первом этапе используется атрибут select. Он предоставляет выражение XPath, которое используется для построения набора узлов, к которым будут применяться шаблоны. Если атрибут select не указан, то строится список всех дочерних элементов контекстного узла. (Узел контекста - это узел, к которому применяется текущий шаблон)

Атрибут match для элементов template используется на втором этапе. Процессор таблиц стилей находит все шаблоны, атрибут которых совпадает с узлом, к которому он пытается применить шаблоны. Если он находит более одного, он выбирает наиболее конкретный, например, учитывая эти шаблоны:

<xsl:template match="*"/>
<xsl:template match="foo"/>
<xsl:template match="foo[bar]"/>

элемент foo с дочерним элементом bar будет соответствовать третьему, элемент foo без элемента bar будет соответствовать второму, а элемент baz будет соответствовать первому. (Фактический метод, который использует XSLT, определен здесь ; на практике я использую XSLT уже почти десять лет, и мне ни разу не понадобилось конкретно знать, как он работает, хотя это интересно. )

Если он не найдет совпадение, то будет использовать встроенный шаблон по умолчанию для типа узла - в принципе, можно предположить, что любое преобразование XSLT неявно содержит эти шаблоны:

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

<xsl:template match="text()">
    <xsl:copy/>
</xsl:template>

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

Вооружившись всеми этими знаниями, Вы можете теперь понять, что преобразование идентичности:

<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>

соответствует любому узлу или атрибуту (обратите внимание, что атрибуты не являются узлами, поэтому @* необходимо), скопирует его, а затем применит шаблоны ко всем своим дочерним узлам и атрибутам. (Только корень документа и элементы будут иметь дочерние узлы, и только элементы будут иметь атрибуты). Поскольку это единственный шаблон в преобразовании, и он соответствует всем узлам и атрибутам, он применяется ко всем дочерним узлам и атрибутам. Таким образом, он копирует все, что находится в дереве исходных текстов, в дерево вывода.

Если добавить этот шаблон в идентификационное преобразование:

<xsl:template match="foo"/>

то теперь у Вас есть преобразование, которое копирует все узлы дерева исходных текстов кроме foo элементов - этот второй шаблон совпадает с элементами foo (первый тоже совпадает, но так как атрибут второго совпадает с более специфичен, то это тот, который выбирает XSLT) и ничего с ними не делает.

Учитывая всё это, ответы на Ваши специфические вопросы:

  1. применяет шаблоны к дочерним элементам контекстного узла.

  2. Совпадающие элементы не "возвращаются" на шаге 1; процессор XSLT находит шаблон для каждого из них и применяет его.

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

50
ответ дан 29 November 2019 в 06:49
поделиться
  1. попытается найти шаблон, соответствующий текущему узлу и его дочерним элементам.
  2. После того, как все соответствующие узлы будут возвращены, процессор XSL выведет эти закрывающие тэги (т.е. и )
  3. Непосредственно перед каталогом есть корневой узел, которому соответствует "/"

EDIT: Пример для пояснения 1. ; рассмотрите предоставленный вами образец :

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
      Here we're at "root" node, just before "catalog" element.<br />
      Let's enumerate this child nodes:
      <ul>
      <xsl:for-each select="*">
          <li><xsl:value-of select="name()" /></li>
      </xsl:for-each>
      </ul>
      <!-- Now, process "catalog" and ALL his child nodes -->
      <xsl:apply-templates/>  
    </xsl:template>

    <xsl:template match="cd">
      <p>
        <!-- Find a template ONLY for title element -->
        <xsl:apply-templates select="title"/> 
        <xsl:apply-templates select="artist"/>
      </p>
    </xsl:template>
</xsl:stylesheet>
3
ответ дан 29 November 2019 в 06:49
поделиться

xsl:apply-templates направляет движок XSLT на сопоставление подузлов текущего исходного документа с шаблонами таблиц стилей для дальнейшей обработки.

.
1
ответ дан 29 November 2019 в 06:49
поделиться

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

2) После того, как все узлы совпадут, выводятся следующие строки, которые в данном случае являются

</body> 
</html>

3) В каталоге примера - корневой узел.

.
1
ответ дан 29 November 2019 в 06:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: