Разное

Многоуровневое меню: Многоуровневое меню | PROG-TIME

28.05.1983

Содержание

CSS многоуровневое меню — Русские Блоги

Это довольно великолепная функция, которая делает веб-страницы похожими на настольные программы, такие как меню «Пуск» окна. Принцип реализации в основном такой же, как у чистого альбома CSS, но есть много вещей, на которые следует обратить внимание, давайте шаг за шагом.

Давайте начнем с очень простого меню первого уровня и эффекта наведения.

<ul>
  <li>
    <a href="http://www.cnblogs.com/rubylouvre/">
             Меню 1 <! - Маленькое изображение-> <span> <! - Большое изображение-> </ span>
    </a>
  </li>
  <li>
    <a href="http://www.cnblogs.com/rubylouvre/">
             Меню 2 <! - Уменьшить изображение-> <span> <! - Увеличить изображение-> </ span>
    </a>
  </li>
  <li>
    <a href="http://www.cnblogs.com/rubylouvre/">
             Меню три <! - Маленькая картинка-> <span> <! - Большая картинка-> </ span>
    </a>
  </li>
  <li>
    <a href="http://www.
cnblogs.com/rubylouvre/"> Меню 4 <! - Маленькое изображение-> <span> <! - Большое изображение-> </ span> </a> </li> </ul>

Структура знакома, просто замените место, где картинка была изначально размещена с текстом. Я специально это отметил. Код для уровня представления, который следует очень прост.

* {
  margin:0;
  padding:0;
}
.menu {
  font-size:12px;
}
 .menu li {/ * горизонтальное меню * /
  float:left;
  list-style:none;
}
.menu a {
  display:block;
  position:relative;
  height:32px;
  width:100px;
  line-height:32px;
  background:#a9ea00;
  color:#ff8040;
  text-decoration:none;
  text-align:center;
}
.menu a:hover {
  background:#369;
  color:#fff;
}
.menu li span {
  display:none;
  position:absolute;
  left:0;
  top:32px;
  width:200px;
  height:150px;
  background:#B9D6FF;
}
.menu a:hover span {
  display:block;
}

Здесь стоит отметить две вещи. Давайте сначала поговорим о первом. Верх подменю (элемент span) должен иметь возможность удерживать его верх в пределах диапазона элемента a, если содержащийся блок является элементом li, то же самое верно. Когда верхнее значение диапазона больше 32 пикселей, например 40 пикселей, мы не можем навести указатель мыши на элемент диапазона. Поскольку он покидает область действия: hover, элемент span снова скрыт.

.menu li span {
  display:none;
  position:absolute;
  left:0;
     top: 40px; / * ★★ Изменить здесь ★★ * /
  width:200px;
  height:150px;
  background:#B9D6FF;
}

Вторая проблема уникальна для IE6, то есть подменю не исчезает после наведения мыши соответствующего блока. Псевдокласс hover — это эквивалент перемещения и перемещения. Мы можем определить один стиль для его детей и внуков при наведении мыши, а другой — при наведении мышки. Другими словами, дисплей теперь не может переключаться в IE6 (кроме элемента img). Решение Используйте видимость вместо отображения.

Хорошо, теперь мы действительно создаем меню второго уровня, удаляем весь CSS, связанный с пролетом, и меняем позицию исходного промежутка в структурном слое на следующий код:

<ul>
  <li> <a href="http://www. cnblogs.com/rubylouvre/"> menu_11 второго уровня </a> </ li>
     <li> <a href="http://www.cnblogs.com/rubylouvre/"> menu_12 второго уровня </a> </ li>
</ul>

Давайте посмотрим на каждый браузер, и он кажется очень слабым. Вторичные пункты меню IE6 и Opera10 расположены вертикально, но мы не очистили поплавок? Пункты меню второго уровня firefox3.5, chrome и safari4 распределены по горизонтали, но, кажется, есть еще один пункт меню выше … Одноклассники IE8 показали лучший результат на этот раз. Я не установил IE7, поэтому всегда игнорировал его.

Мы сбрасываем стиль, такой как изменение содержащего блока на элемент li, чтобы элементы меню второго уровня отображались вертикально.

* {
  margin:0;
  padding:0;
}
.menu {
  font-size:12px;
}
 .menu li {/ * горизонтальное меню * /
  float:left;
  list-style:none;
     позиция: относительная; / * Переместить содержащий элемент блока li * /
}
.menu a {
  display:block;
     / * позиция: относительная; найдена в элементе a,
     Это ужасно в стандартном браузере,
     Это то же самое, что и ошибка, возникшая в первом рабочем окне чистого альбома CSS 3 в chrome * /
  height:32px;
  width:100px;
  line-height:32px;
  background:#a9ea00;
  color:#ff8040;
  text-decoration:none;
  text-align:center;
}
.
menu a:hover { background:#369; color:#fff; } / * Новая дополнительная часть меню * / .menu ul ul { видимость: скрыто; / * скрыто в начале * / position:absolute; left:0px; top:32px; } .menu ul a:hover ul{ visibility:visible; } .menu ul ul li { ясно: оба; / * Вертикальный дисплей * / text-align:left; }

Я обнаружил, что вторичное меню не отвечает в Firefox, Safari и Chrome. Opera10 показала лучшие результаты, затем IE8. Однако все элементы стандартного браузера поддерживают псевдокласс hover. В отличие от IE6, элемент a с href не допускается. Мы переписали часть кода CSS:

.menu ul li: hover ul, / * не-IE6 * /
.menu ul a:hover ul{/*IE6*/
  visibility:visible;
}

Может появиться дополнительное меню, но также появляется загадочный элемент li. Я не могу устранить этот таинственный элемент li с помощью двойной термоусадочной упаковки. Обратитесь к сторонним кодам, разместив все подменю вне элемента a, а затем используя li: hover для управления переключением стилей. Таким образом, структурный слой переписывается следующим образом:

<div>
  <ul>
    <li>
             <a href="http://www.cnblogs.com/rubylouvre/"> Меню 1 </a>
      <ul>
                 <li> <a href="http://www.cnblogs.com/rubylouvre/"> menu_11 второго уровня </a> </ li>
                 <li> <a href="http://www.cnblogs.com/rubylouvre/"> menu_12 второго уровня </a> </ li>
      </ul>
    </li>
    <li>
             <a href="http://www.cnblogs.com/rubylouvre/"> Меню II </a>
      <ul>
                 <li> <a href="http://www.cnblogs.com/rubylouvre/"> дополнительное меню_21 </a> </ li>
                 <li> <a href="http://www.cnblogs.com/rubylouvre/"> menu_22 второго уровня </a> </ li>
      </ul>
    </li>
    <li>
         // *************** Слегка ************
    </li>
    <li>
         // *************** Слегка ************
    </li>
  </ul>
</div>

Здесь я рекомендую свою группу по обучению внешним интерфейсам: 784783012, которые все изучают интерфейс. Если вы хотите создавать классные веб-страницы, вы хотите изучать программирование. Я собрал 2018 самых полных учебных материалов для внешнего интерфейса, от самых простых HTML + CSS + JS [классные спецэффекты, игры, упаковка плагинов, режим дизайна] до мобильного терминала. Проект HTML5 все учебные материалы организованы и отправлены. Каждый партнер, который хочет изучать веб-интерфейс или поменять карьеру, или студенты колледжа, и те, кто хочет улучшить свои способности на работе, могут присоединиться к обучению.

Нажмите:присоединиться

Многоуровневое меню

Постановка задачи
Повторный вызов макроса
Использование шаблонов второй раз
Использование шаблонов третий раз (и более)
Итоговый набор шаблонов
Недостатки подхода
Один вызов макроса
Использование шаблонов второй раз (и более)
Финальная оптимизация
Итоговый набор шаблонов
Дополнение: снятие активности с родительского элемента
Развернут только активный пункт меню
Все пункты меню развернуты

В этом примере рассматривается самое сложное для понимания меню. Однако от топика «Меню в виде списка» пример отличается лишь небольшой логической надстройкой, и понимание принципов, описанных в этой главе, позволит в полной мере оценить преимущества XSLT в качестве языка шаблонизатора.

Построение подобного меню тесно связано с построением так называемой «карты сайта» — списка страниц, отражающего реальную иерархию страниц на сайте (см. также

Карта сайта средствами XSLT-шаблонизатора).

Постановка задачи

Под многоуровневым меню мы будем понимать меню с вложенными пунктами, которые будут определяться реальной иерархией страниц на сайте.

Таким образом, если в структуре сайта мы видим иерархию:

  • страница 1

    • страница 1.1

    • страница 1.2

    • страница 1.3

      • страница 1.3.1

  • страница 2

  • страница 3

То в HTML-коде мы ожидаем получить следующее представление (содержимое тега <a> опущено):

<ul>
  <li>
    <a>страница 1</a>

    
    <ul>
       <li>
         <a>страница 1. 1</a>
       </li>
       <li>
         <a>страница 1.2</a>
       </li>
       <li>
         <a>страница 1.3</a>

         
         <ul>
            <li>
              <a>страница 1.3</a>
            </li>
         </ul> 

       </li>
    </ul>

  </li>
  <li>
    <a>страница 2</a>
  </li>
  <li>
    <a>страница 3</a>
  </li>
</ul>

Сконцентрируемся на задаче получения такого списка, а вопросы оформления его при помощи CSS уже можно будет решить самостоятельно.

За основу возьмем шаблоны, приведенные в топике «Меню в виде списка».

Повторный вызов макроса

Замечание

Этот подход не лишен недостатков, которые мы обсудим далее. Однако он иллюстрирует важные моменты работы XSLT-шаблонизатора.

Мы знаем, что шаблоны из топика «Меню в виде списка» выводят первый уровень, указывают ссылки на страницы и отмечают активный пункт меню.

Из задачи следует, что, если у нас есть вложенные подстраницы, то в текущий элемент списка <li></li> необходимо вставить новый элемент <ul></ul>, внутри которого нужно перечислить все подстраницы.

Таким образом исходные шаблоны для отдельного элемента списка первого уровня должен нам представляться следующим образом:



<xsl:template match="item" mode="menu">
  <li>
     <a href="{@link}">
        <xsl:value-of select="@name"/>
     </a>
     
  </li>
</xsl:template>



<xsl:template match="item[@status = 'active']" mode="menu">
  <li>
     <a href="{@link}">
       <xsl:value-of select="@name"/>
     </a>
     
  </li>
</xsl:template>

Мы знаем, что для того, чтобы получить список вложенных страниц (отображаемых в меню) для определенной страницы сайта, следует передать макросу %content menu()% еще один параметр — идентификатор страницы. Идентификатор доступен в этих шаблонах как атрибут id элемента item (так же как нам доступен атрибут link, который мы вставляем в ссылку).

Логично было бы потом обработать результаты, которые вернет макрос, и вывести их в нужном нам месте.

Для обработки результатов воспользуемся инструкцией apply-templates, для получения результатов — функцией document(), а для построения запроса макроса с параметром — функцией concat():

<xsl:template match="item" mode="menu">
  <li>
     <a href="{@link}">
        <xsl:value-of select="@name"/>
     </a>
     <xsl:apply-templates select="document(concat('udata://content/menu/0/1/', @id))/udata"/>
  </li>
</xsl:template>

Использование шаблонов второй раз

В этот момент должен возникнуть резонный вопрос: следует ли нам назначить этому вызову свой собственный режим, например mode=»menu-level2″, чтобы обработать результаты макроса отдельно?

Правильный ответ в рамках поставленной задачи: НЕТ. Этот шаблон у нас уже есть.

Для того, чтобы понять, почему это так — рассмотрим уже имеющийся шаблон, обрабатывающий вызов макроса %content menu()%:

<xsl:template match="udata[@module = 'content'][@method = 'menu']">
  <ul>
      <xsl:apply-templates select="items/item" mode="menu"/>
  </ul>
</xsl:template>

Этот шаблон уже и так делает то, что нам нужно: берет содержимое элемента udata с атрибутами module = 'content' и method = 'menu', вставляет теги <ul></ul> и отправляет на обработку все элементы item, результаты помещая между <ul></ul>.

Еще раз остановимся на этом моменте: когда мы отдаем результат в обработку при помощи инструкции apply-templates, шаблонизатор ищет подходящий шаблон среди всех доступных шаблонов. Поэтому условие match="udata[@module = 'content'][@method = 'menu'] также сработает и для повторного вызова макроса.

Аналогично, этот шаблон получит все элементы item при помощи <xsl:apply-templates select="items/item" mode="menu"/> и отправит их на обработку двум следующим шаблонам (в которые мы выше добавили повторный вызов макроса):



<xsl:template match="item" mode="menu">
  <li>
    <a href="{@link}">
      <xsl:value-of select="@name"/>
    </a>
    <xsl:apply-templates select="document(concat('udata://content/menu/0/1/', @id))/udata[items/item]"/>
  </li>
</xsl:template>



<xsl:template match="item[@status = 'active']" mode="menu">
  <li>
     <a href="{@link}">
       <xsl:value-of select="@name"/>
     </a>
     <xsl:apply-templates select="document(concat('udata://content/menu/0/1/', @id))/udata[items/item]"/>
  </li>
</xsl:template>

Использование шаблонов третий раз (и более)

Как видно, этих шаблонах мы снова вызываем макрос %content menu()% и снова у нас уже есть шаблон для обработки результатов. Эта процедура будет повторена снова и снова, пока у нас не будут выбраны все страницы с отмеченной опцией «Отображать в меню». Шаблонизатор, таким образом, «развернет» все дерево иерархии страниц, которые должны попасть в меню, и превратит его во вложенные списки.

Уточняющее условие [items/item] в select для apply-templates, позволяет выбирать элемент udata только в том случае, если у него есть вложенные элементы item (то есть вложенные подстраницы).

Замечание

Если мы уберем повторный вызов макроса из <xsl:template match="item" mode="menu">, то меню будет разворачиваться только для активных пунктов.

Итоговый набор шаблонов

В итоге, если нас интересует вся иерархия, мы должны получить следующий набор шаблонов:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output encoding="UTF-8" method="html" indent="yes"/>

  
  
  <xsl:template match="/">
    <html>
      <head></head>
      <body>
      
        <div>
          <xsl:apply-templates select="document('udata://content/menu/')/udata"/>
        </div>

        <div>
          
        </div>
      </body>
    </html>
  </xsl:template>

  

  <xsl:template match="udata[@module = 'content'][@method = 'menu']">
    <ul>
      <xsl:apply-templates select="items/item" mode="menu"/>
    </ul>
  </xsl:template>

  

  <xsl:template match="item" mode="menu">
    <li>
      <a href="{@link}">
        <xsl:value-of select="@name"/>
      </a>
      
      <xsl:apply-templates select="document(concat('udata://content/menu/0/1/', @id))/udata[items/item]"/>
    </li>
  </xsl:template>

  

  <xsl:template match="item[@status = 'active']" mode="menu">
    <li>
       <a href="{@link}">
         <xsl:value-of select="@name"/>
       </a>
       <xsl:apply-templates select="document(concat('udata://content/menu/0/1/', @id))/udata[items/item]"/>
    </li>
  </xsl:template>

</xsl:stylesheet>

Недостатки подхода

Как нетрудно заметить, вызов макроса осуществляется много раз. И чем более сложная иерархия — тем чаще. Ниже описывается способ, когда достаточно одного вызова макроса %content menu()% для того, чтобы обработать всю иерархию страниц, выводимых в меню.

Один вызов макроса

Рассмотрим ответ макроса %content menu()%, где параметр max_depth регулирует уровень отображения вложенных пунктов меню. Зададим max_depth = 3.

Вызов макроса: udatа://content/menu/0/3 (или можно набрать в URL: http://ваш_сайт/udata/content/menu/0/3)

Примерный ответ макроса (пустые строки вставлены для читаемости):

<udata module="content" method="menu" generation-time="0.035795">
  <items>
    <item link="/page1/" name="страница 1" xlink:href="upage://94">

      <items>
        <item link="/page11/" name="страница 1.1" xlink:href="upage://105">страница 1.1</item>
        <item link="/page12/" name="страница 1.2" xlink:href="upage://106">страница 1. 2</item>
        <item link="/page13/" name="страница 1.3" xlink:href="upage://107">

          <items>
            <item link="/page131/" name="страница 1.3.1" xlink:href="upage://115">страница 1.3.1</item>
          </items>

         страница 1.3

        </item>
      </items>

      страница 1

    </item>
    <item link="/page2/" name="страница 2" xlink:href="upage://95">страница 2</item>
    <item link="/page3/" name="страница 3" xlink:href="upage://96">страница 3</item>
  </items>
</udata>

Задачи у нас те же, что и в предыдущем топике, их можно выразить таким же представлением шаблона:

<xsl:template match="item" mode="menu">
  <li>
     <a href="{@link}">
        <xsl:value-of select="@name"/>
     </a>
     
  </li>
</xsl:template>

Однако, глядя на ответ макроса, мы можем видеть, что для некоторых элементов item мы уже имеем доступ ко вложенным страницам — вложенные элементы item описывают нам подпункты меню.

Тогда, мы можем обработать весь список без дополнительных вызовов и запросов к системе — просто укажем, что надо обработать эти элементы при помощи инструкции apply-templates.

Однако, нам необходимо, чтобы каждый новый список находился в элементе <ul></ul> — следовательно для всего списка подстраниц необходимо выбирать элемент items (он содержит весь список).

<xsl:template match="item" mode="menu">
  <li>
     <a href="{@link}">
        <xsl:value-of select="@name"/>
     </a>
     <xsl:apply-templates select="items" mode="menu"/>
  </li>
</xsl:template>

И необходимо описать шаблон именно для него (условие match="items"). Этот шаблон обрамляет список <ul></ul> и отправляет (apply-templates) вложенные элементы item на обработку.

<xsl:template match="items" mode="menu">
  <ul>
    <xsl:apply-templates select="item" mode="menu"/>
  </ul>
</xsl:template>

Использование шаблонов второй раз (и более)

Также как в и предыдущем примере с повторным вызовом макроса, для элемента item уже есть шаблоны. И это шаблоны <xsl:template match="item" mode="menu"> — для неактивного пункта меню, и <xsl:template match="item[@status = 'active']" mode="menu"> — для активного пункта меню.



<xsl:template match="item" mode="menu">
  <li>
    <a href="{@link}">
      <xsl:value-of select="@name" />
    </a>
    <xsl:apply-templates select="items" mode="menu"/>
  </li>
</xsl:template>



<xsl:template match="item[@status = 'active']" mode="menu">
  <li>
    <a href="{@link}">
      <xsl:value-of select="@name" />
    </a>
    <xsl:apply-templates select="items" mode="menu"/>
  </li>
</xsl:template>

И в этих шаблонах теперь стоит запрос на вложенные элементы. В случае их наличия вызов <xsl:apply-templates select="items" mode="menu"/> снова отправит их к <xsl:template match="items" mode="menu">, который создаст новые теги списка, и отдаст элементы списка на обработку снова этим шаблонам.

Таким образом эти три шаблона обработают все дерево, отданное макросом %content menu()%.

Замечание

Если мы уберем вызов apply-templates из <xsl:template match="item" mode="menu">, то меню будет разворачиваться только для активных пунктов.

Финальная оптимизация

Можно заметить, что шаблон, обрабатывающий результаты вызова макроса, также вставляет элемент <ul></ul>. Можно воспользоваться этим свойством и передать эту задачу шаблону, обрабатывающему элемент items. Тогда набор шаблонов будет выглядеть следующим образом:

  

  <xsl:template match="udata[@module = 'content'][@method = 'menu']">
      <xsl:apply-templates select="items" mode="menu"/>
  </xsl:template>

  

  <xsl:template match="items" mode="menu">
    <ul>
      <xsl:apply-templates select="item" mode="menu"/>
    </ul>
  </xsl:template>

  

  <xsl:template match="item" mode="menu">
    <li>
      <a href="{@link}">
        <xsl:value-of select="@name"/>
      </a>
      
      <xsl:apply-templates select="items" mode="menu"/>    </li>
  </xsl:template>

  

  <xsl:template match="item[@status = 'active']" mode="menu">
    <li>
       <a href="{@link}">
         <xsl:value-of select="@name"/>
       </a>
       <xsl:apply-templates select="items" mode="menu"/>
    </li>
  </xsl:template>

</xsl:stylesheet>

Если посмотреть внимательно, то можно увидеть, что можно также обойтись без шаблона <xsl:template match="udata[@module = 'content'][@method = 'menu']">.

Тогда при первом вызове из шаблона дизайна просто достаточно сразу выбрать элемент items, но обязательно задать ему свой режим mode="menu":

  
  
  <xsl:template match="/">
    <html>
      <head></head>
      <body>
      
        <div>
          <xsl:apply-templates select="document('udata://content/menu/0/3')/udata/items" mode="menu"/>
        </div>

        <div>
          
        </div>
      </body>
    </html>
  </xsl:template>

Итоговый набор шаблонов

Этот вариант получился наиболее лаконичным, быстрым, и использующим всю гибкость языка XSLT:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output encoding="UTF-8" method="html" indent="yes"/>

  
  
  <xsl:template match="/">
    <html>
      <head></head>
      <body>
      
        <div>
          <xsl:apply-templates select="document('udata://content/menu/0/3')/udata/items" mode="menu"/>
        </div>

        <div>
          
        </div>
      </body>
    </html>
  </xsl:template>

  

  <xsl:template match="items" mode="menu">
    <ul>
      <xsl:apply-templates select="item" mode="menu"/>
    </ul>
  </xsl:template>

  

  <xsl:template match="item" mode="menu">
    <li>
      <a href="{@link}">
        <xsl:value-of select="@name"/>
      </a>
      
      <xsl:apply-templates select="items" mode="menu"/>
    </li>
  </xsl:template>

  

  <xsl:template match="item[@status = 'active']" mode="menu">
    <li>
       <a href="{@link}">
         <xsl:value-of select="@name"/>
       </a>
       <xsl:apply-templates select="items" mode="menu"/>
    </li>
  </xsl:template>

</xsl:stylesheet>

Дополнение: снятие активности с родительского элемента

Макрос %content menu()% помечает родительский элемент также атрибутом status = 'active'. Иногда это может быть нежелательно — в таком случае можно воспользоваться еще одним дополнительным уточняющим условием.

Рассмотрим два примера решения для шаблонов с одним вызовом макроса (см. выше).

Развернут только активный пункт меню

Добавим шаблон с условием для неактивных пунктов меню:

<xsl:template match="item[.//item[@status = 'active']]" mode="menu">
    <li>
      <a href="{@link}">
        <xsl:value-of select="@name"/>
      </a>
      <xsl:apply-templates select="items" mode="menu"/>
    </li>
</xsl:template>

Это условие говорит о том, что этот шаблон будет выбран для элемента item, у которого есть дочерние элементы с атрибутом status = 'active'. Логично предположить, что в этот момент открыта дочерняя страница, для этого элемента.

Таким образом итоговый набор шаблонов должен выглядеть следующим образом:

<?xml version="1. 0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output encoding="UTF-8" method="html" indent="yes"/>

  
  
  <xsl:template match="/">
    <html>
      <head></head>
      <body>
      
        <div>
          <xsl:apply-templates select="document('udata://content/menu/0/3')/udata/items" mode="menu"/>
        </div>

        <div>
          
        </div>
      </body>
    </html>
  </xsl:template>

  

  <xsl:template match="items" mode="menu">
    <ul>
      <xsl:apply-templates select="item" mode="menu"/>
    </ul>
  </xsl:template>

  

  <xsl:template match="item" mode="menu">
    <li>
      <a href="{@link}">
        <xsl:value-of select="@name"/>
      </a>
    </li>
  </xsl:template>

  

  <xsl:template match="item[@status = 'active']" mode="menu">
    <li>
       <span>
         <xsl:value-of select="@name"/>
       </span>
       <xsl:apply-templates select="items" mode="menu"/>
    </li>
  </xsl:template>

  

  <xsl:template match="item[. //item[@status = 'active']]" mode="menu">
    <li>
       <a href="{@link}">
         <xsl:value-of select="@name"/>
       </a>
       <xsl:apply-templates select="items" mode="menu"/>
    </li>
  </xsl:template>

</xsl:stylesheet>

Все пункты меню развернуты

В этой ситуации мы можем немного оптимизировать код шаблонов, используя то же условие, что и в предыдущем примере:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output encoding="UTF-8" method="html" indent="yes"/>

  
  
  <xsl:template match="/">
    <html>
      <head></head>
      <body>
      
        <div>
          <xsl:apply-templates select="document('udata://content/menu/0/3')/udata/items" mode="menu"/>
        </div>

        <div>
          
        </div>
      </body>
    </html>
  </xsl:template>

  

  <xsl:template match="items" mode="menu">
    <ul>
      <xsl:apply-templates select="item" mode="menu"/>
    </ul>
  </xsl:template>

  

  <xsl:template match="item[@status = 'active']" mode="menu">
    <li>
       <span>
         <xsl:value-of select="@name"/>
       </span>
       <xsl:apply-templates select="items" mode="menu"/>
    </li>
  </xsl:template>

  

  <xsl:template match="item|item[. //item[@status = 'active']]" mode="menu">
    <li>
       <a href="{@link}">
         <xsl:value-of select="@name"/>
       </a>
       <xsl:apply-templates select="items" mode="menu"/>
    </li>
  </xsl:template>

</xsl:stylesheet>

Замечание

Следует иметь в виду, что приоритет у условий item[@status = 'active'] и item[.//item[@status = 'active']] — одинаковый, поэтому шаблон для неактивных и родительских страниц нужно помещать после шаблона для активных пунктов. По правилам языка XSLT в случае одинакового приоритета выбирается последний встреченный шаблон.

Несколько меню на сайте

Была ли данная статья полезна? Как можно улучшить эту статью?

Меню с изображениями

Многоуровневое меню | PHPClub — клуб разработчиков PHP

nocturne
квантовая нелокальность