2010-04-20 3 views
1

Я создал меню в umbraco, используя XSLT. В меню используются обычные элементы ul и li, и я показываю только первый уровень меню. Целью является создание меню, которое расширяется, чтобы отобразить подменю, когда я нажимаю на родительский узел (на верхнем уровне).Создание меню с использованием xslt для Umbraco

Я после xslt мне нужно будет выставить подменю при нажатии.

Я думаю, что мне нужно было бы использовать предка или себя, чтобы обнаружить текущее меню и родительское меню и отобразить их, а также переменную $ currentPage.

У меня есть следующие:

XSLT
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]> 
<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxml="urn:schemas-microsoft-com:xslt" 
    xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:tagsLib="urn:tagsLib" xmlns:urlLib="urn:urlLib" 
    exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets tagsLib urlLib "> 

<xsl:output method="xml" omit-xml-declaration="yes"/> 

<xsl:param name="currentPage"/> 

<xsl:template match="/"> 
    <div id="kb-categories"> 
     <h3>Categories</h3> 
     <xsl:call-template name="drawNodes"> 
      <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::node [@level=1]"/> 
     </xsl:call-template> 
    </div> 
</xsl:template> 

<xsl:template name="drawNodes"> 
    <xsl:param name="parent"/> 
    <xsl:if test="(umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1)) and $parent/@level = 1">   
     <ul class="kb-menuLevel1" >  
     <xsl:for-each select="$parent/node [string(./data [@alias='showInMenu']) = 1]"> 
      <li> 
       <a href="/kb{umbraco.library:NiceUrl(@id)}"> 
        <xsl:value-of select="@nodeName"/> 
       </a>     
       <xsl:variable name="level" select="@level" /> 
       <xsl:if test="(count(./node [string(./data [@alias='showInMenu']) = '1']) &gt; 0)"> 
        <xsl:call-template name="drawNodes">  
         <xsl:with-param name="parent" select="."/>  
        </xsl:call-template> 
       </xsl:if> 
      </li> 
     </xsl:for-each> 
     </ul> 
    </xsl:if> 
    <xsl:if test="(umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1)) and $parent/@level &gt; 1">  
     <ul class="kb-menuLevel{@level}" style="display: none;">    
     <xsl:for-each select="$parent/node [string(./data [@alias='showInMenu']) = 1]"> 
      <li> 
       <a href="/kb{umbraco.library:NiceUrl(@id)}"> 
        <xsl:value-of select="@nodeName"/> 
       </a>     
       <xsl:variable name="level" select="@level" /> 
       <xsl:if test="(count(./node [string(./data [@alias='showInMenu']) = '1']) &gt; 0)"> 
        <xsl:call-template name="drawNodes">  
         <xsl:with-param name="parent" select="."/>  
        </xsl:call-template> 
       </xsl:if> 
      </li> 
     </xsl:for-each> 
     </ul> 
    </xsl:if> 

</xsl:template> 

</xsl:stylesheet> 

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

Мое меню:

  • Пункт меню 1
  • Пункт меню 2
  • Пункт меню 3
  • Пункт меню 4

при нажатии на пункт меню 2 Я буду на страницу для пункта меню пункт 2 и подменю также будет отображаться:

  • Пункт меню 1
  • Пункт меню 2
    - Меню Пункт 2.1
    - Меню Пункт 2.2
  • Пункт меню 3
  • Пункт меню 4

и так далее вниз вложенная меню.

Вот несколько примеров xml для вышеуказанного.

<root> 
    <node id="1" nodeTypeAlias="kbHomepage" nodeName="Home" level="1"> 
     <data alias="introduction"> 
      <![CDATA[<p>Welcome</p>]]> 
     </data> 
     <node id="2" nodeTypeAlias="guide" nodeName="Menu Item 1" level="2"> 
      <data alias="bodyText"> 
       <![CDATA[<p>This is some text</p>]]> 
      </data> 
      <data alias="showInMenu">1</data> 
      <data alias="menuName">Menu Item 1</data> 
     </node>  
     <node id="3" nodeTypeAlias="guide" nodeName="Menu Item 2" level="2"> 
      <data alias="bodyText"> 
       <![CDATA[<p>This is some text</p>]]> 
      </data> 
      <data alias="showInMenu">1</data> 
      <data alias="menuName">Menu Item 2</data> 
      <node id="4" nodeTypeAlias="guide" nodeName="Menu Item 2.1" level="3"> 
       <data alias="bodyText"> 
        <![CDATA[<p>Some Text</p>]]> 
       </data> 
       <data alias="showInMenu">1</data> 
       <data alias="menuName">Menu Item 2.1</data> 
      </node> 
      <node id="5" nodeTypeAlias="guide" nodeName="Menu Item 2.2" level="3"> 
       <data alias="bodyText"> 
        <![CDATA[<p>Some Text</p>]]> 
       </data> 
       <data alias="showInMenu">1</data> 
       <data alias="menuName">Menu Item 2.2</data> 
       <node id="6" nodeTypeAlias="guide" nodeName="Item 2.2.1 Guide" level="4"> 
        <data alias="bodyText"> 
         <![CDATA[<p>Some Text</p>]]> 
        </data> 
        <data alias="showInMenu">0</data> 
        <data alias="menuName"></data> 
       </node> 
      </node> 
     </node>  
     <node id="8" nodeTypeAlias="guide" nodeName="Menu Item 3" level="2"> 
      <data alias="bodyText"> 
       <![CDATA[<p>This is some text</p>]]> 
      </data> 
      <data alias="showInMenu">1</data> 
      <data alias="menuName">Menu Item 3</data> 
     </node>  
     <node id="9" nodeTypeAlias="guide" nodeName="Menu Item 4" level="2"> 
      <data alias="bodyText"> 
       <![CDATA[<p>This is some text</p>]]> 
      </data> 
      <data alias="showInMenu">1</data> 
      <data alias="menuName">Menu Item 4</data> 
     </node>  
    </node> 
    <node id="7" nodeTypeAlias="someAlias" nodeName="Some Other Page" level="1"> 
     <data alias="bodyText"> 
      <![CDATA[<p>This is some text</p>]]> 
     </data>   
    </node>  
</root> 

редактировать: следующий почти делает то, что мне нужно:

<xsl:variable name="visibleChidren" select="node[data[@alias='showInMenu'] = 1 and (@level = 2 or descendant-or-self::*[generate-id($currentPage) = generate-id(.)] or preceding-sibling::*[generate-id($currentPage) = generate-id(.)] or following-sibling::*[generate-id($currentPage) = generate-id(.)])]" /> 

мне просто нужно также включать прямые детей от текущей страницы.

ответ

0

Я понял, что мне нужно делать, что я хочу. Ключевая линия бытия:

<xsl:variable name="visibleChidren" select="node[data[@alias='showInMenu'] = 1 and (@level = 2 or descendant-or-self::*[generate-id($currentPage) = generate-id(.)] or preceding-sibling::*[generate-id($currentPage) = generate-id(.)] or following-sibling::*[generate-id($currentPage) = generate-id(.)] or parent::*[generate-id($currentPage) = generate-id(.)])]" /> 

От всей XSLT:

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]> 
<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxml="urn:schemas-microsoft-com:xslt" 
    xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:tagsLib="urn:tagsLib" xmlns:urlLib="urn:urlLib" 
    exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets tagsLib urlLib "> 

    <xsl:output method="xml" omit-xml-declaration="yes"/> 

    <xsl:param name="currentPage"/> 
    <xsl:variable name="currentLevel" select="$currentPage/@level" /> 

    <xsl:template match="/"> 
    <div id="kb-categories"> 
     <h3>Categories</h3> 
     <xsl:apply-templates mode="list" select="$currentPage/ancestor-or-self::node [@nodeTypeAlias = 'kbHomepage']" /> 
    </div> 
    </xsl:template> 

    <!-- matches anything with <node> children and makes a list out of them --> 
    <xsl:template match="node" mode="list"> 
    <!-- select only sub-nodes that have 'showInMenu' = 1 --> 
    <xsl:variable name="visibleChidren" select="node[data[@alias='showInMenu'] = 1 and (@level = 2 or descendant-or-self::*[generate-id($currentPage) = generate-id(.)] or preceding-sibling::*[generate-id($currentPage) = generate-id(.)] or following-sibling::*[generate-id($currentPage) = generate-id(.)] or parent::*[generate-id($currentPage) = generate-id(.)])]" /> 
    <xsl:if test="$visibleChidren"> 
     <ul> 
     <xsl:apply-templates mode="item" select="$visibleChidren" /> 
     </ul> 
    </xsl:if> 
    </xsl:template> 

    <xsl:template match="node" mode="item"> 
     <li> 
     <a href="/kb{umbraco.library:NiceUrl(@id)}"> 
      <xsl:value-of select="@nodeName"/> 
     </a> 
     <xsl:apply-templates mode="list" select="." /> 
     </li> 
    </xsl:template> 

</xsl:stylesheet> 
2

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

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]> 
<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxml="urn:schemas-microsoft-com:xslt" 
    xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:tagsLib="urn:tagsLib" xmlns:urlLib="urn:urlLib" 
    exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets tagsLib urlLib "> 

    <xsl:output method="xml" omit-xml-declaration="yes" encoding="utf-8" /> 

    <xsl:param name="currentPage" /> 

    <xsl:template match="/"> 
    <div id="kb-categories"> 
     <h3>Categories</h3> 
     <xsl:apply-templates mode="list" select="/root/node[@nodeTypeAlias='kbHomepage']" /> 
    </div> 
    </xsl:template> 

    <!-- matches anything with <node> children and creates an <ul> --> 
    <xsl:template match="*[node]" mode="list"> 
    <!-- prepare a list of all visible children --> 
    <xsl:variable name="visibleChidren" select="node[ 
     data[@alias='showInMenu'] = 1 
     and (
     not(umbraco.library:IsProtected(@id, @path)) 
     or umbraco.library:IsLoggedOn() 
    ) 
    ]" /> 
    <!-- prepare a CSS class for the "selected path" --> 
    <xsl:variable name="display"> 
     <xsl:if test=".//node[generate-id() = generate-id($currentPage)]"> 
     <xsl:text>visible</xsl:text> 
     </xsl:if> 
    </xsl:variable> 
    <xsl:if test="$visibleChidren"> 
     <ul class="menu kb-menuLevel{$visibleChidren[1]/@level} {$display}"> 
     <xsl:apply-templates mode="item" select="$visibleChidren" /> 
     </ul> 
    </xsl:if> 
    </xsl:template> 

    <!-- matches <node> elements and turns them into list items --> 
    <xsl:template match="node" mode="item"> 
    <li> 
     <xsl:if test="generate-id() = generate-id($currentPage)"> 
     <xsl:attribute name="class">selected</xsl:attribute> 
     </xsl:if> 
     <a href="/kb{{umbraco.library:NiceUrl(@id)}}"> 
     <xsl:value-of select="@nodeName" /> 
     </a> 
     <!-- if there are any child nodes, render them --> 
     <xsl:if test="node"> 
     <xsl:apply-templates mode="list" select="." /> 
     </xsl:if> 
    </li> 
    </xsl:template> 

</xsl:stylesheet> 

Дает вам следующее.Обратите внимание, что я избежала шаблон значения атрибута в <a href... - удалить двойные Curlies выше, чтобы включить их снова:

<div id="kb-categories"> 
    <h3>Categories</h3> 
    <ul class="menu kb-menuLevel2 visible"> 
    <li> 
     <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 1</a> 
    </li> 
    <li> 
     <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 2</a> 
     <ul class="menu kb-menuLevel3 visible"> 
     <li class="selected"> 
      <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 2.1</a> 
     </li> 
     <li> 
      <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 2.2</a> 
     </li> 
     </ul> 
    </li> 
    <li> 
     <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 3</a> 
    </li> 
    <li> 
     <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 4</a> 
    </li> 
    </ul> 
</div> 

Теперь вы можете сделать в CSS:

ul.menu { 
    display: hidden; 
} 
ul.menu.visible { 
    display: block; 
} 
ul.menu li.selected { 
    font-weight: bold; 
} 

ли это вам помочь?

+0

@rob_g: Перед тем, как осуществить видимость узла, пожалуйста, проверьте, если мой код до сих пор производит правильный вывод HTML. – Tomalak

+0

Tomalak, я добавил xml. в меню должны отображаться только узлы уровня 2, если не щелкнуть элемент меню. Произнесите пункт меню 2, затем все узлы уровня 2 и все узлы уровня 3 в пункте меню 2 должны быть видимыми. нажатие на пункт меню Пункт 2 откроет страницу (как определено с помощью создаваемого элемента .Когда эта страница открыта, на нее ссылается $ currentPage. Я надеюсь, что текущей страницы достаточно, чтобы сделать то, что мне нужно: отобразить все прямые дети от $ currentPage и всех предков до и включительно уровня 2. Спасибо. –

+0

спасибо за помощь Tomalak –

0
+1

спасибо Тиму, но я все это сделал, прежде чем вы разместили этот комментарий. В противном случае я бы использовал его! –

+0

Ahhh well nevermind. Рад, что ты заработал! –