1

XSLTを使用してumbracoでメニューを作成しました。メニューは通常のul要素とli要素を使用しており、メニューの最初のレベルのみを表示しています。目的は、(トップレベルの)親ノードをクリックするとサブメニューを表示するように展開するメニューを作成することです。

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

これはapply-templatesを使用して改善できると思いますが、まだそれに慣れていません(これは、xsltの学習の2日目です)。

私のメニュー:

  • メニュー項目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(.)])]" />

現在のページの直接の子も含める必要があります。

4

3 に答える 3

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...- 上記の二重中括弧を削除して、再度有効にします。

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

それは役に立ちますか?

于 2010-04-20T09:51:14.257 に答える
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>
于 2010-04-21T02:21:46.950 に答える
0

または、XSLTでの多くのハッキングを解決し、our.umbraco.orgの次のナビゲーションパッケージを使用することもできます。

これは、XSLTの暗い世界で必要なことはすべて行い、手を汚す必要はないと思います。

http://our.umbraco.org/projects/cogworks---flexible-navigation

于 2010-04-21T11:25:03.457 に答える