2014-12-19 4 views
2

Я пытаюсь выполнить навигацию по страницам со следующим кодом. Хотя этот код окунулся в важные части, должно быть ясно, что моя идея. Идентификаторы могут быть любым заданным именем и могут отображаться в любом заданном номере в любом заданном порядке.Рекурсивный вызов шаблона XSL с параметром

ввода: Страницы, которые определяют свои предыдущие и последующие страницы в отсортированном коллекции:

<pages> 
    <page id="page1" next="page2" /> 
    <page id="page2" prev="page1" next="page3" /> 
    <page id="page3" prev="page2" /> 
    <page id="test2" prev="test1" /> 
    <page id="test1" next="test2" /> 
    <page id="alone" /> 
</pages> 

Желаемая выход (который я не в состоянии генерировать):

<page id="page1"> 
    <link href="page1" class="active" /> 
    <link href="page2" /> 
    <link href="page3" /> 
</page> 
<page id="page2"> 
    <link href="page1" /> 
    <link href="page2" class="active" /> 
    <link href="page3" /> 
</page> 
<page id="page3"> 
    <link href="page1" /> 
    <link href="page2" /> 
    <link href="page3" class="active" /> 
</page> 
<page id="test1"> 
    <link href="test1" class="active" /> 
    <link href="test2 /> 
</page> 
<page id="test2"> 
    <link href="test1" /> 
    <link href="test2" class="active" /> 
</page> 
<page id="alone"> 
</page> 

Что я имею до сих пор пробовал XSL:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:for-each select="pages/page"> 
    <page id="{@id}"> 

    <xsl:call-template name="prev-page"> 
     <xsl:with-param name="id"> 
     <xsl:value-of select="@prev" /> 
     </xsl:with-param> 
    </xsl:call-template> 

    <link href="{@id}" class="active" /> 

    <xsl:call-template name="next-page"> 
     <xsl:with-param name="id"> 
     <xsl:value-of select="@next" /> 
     </xsl:with-param> 
    </xsl:call-template> 

    </page> 
</xsl:for-each> 

<xsl:template name="prev-page"> 
    <xsl:param name="id" /> 

    <xsl:if test="string-length($id) > 0"> 
    <link href="{$id}" /> 
    <xsl:call-template name="prev-page"> 
     <xsl:with-param name="id"> 
     <!-- I believe in here lies the problem --> 
     <xsl:value-of select="(/pages/page[@id = $id])[0]/@prev" /> 
     </xsl:with-param> 
    </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
... (same for page-next) 
</xsl:stylesheet> 
+0

Правильно ли я понимаю, что атрибуты prev/next не играют никакой роли в выходе? Или вам нужны они, чтобы установить заказ? –

+0

Они устанавливают заказ. Порядок ввода страниц в случайном порядке. Я в основном хочу отсортировать их с помощью следующих и следующих атрибутов. –

+0

OMG. Какая версия XSLT? –

ответ

0

С вдохновением от michael.hor257k я придумал свое решение. Я просматриваю связанный список до тех пор, пока не дойду до страницы, где атрибут @prev указывает на несуществующую страницу. Затем я перемещаю список вперед и распечатываю элемент до тех пор, пока атрибут @next не укажет на несуществующую страницу.

<xsl:template match="/"> 
    <xsl:for-each select="page"> 
    <page id="{@id}"> 
     <xsl:if test="string-length(@next) > 0 or string-length(@prev) > 0"> 
     <xsl:call-template name="page-navigation-reverse"> 
      <xsl:with-param name="id"> 
      <xsl:value-of select="@prev" /> 
      </xsl:with-param> 
      <xsl:with-param name="current-id"> 
      <xsl:value-of select="@id" /> 
      </xsl:with-param> 
     </xsl:call-template> 
     </xsl:if> 
    </page> 
    </xsl:for-each> 
</xsl:template> 

<xsl:template name="page-navigation-reverse"> 
    <xsl:param name="id" /> 
    <xsl:param name="current-id" /> 

    <xsl:variable name="item-id"> 
    <xsl:choose> 
     <xsl:when test="string-length($id) &lt;= 0"> 
     <xsl:value-of select="$current-id" /> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="$id" /> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:variable> 

    <xsl:choose> 

    <xsl:when test="//page[@id = $item-id]/@prev"> 

     <xsl:call-template name="page-navigation-reverse"> 
     <xsl:with-param name="id"> 
      <xsl:value-of select="//page[@id = $item-id]/@prev" /> 
     </xsl:with-param> 
     <xsl:with-param name="current-id"> 
      <xsl:value-of select="$current-id" /> 
     </xsl:with-param> 
     </xsl:call-template> 
    </xsl:when> 

    <xsl:otherwise> 
     <xsl:call-template name="page-navigation-forward"> 
     <xsl:with-param name="id"> 
      <xsl:value-of select="$item-id" /> 
     </xsl:with-param> 
     <xsl:with-param name="current-id"> 
      <xsl:value-of select="$current-id" /> 
     </xsl:with-param> 
     </xsl:call-template> 
    </xsl:otherwise> 

    </xsl:choose> 
</xsl:template> 

<xsl:template name="page-navigation-forward"> 
    <xsl:param name="id" /> 
    <xsl:param name="current-id" /> 

    <link href="{$id}"> 
    <xsl:attribute name="class"> 
     <xsl:if test="$id = $current-id"> 
     <xsl:text> active</xsl:text> 
     </xsl:if> 
    </xsl:attribute> 
    </link> 

    <xsl:if test="//page[@id = $id]/@next"> 
    <xsl:call-template name="page-navigation-forward"> 
     <xsl:with-param name="id"> 
     <xsl:value-of select="//page[@id = $id]/@next" /> 
     </xsl:with-param> 
     <xsl:with-param name="current-id"> 
     <xsl:value-of select="$current-id" /> 
     </xsl:with-param> 
    </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
+0

Я думал, что вы хотите сами организовать страницы, а не только ссылки, в «правильном» порядке. Ваше решение этого не делает - предшествует . --- Другое дело, что вы неоднократно переставляете каждую «цепочку» столько раз, сколько ссылок в цепочке. Это очень неэффективно. –

+0

Извините, за путаницу. Да, я просто хотел отсортировать ссылки. В моем случае производительность не имеет большого значения. –

4

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

XSLT 1,0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" 
extension-element-prefixes="exsl"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

<!-- first-pass --> 
<xsl:key name="page" match="page" use="@id" /> 

<xsl:variable name="sorted-pages"> 
    <xsl:apply-templates select="pages/page[not(@prev)]" mode="first-pass"/> 
</xsl:variable> 

<xsl:template match="page" mode="first-pass"> 
    <xsl:copy-of select="."/> 
    <xsl:apply-templates select="key('page', @next)" mode="first-pass"/> 
</xsl:template> 

<xsl:variable name="sorted-pages-set" select="exsl:node-set($sorted-pages)/page" /> 

<!-- final-output --> 
<xsl:template match="/"> 
    <pages> 
     <xsl:for-each select="$sorted-pages-set"> 
     <xsl:variable name="current-id" select="@id" /> 
      <page id="{$current-id}"> 
       <xsl:apply-templates select="$sorted-pages-set"> 
        <xsl:with-param name="current-id" select="$current-id"/> 
       </xsl:apply-templates> 
      </page> 
     </xsl:for-each> 
    </pages> 
</xsl:template> 

<xsl:template match="page"> 
    <xsl:param name="current-id" /> 
    <link href="{@id}"> 
     <xsl:if test="@id=$current-id"> 
      <xsl:attribute name="class">active</xsl:attribute> 
     </xsl:if> 
    </link> 
</xsl:template> 

</xsl:stylesheet> 

Применительно к следующему Тестовый вход:

<pages> 
    <page id="alone" /> 
    <page id="fourth" prev="third" next="MISSING" /> 
    <page id="second" prev="first" next="third" /> 
    <page id="ii" prev="i" next="iii" />/> 
    <page id="first" next="second" /> 
    <page id="third" prev="second" next="fourth" /> 
    <page id="solo" /> 
    <page id="i" next="ii" /> 
    <page id="b" prev="a" /> 
    <page id="iii" prev="ii" /> 
    <page id="PROBLEM" prev="MISSING"/> 
    <page id="a" next="b" /> 
</pages> 

производит следующий результат:

<?xml version="1.0" encoding="UTF-8"?> 
<pages> 
    <page id="alone"> 
     <link href="alone" class="active"/> 
     <link href="first"/> 
     <link href="second"/> 
     <link href="third"/> 
     <link href="fourth"/> 
     <link href="solo"/> 
     <link href="i"/> 
     <link href="ii"/> 
     <link href="iii"/> 
     <link href="a"/> 
     <link href="b"/> 
    </page> 
    <page id="first"> 
     <link href="alone"/> 
     <link href="first" class="active"/> 
     <link href="second"/> 
     <link href="third"/> 
     <link href="fourth"/> 
     <link href="solo"/> 
     <link href="i"/> 
     <link href="ii"/> 
     <link href="iii"/> 
     <link href="a"/> 
     <link href="b"/> 
    </page> 
    <page id="second"> 
     <link href="alone"/> 
     <link href="first"/> 
     <link href="second" class="active"/> 
     <link href="third"/> 
     <link href="fourth"/> 
     <link href="solo"/> 
     <link href="i"/> 
     <link href="ii"/> 
     <link href="iii"/> 
     <link href="a"/> 
     <link href="b"/> 
    </page> 
    <page id="third"> 
     <link href="alone"/> 
     <link href="first"/> 
     <link href="second"/> 
     <link href="third" class="active"/> 
     <link href="fourth"/> 
     <link href="solo"/> 
     <link href="i"/> 
     <link href="ii"/> 
     <link href="iii"/> 
     <link href="a"/> 
     <link href="b"/> 
    </page> 
    <page id="fourth"> 
     <link href="alone"/> 
     <link href="first"/> 
     <link href="second"/> 
     <link href="third"/> 
     <link href="fourth" class="active"/> 
     <link href="solo"/> 
     <link href="i"/> 
     <link href="ii"/> 
     <link href="iii"/> 
     <link href="a"/> 
     <link href="b"/> 
    </page> 
    <page id="solo"> 
     <link href="alone"/> 
     <link href="first"/> 
     <link href="second"/> 
     <link href="third"/> 
     <link href="fourth"/> 
     <link href="solo" class="active"/> 
     <link href="i"/> 
     <link href="ii"/> 
     <link href="iii"/> 
     <link href="a"/> 
     <link href="b"/> 
    </page> 
    <page id="i"> 
     <link href="alone"/> 
     <link href="first"/> 
     <link href="second"/> 
     <link href="third"/> 
     <link href="fourth"/> 
     <link href="solo"/> 
     <link href="i" class="active"/> 
     <link href="ii"/> 
     <link href="iii"/> 
     <link href="a"/> 
     <link href="b"/> 
    </page> 
    <page id="ii"> 
     <link href="alone"/> 
     <link href="first"/> 
     <link href="second"/> 
     <link href="third"/> 
     <link href="fourth"/> 
     <link href="solo"/> 
     <link href="i"/> 
     <link href="ii" class="active"/> 
     <link href="iii"/> 
     <link href="a"/> 
     <link href="b"/> 
    </page> 
    <page id="iii"> 
     <link href="alone"/> 
     <link href="first"/> 
     <link href="second"/> 
     <link href="third"/> 
     <link href="fourth"/> 
     <link href="solo"/> 
     <link href="i"/> 
     <link href="ii"/> 
     <link href="iii" class="active"/> 
     <link href="a"/> 
     <link href="b"/> 
    </page> 
    <page id="a"> 
     <link href="alone"/> 
     <link href="first"/> 
     <link href="second"/> 
     <link href="third"/> 
     <link href="fourth"/> 
     <link href="solo"/> 
     <link href="i"/> 
     <link href="ii"/> 
     <link href="iii"/> 
     <link href="a" class="active"/> 
     <link href="b"/> 
    </page> 
    <page id="b"> 
     <link href="alone"/> 
     <link href="first"/> 
     <link href="second"/> 
     <link href="third"/> 
     <link href="fourth"/> 
     <link href="solo"/> 
     <link href="i"/> 
     <link href="ii"/> 
     <link href="iii"/> 
     <link href="a"/> 
     <link href="b" class="active"/> 
    </page> 
</pages> 
+0

Ничего, но я надеюсь, что не будет слишком много страниц, потому что я думаю, что после сортировки (в алфавитном порядке) у вас будут страницы 1, стр. 10, стр. 11, стр. 2, стр. 3, стр. 4, ... Посмотрите, что я имею в виду :) – potame

+1

@potame Что делает ты так думаешь? У меня нет ** какой-либо ** сортировки, ни алфавитной, ни цифровой. –

+0

Код Nice XSLT 1.0, даже он отлично работает для более чем двухзначных чисел, также, +1. –

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