Выбрать главу

   string-value="{.}">

   <xsclass="underline" apply-templates select="*"/>

  </element>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Листинг 3.27. Входящий документ

<data>

 <part>

  <item>A</item>

  <item>B</item>

  <item>C</item>

 </part>

 <part>

  <value>D</value>

  <value>E</value>

  <value>F</value>

 </part>

</data>

Листинг 3.28. Выходящий документ

<element name="data"

 context-position="1" context-size="1" string-value="ABCDEF">

 <element name="part"

  context-position="1" context-size="2" string-value="ABC">

 <element name="item"

  context-position="1" context-size="3" string-value="A"/>

 <element name="item"

  context-position="2" context-size="3" string-value="B"/>

 <element name="item"

  context-position="3" context-size="3" string-value="C"/> </element>

 <element name="part"

  context-position="2" context-size="2" string-value="DEF">

 <element name="value"

  context-position="1" context-size="3" string-value="D"/>

 <element name="value"

  context-position="2" context-size="3" string-value="E"/>

 <element name="value"

  context-position="3" context-size="3" string-value="F"/>

 </element>

</element>

Модель преобразования

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

Контекст преобразования

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

Контекст преобразования тесно связан с контекстом вычисления выражений:

□ текущий узел контекста преобразования соответствует контекстному узлу вычисления выражений;

□ позиция текущего узла в текущем обрабатываемом множестве соответствует позиции контекста вычисления выражений;

□ размер текущего множества узлов соответствует размеру контекста вычисления выражений.

Контекст преобразования может изменяться только двумя элементами — xsclass="underline" apply-templates и xsclass="underline" for-each. Каждый из этих элементов вычисляет множество узлов, которое становится текущим и затем обрабатывается. После этого контекст преобразования восстанавливается до того состояния, каким он был перед обработкой.

Изменения контекста могут быть продемонстрированы на следующем примере.

Листинг 3.29. Входящий документ

<summer>

 <month>June</month>

 <month>July</month>

 <month>August</month>

</summer>

Этому документу соответствует следующее дерево (рис. 3.19):

Рис. 3.19. Дерево входящего документа

Листинг 3.30. Преобразование

<xsclass="underline" stylesheet

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsclass="underline" template match="/">

  <html>

   <head>

    <title>Summer</title>

   </head>

   <body>

    <xsclass="underline" apply-templates select="summer"/>

   </body>

  </html>

 </xsclass="underline" template>

 <xsclass="underline" template match="summer">

  <table>

   <tr>

    <xsclass="underline" apply-templates select="month"/>

   </tr>

  </table>

 </xsclass="underline" template>

 <xsclass="underline" template match="month">

  <td>

   <xsclass="underline" value-of select="."/>

  </td>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Забегая вперед скажем, что в изначальном контексте преобразования текущее множество состоит из единственного узла — корневого узла документа. Он становится текущим и обрабатывается соответствующим шаблоном.

В нашем случае шаблонное правило, обрабатывающее корневой узел, выглядит как:

<xsclass="underline" template match="/">

 <html>

  <head>

   <title>Summer</title>

  </head>

  <body>

   <xsclass="underline" apply-templates select="summer"/>

  </body>

 </html>

</xsclass="underline" template>

Тело этого шаблона выполняется в том самом изначальном контексте, о котором мы только что упомянули: текущее множество состоит из корневого узла, он же является и текущим узлом. Мы можем показать контекст, выделяя текущее множество, пунктиром, а текущий узел — полужирной линией (рис. 3.20).

Рис. 3.20. Первоначальный контекст преобразования

Атрибут select элемента xsclass="underline" apply-templates задает выражение, вычисляющее множество узлов, которые должны быть обработаны. Выражение summer, которое содержит этот атрибут, является относительным путем выборки, который возвращает все дочерние элементы summer текущего узла. Поскольку текущим узлом в данном контексте является корневой узел дерева, значением выражения summer будет множество узлов, состоящее из субэлемента summer, корневого узла.

При выполнении элемента xsclass="underline" apply-templates процессор сделает это вычисленное множество узлов текущим множеством и начнет поочередно обрабатывать его узлы, делая их при этом текущими. Иначе говоря, выполнение элемента

<xsclass="underline" apply-templates select="summer"/>

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

<xsclass="underline" template match="summer">