سؤال

وأنا أحاول لبناء dropdrown القائمة CSS متعددة المستويات لموقع أفعله على نظام إدارة محتوى umbraco.

وأحتاج لبنائه أن يكون البنية التالية:

<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>.

وأي شخص هناك للي نقطة في الاتجاه الصحيح؟

هل كانت مفيدة؟

المحلول

أولا، تمر حاجة المعلمة و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>

نصائح أخرى

وليس هناك شيء خاص جدا حول هذه المشكلة. الاختبارات الحل التالي أن القائمة عقدة

<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:variable name="vnextLevelNodes"
           select="node[@level = $vLevel+1]"/>
      <xsl:if test="$vnextLevelNodes">
       <ul>
         <xsl:apply-templates select="$vnextLevelNodes"/>
       </ul>
      </xsl:if>
    </xsl:template>

    <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"> -->
    <xsl:if test="1">
        <li>
          <!-- <a href="{umbraco.library:NiceUrl(@id)}"> -->
          <a href="'umbraco.library:NiceUrl(@id)'">
            <xsl:value-of select="@nodeName"/>
          </a>

                  <xsl:variable name="vnextLevelNodes"
                       select="node[@level = current()/@level+1]"/>
                  <xsl:if test="$vnextLevelNodes">
                   <ul>
                     <xsl:apply-templates select="$vnextLevelNodes"/>
                   </ul>
                  </xsl:if>
        </li>
    </xsl:if>
    </xsl:template>
</xsl:stylesheet>

ولقد استخدمت المستند المصدر XML التالية:

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

وأيضا، لقد علق بها أي رمز الرجوع تمديد مهام Umbraco، وأنا لم يكن لديك الوصول إليها.

عند تطبيق التحول أعلاه على هذه الوثيقة XML المصدر، يتم إنتاج النتيجة الصحيحة، أراد:

<ul>
    <li>
        <a href="'umbraco.library:NiceUrl(@id)'">Page #1</a>
    </li>
    <li>
        <a href="'umbraco.library:NiceUrl(@id)'">Page #2</a>
        <ul>
            <li>
                <a href="'umbraco.library:NiceUrl(@id)'">Subpage #2.2</a>
            </li>
            <li>
                <a href="'umbraco.library:NiceUrl(@id)'">Subpage #2.1</a>
                <ul>
                    <li>
                        <a href="'umbraco.library:NiceUrl(@id)'">Subpage #2.1.1</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="'umbraco.library:NiceUrl(@id)'">Subpage #2.3</a>
            </li>
        </ul>
    </li>
    <li>
        <a href="'umbraco.library:NiceUrl(@id)'">Page #3</a>
    </li>
</ul>

والأمل ساعد هذا.

وابتهاج،

وDimitre Novatchev

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top