Подтвердить что ты не робот

Вопрос XSLT о применении шаблона

Я запутался в инструкции XSLT apply-template. Например, здесь, в w3school.

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

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

<xsl:template match="/">
  <html>
  <body>
  <h2>My CD Collection</h2>
  <xsl:apply-templates/>
  </body>
  </html>
</xsl:template>

мои путаницы:

(1) какова функция <xsl:apply-templates/>? Он не содержит конкретного шаблона для вызова. Я думаю, что он будет соответствовать (возвращать) все непосредственно дочерние элементы текущего элемента (непрямой child текущего node не будет возвращен, текущий node является root node), не уверен, верен ли я?

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

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

спасибо заранее, Джордж

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

<xsl:template match="*"/>
<xsl:template match="foo"/>
<xsl:template match="foo[bar]"/>
Элемент

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

Если он не находит совпадения, он будет использовать встроенный шаблон по умолчанию для типа node - в принципе, вы можете предположить, что любое преобразование 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>

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

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

<xsl:template match="foo"/>

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

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

  • <xsl:apply-templates> применяет шаблоны к дочерним элементам контекста node.

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

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

Ответ 2

  • <xsl:apply-templates /> попытается найти шаблон, который соответствует текущему node и его дочерним элементам.
  • После возвращения всех согласованных узлов XSL-процессор выведет те закрывающие теги (т.е. </body> и </html>)
  • Существует корень node, непосредственно перед каталогом, соответствующий "/"

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 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

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

Ответ 4

1) <xsl:apply-templates/> вызывает траверсы через все подносы (дочерние элементы) и вызывает соответствующий шаблон, если таковой имеется.

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

</body> 
</html>

3) В каталоге примеров находится корень node.

Ответ 5

  • Элемент XML имеет дочерние или атрибуты. Для XML ниже в книге элементов есть child:: author (short author author) и attribute:: first (shortly @first)

    <?xml version="1.0" encoding="UTF-8"?> <book> <author first="tom">Smith</author> </book>

  • xsl: apply-templates означает выполнение шаблонов для всех дочерних совпадений node,, поэтому для шаблона ниже запустите шаблон для автора, но не для @first.

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

  • text() node Смит является дочерним элементом автора элемента, поэтому xsl: apply-templates вызывают шаблон для текста() node:

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