2013-08-15 3 views
2

Я применяю шаблоны с переменной в атрибуте select, которая содержит часть дерева. Из этого я вызываю еще одно применение шаблонов со строкой next-sibling ::, но это относится ко всему дереву. Например:Почему XSLT меняет контекст неожиданно?

<a> 
    <b id="1" ol="1" /> 
    <b id="2" ol="0" /> 
    <b id="3" ol="0" /> 
    <b id="4" ol="1" /> 
    <b id="5" ol="0" /> 
    <b id="6" ol="0" /> 
    <b id="7" ol="1" /> 
    <b id="8" ol="0" /> 
    <b id="9" ol="0" /> 
    <b id="10" ol="1" /> 
    <b id="11" ol="0" /> 
    <b id="12" ol="0" /> 
    <b id="13" ol="1" /> 
    <b id="14" ol="0" /> 
    <b id="15" ol="0" /> 
    <b id="16" ol="1" /> 
</a> 

... 
<xsl:variable name="part" select="b[@ol = 1] /> 
<xsl:apply-templates mode="top" select="$part[position() mod 3 = 1]" /> 
... 
<xsl:template mode="top" match="*"> 
    <tr> 
     <xsl:apply-template mode="inner" select=".|following-sibling::b[not(position() > 2)]" /> 
    </tr> 
<xsl:template> 

<xsl:template mode="inner" match="*"> 
    <p><xsl:value-of select="@id" /></p> 
<xsl:template> 

Что я ожидаю

<tr><p>1</p><p>4</p><p>7</p></tr> 
<tr><p>10</p><p>13</p><p>16</p></tr> 

То, что я получил

<tr><p>1</p><p>2</p><p>3</p></tr> 
<tr><p>10</p><p>11</p><p>12</p></tr> 

Так почему же шаблон «сверху» контекст изменения, чтобы завершить дерево вместо $part при применении следующих -sibling? А как получить ожидаемый вариант?

+0

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

ответ

0

XPath выбирает узлы в дереве ввода, он никогда не меняет это дерево ввода. Таким образом, выбор некоторых узлов никоим образом не изменяет структуру и отношения в дереве, братья или дети или предки остаются неизменными. Если вы хотите управлять деревом, используйте XSLT или XQuery. Поскольку вы уже используете XSLT, с XSLT 1.0 вам нужно будет написать шаблоны для создания фрагмента результирующего дерева с новой структурой, а после применения функции расширения, например exsl:node-set, вы можете обработать промежуточное дерево. С XSLT 2.0 вам не нужна функция расширения, но вам нужно построить промежуточное дерево.

Для достижения выход вы хотите, вы можете использовать

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

<xsl:output indent="yes" method="html"/> 

<xsl:template match="a"> 
    <xsl:variable name="part" select="b[@ol = 1]" /> 
    <xsl:apply-templates mode="top" select="$part[position() mod 3 = 1]" /> 
</xsl:template> 

<xsl:template mode="top" match="*"> 
    <tr> 
     <xsl:apply-templates mode="inner" select=".|following-sibling::b[@ol = 1][not(position() > 2)]" /> 
    </tr> 
</xsl:template> 

<xsl:template mode="inner" match="*"> 
    <p><xsl:value-of select="@id" /></p> 
</xsl:template> 

</xsl:stylesheet> 

с этой таблицы стилей XSLT Saxon 6.5.5 трансформирует

<a> 
    <b id="1" ol="1" /> 
    <b id="2" ol="0" /> 
    <b id="3" ol="0" /> 
    <b id="4" ol="1" /> 
    <b id="5" ol="0" /> 
    <b id="6" ol="0" /> 
    <b id="7" ol="1" /> 
    <b id="8" ol="0" /> 
    <b id="9" ol="0" /> 
    <b id="10" ol="1" /> 
    <b id="11" ol="0" /> 
    <b id="12" ol="0" /> 
    <b id="13" ol="1" /> 
    <b id="14" ol="0" /> 
    <b id="15" ol="0" /> 
    <b id="16" ol="1" /> 
</a> 

в

<tr> 
    <p>1</p> 
    <p>4</p> 
    <p>7</p> 
</tr> 
<tr> 
    <p>10</p> 
    <p>13</p> 
    <p>16</p> 
</tr> 
+0

Любые предложения, как получить то, что я хочу? –

+0

@ThatsEnough, я отредактировал свой ответ, чтобы создать таблицу стилей XSLT, создающую нужные вам последовательности. –

0

$ части выбирает элементы с @ ol = 1, а именно, элементы 1,4,7,10,13,16.

$ part [position() mod 3 = 1] выбирает элементы в $ part, чья позиция в $ part равна 1, 4, 7, ... То есть выбирает элементы с идентификаторами 1 и 10.

Затем вы применяете к ним шаблоны, чтобы вывести группы из трех элементов, начиная с этих двух, что дает вам группы (1,2,3) и (10,11,12).

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

+0

Дайте мне, пожалуйста, как получить структуру, о которой я упоминал выше. –

+0

Я не очень хорошо понимаю проблему. Вы можете выбрать все элементы с помощью @ ol = 1 или выбрать каждый третий элемент; с вашими образцами данных дают одинаковый ответ, но, вероятно, это не всегда так. –

Смежные вопросы