4

umbraco コンテンツ管理システムで行っている Web サイト用のマルチレベルのドロップダウン CSS メニューを構築しようとしています。

次の構造を持つようにビルドする必要があります。

<ul id="nav">
  <li><a href="..">Page #1</a></li>
  <li>
    <a href="..">Page #2</a>
    <ul>
      <li><a href="..">Subpage #1</a></li>
      <li><a href="..">Subpage #2</a></li>        
    </ul>
  </li>
</ul>

そこで、XSLT を使用してネストを行う方法を見つけようとしています。これは私がこれまでに持っているものです:

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

<xsl:param name="currentPage"/>

<!-- update this variable on how deep your menu should be -->
<xsl:variable name="maxLevelForMenu" select="4"/>

<xsl:template match="/">
  <ul id="nav">
    <xsl:call-template name="drawNodes">  
      <xsl:with-param 
       name="parent" 
       select="$currentPage/ancestor-or-self::node [@level=1]"
      />  
    </xsl:call-template>
  </ul>
</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 umbraco.library:IsLoggedOn() = 1)">
    <xsl:for-each select="$parent/node [string(./data [@alias='umbracoNaviHide']) != '1' and @level &lt;= $maxLevelForMenu]"> 
      <li>
        <a href="{umbraco.library:NiceUrl(@id)}">
          <xsl:value-of select="@nodeName"/>
        </a>  
        <xsl:if test="count(./node [string(./data [@alias='umbracoNaviHide']) != '1' and @level &lt;= $maxLevelForMenu]) &gt; 0">   
          <xsl:call-template name="drawNodes">    
            <xsl:with-param name="parent" select="."/>    
          </xsl:call-template>  
        </xsl:if> 
      </li>
    </xsl:for-each>
  </xsl:if>
</xsl:template>

私が理解できないように見えるのは、最初のレベル (ここではページ #1 とページ #2​​) に子があるかどうか、および子<ul>を含めるためにエクストラを追加するかどうかを確認する方法<li>です。

私を正しい方向に向けてくれる人はいますか?

4

2 に答える 2

5

まず、parentパラメータを渡す必要はありません。コンテキストはこの情報を転送します。

問題を解決する XSL スタイルシートは次のとおりです。

<!-- update this variable on how deep your menu should be -->
<xsl:variable name="maxLevelForMenu" select="4"/>

<!--- match the document root --->
<xsl:template match="/root">
  <div id="nav">
    <xsl:call-template name="SubTree" />
  </div>
</xsl:template>

<!-- this will be called by xsl:apply-templates -->
<xsl:template match="node">
  <!-- the node is either protected, or the user is logged on (no need to check for IsProtected twice) -->
  <xsl:if test="umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or umbraco.library:IsLoggedOn() = 1">
    <li>
      <a href="{umbraco.library:NiceUrl(@id)}"><xsl:value-of select="@nodeName"/></a>
      <xsl:call-template name="SubTree" />
    </li>
  </xsl:if>
</xsl:template>

<xsl:template name="SubTree">
  <!-- render sub-tree only if there are any child nodes --->
  <xsl:if test="node">
    <ul>
      <xsl:apply-templates select="node[data[@alias='umbracoNaviHide'] != '1'][@level &lt;= $maxLevelForMenu]">
        <!-- ensure sorted output of the child nodes --->
        <xsl:sort select="@sortOrder" data-type="number" />
      </xsl:apply-templates>
    </ul>
  </xsl:if>
</xsl:template>

これは私がテストした XML です (私は Umbraco についてあまり知りませんが、いくつかのサンプルを見た後、Umbraco ドキュメントに近づいたことを願っています)。

<root id="-1">
  <node id="1" level="1" sortOrder="1" nodeName="Page #1">
    <data alias="umbracoNaviHide">0</data>
  </node>
  <node id="2" level="1" sortOrder="2" nodeName="Page #2">
    <data alias="umbracoNaviHide">0</data>
    <node id="3" level="2" sortOrder="2" nodeName="Subpage #2.2">
      <data alias="umbracoNaviHide">0</data>
    </node>
    <node id="4" level="2" sortOrder="1" nodeName="Subpage #2.1">
      <data alias="umbracoNaviHide">0</data>
      <node id="5" level="3" sortOrder="3" nodeName="Subpage #2.1.1">
        <data alias="umbracoNaviHide">0</data>
      </node>
    </node>
    <node id="6" level="2" sortOrder="3" nodeName="Subpage #2.3">
      <data alias="umbracoNaviHide">1</data>
    </node>
  </node>
  <node id="7" level="1" sortOrder="3" nodeName="Page #3">
    <data alias="umbracoNaviHide">1</data>
  </node>
</root>

これは出力です:

<div id="nav">
  <ul>
    <li><a href="http://foo/">Page #1</a></li>
    <li><a href="http://foo/">Page #2</a>
      <ul>
        <li><a href="http://foo/">Subpage #2.1</a>
          <ul>
            <li><a href="http://foo/">Subpage #2.1.1</a></li>
          </ul>
        </li>
        <li><a href="http://foo/">Subpage #2.2</a></li>
      </ul>
    </li>
  </ul>
</div>
于 2008-11-21T12:50:17.410 に答える
0

この問題については、特別なことは何もありません。次のソリューションは、node-list の

<xsl:apply-templates/>

テンプレートを適用する前に、空ではありません:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes"/>
  <xsl:variable name="vLevel" select="0"/>

    <xsl:template match="root">
      <xsl:変数名="vnextLevelNodes"
           select="node[@level = $vLevel+1]"/>
      <xsl:if test="$vnextLevelNodes">
       <ul>
         <xsl:apply-templates select="$vnextLevelNodes"/>
       </ul>
      </xsl:if>
    </xsl:テンプレート>

    <xsl:template match="ノード">
  <!-- ノードが保護されているか、ユーザーがログオンしています (IsProtected を 2 回確認する必要はありません) -->
    <!-- <xsl:if テスト=
      "umbraco.library:IsProtected($parent/@id, $parent/@path) = 0
      また
       umbraco.library:IsLoggedOn() = 1"> -->
    <xsl:if test="1">
        <リ>
          <!-- <a href="{umbraco.library:NiceUrl(@id)}"> -->
          <a href="'umbraco.library:NiceUrl(@id)'">
            <xsl:value-of select="@nodeName"/>
          </a>

                  <xsl:変数名="vnextLevelNodes"
                       select="ノード[@level = current()/@level+1]"/>
                  <xsl:if test="$vnextLevelNodes">
                   <ul>
                     <xsl:apply-templates select="$vnextLevelNodes"/>
                   </ul>
                  </xsl:if>
        </li>
    </xsl:if>
    </xsl:テンプレート>
</xsl:スタイルシート>

次の XML ソース ドキュメントを使用しました。

<ルート ID="-1">
    <node id="1" level="1" sortOrder="1" nodeName="ページ #1">
        <data alias="umbracoNaviHide">0</data>
    </ノード>
    <node id="2" level="1" sortOrder="2" nodeName="ページ #2​​">
        <data alias="umbracoNaviHide">0</data>
        <node id="3" level="2" sortOrder="2" nodeName="サブページ #2​​.2">
            <data alias="umbracoNaviHide">0</data>
        </ノード>
        <node id="4" level="2" sortOrder="1" nodeName="サブページ #2​​.1">
            <data alias="umbracoNaviHide">0</data>
            <node id="5" level="3" sortOrder="3" nodeName="サブページ #2​​.1.1">
                <data alias="umbracoNaviHide">0</data>
            </ノード>
        </ノード>
        <node id="6" level="2" sortOrder="3" nodeName="サブページ #2​​.3">
            <data alias="umbracoNaviHide">1</data>
        </ノード>
    </ノード>
    <node id="7" level="1" sortOrder="3" nodeName="Page #3">
        <data alias="umbracoNaviHide">1</data>
    </ノード>
</ルート>

また、Umbraco 拡張機能にアクセスできないため、それらを参照するコードをコメントアウトしました。

上記の変換をこのソース XML ドキュメントに適用すると、必要な正しい結果が生成されます。

<ul>
    <リ>
        <a href="'umbraco.library:NiceUrl(@id)'">ページ #1</a>
    </li>
    <リ>
        <a href="'umbraco.library:NiceUrl(@id)'">ページ #2​​</a>
        <ul>
            <リ>
                <a href="'umbraco.library:NiceUrl(@id)'">サブページ #2​​.2</a>
            </li>
            <リ>
                <a href="'umbraco.library:NiceUrl(@id)'">サブページ #2​​.1</a>
                <ul>
                    <リ>
                        <a href="'umbraco.library:NiceUrl(@id)'">サブページ #2​​.1.1</a>
                    </li>
                </ul>
            </li>
            <リ>
                <a href="'umbraco.library:NiceUrl(@id)'">サブページ #2​​.3</a>
            </li>
        </ul>
    </li>
    <リ>
        <a href="'umbraco.library:NiceUrl(@id)'">ページ #3</a>
    </li>
</ul>

これが役に立ったことを願っています。

乾杯、

ディミトレ・ノヴァチェフ

于 2008-11-21T15:07:20.067 に答える