Здравствуйте уважаемые Хабровчане. Хочу представить шаблон вывода многоуровневого меню, хотя, немного переделав, сойдет для вывода обычных деревьев. На нашем любимом сайте подобного не видел, в инете особо не искал. Для кого-то может показаться слишком легким, но надеюсь другим понадобиться.
Вот здесь уже разбиралась тема построение деревьев. В этом примере другая структура XML файла и заточка под другие задачи.
Начнем с XML файла. Структура не сложная. Каждый элемент состоит из идентификатора, идентификатора родительского элемента, ссылки и названия.
menu.xml
Не долго думая выведем шаблон преобразования
menu.xsl
Шаблон преобразования состоит из двух частей. Первая выводит основные HTML теги и не особо интересна. Стоит только обратить внимание на вызов шаблона, который начинает вызов элементов с родительским идентификатором равным нулю.
Втора часть выводит пункт меню и проверяет, есть ли элементы с родительским идентификатором равным текущему идентификатору. Если есть, то рекурсивно вызывает этот же шаблон.
Естественно, пункты ссылающиеся на не существующих родителей отображаться не будут.
Сохраняем menu.xml и menu.xsl в одной папке и в браузере запускаем первый. Видим вот такую картину.
Вывод меню
P. S. Спасибо Dart за найденные ошибки.
Вот здесь уже разбиралась тема построение деревьев. В этом примере другая структура XML файла и заточка под другие задачи.
Начнем с XML файла. Структура не сложная. Каждый элемент состоит из идентификатора, идентификатора родительского элемента, ссылки и названия.
menu.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="menu.xsl"?>
<root>
<item id="1" idParent="0" link="#" title="Ссылка 1"/>
<item id="2" idParent="1" link="#" title="Ссылка 2"/>
<item id="3" idParent="1" link="#" title="Ссылка 3"/>
<item id="4" idParent="2" link="#" title="Ссылка 4"/>
<item id="5" idParent="2" link="#" title="Ссылка 5"/>
<item id="6" idParent="1" link="#" title="Ссылка 6"/>
<item id="7" idParent="6" link="#" title="Ссылка 7"/>
<item id="8" idParent="6" link="#" title="Ссылка 8"/>
<item id="9" idParent="0" link="#" title="Ссылка 9"/>
</root>
Не долго думая выведем шаблон преобразования
menu.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Настройка вывода -->
<xsl:output method="html" encoding="utf-8" omit-xml-declaration="yes" doctype-system="about:legacy-compat"/>
<!-- Основное преобразование -->
<xsl:template match="/">
<html lang="ru">
<head>
<title>Многоуровневое меню</title>
</head>
<body>
<h1>Многоуровневое меню</h1>
<ul>
<xsl:apply-templates select="/root/item[@idParent=0]"/>
</ul>
</body>
</html>
</xsl:template>
<!-- Шаблон вывода меню -->
<xsl:template match="/root/item">
<xsl:variable name="id" select="@id"/>
<!-- Вывод элемента меню -->
<li>
<a href="{@link}">
<xsl:value-of select="@title"/>
</a>
<!-- Если существют подпункты -->
<xsl:if test="/root/item[@idParent=$id]">
<ul>
<xsl:apply-templates select="/root/item[@idParent=$id]"/>
</ul>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
Шаблон преобразования состоит из двух частей. Первая выводит основные HTML теги и не особо интересна. Стоит только обратить внимание на вызов шаблона, который начинает вызов элементов с родительским идентификатором равным нулю.
Втора часть выводит пункт меню и проверяет, есть ли элементы с родительским идентификатором равным текущему идентификатору. Если есть, то рекурсивно вызывает этот же шаблон.
Естественно, пункты ссылающиеся на не существующих родителей отображаться не будут.
Сохраняем menu.xml и menu.xsl в одной папке и в браузере запускаем первый. Видим вот такую картину.
Вывод меню
P. S. Спасибо Dart за найденные ошибки.