Руководство по шаблонам XUL:Рекурсивное генерирование контента
Материал из MDC.
В предыдущем примере конструктор создал во второй строке лишний набор из двух кнопок. Тем не менее, надписи на кнопках во втором наборе отличаются от надписей в первом наборе. Если вы посмотрите на граф снова, вы можете догадаться, почему так происходит. На нём видно, что узлы C и D соединены дугой с меткой relatedItem. Эта лишняя дуга, которой ни имеет ни узел B, ни узел D, и стала причиной создания дополнительного набора кнопок.
После создания контента конструктор повторяет таким же образом процесс и на более нижних уровнях - до тех пор, пока это возможно. Таким образом, можно сказать, что конструктор создаёт контент рекурсивно. Т.е. после создания контента на одном уровне, конструктор выполняет работу на новом уровне - для нового родительского узла и новой начальной вершины. Естественно, родительский узел будет выбран из только что созданного контента, а не из какого-либо внешнего элемента, и начальная вершина будет выбрана среди конечных вершин предыдущего набора конечных вершин. В данном случае родительский узел - это элемент с атрибутом datasources, т.е. <vbox>. Для вложенных результатов родительским узлом станет один из элементов, созданных на предыдущем уровне. Таким образом, после первой итерации имеем:
<vbox datasources="http://www.xulplanet.com/ds/sample.rdf"
ref="http://www.xulplanet.com/rdf/A">
<template>
<query>
<content uri="?start"/>
<triple subject="?start"
predicate="http://www.xulplanet.com/rdf/relatedItem"
object="?relateditem"/>
</query>
<action>
<hbox uri="?relateditem">
<button label="?start"/>
<button label="?relateditem"/>
</hbox>
</action>
</template>
<hbox id="http://www.xulplanet.com/rdf/B">
<button label="http://www.xulplanet.com/rdf/A"/>
<button label="http://www.xulplanet.com/rdf/B"/>
</hbox>
<hbox id="http://www.xulplanet.com/rdf/C">
<button label="http://www.xulplanet.com/rdf/A"/>
<button label="http://www.xulplanet.com/rdf/C"/>
</hbox>
<hbox id="http://www.xulplanet.com/rdf/D">
<button label="http://www.xulplanet.com/rdf/A"/>
<button label="http://www.xulplanet.com/rdf/D"/>
</hbox>
</vbox>
Для следующей итерации точками вставки контента станут три элемента <hbox>. Тем не менее, поскольку только узел C имеет дополнительный контент, только во второй элемент <hbox> будут вложены дополнительные дочерние элементы.
Для вложенных элементов конструктор обрабатывает запрос как обычно; разве что в качестве начальной точки (seed) вместо атрибута ref используется конечная вершина (end point or member). Причём это значение должно соответствовать атрибуту id подходящего элемента. Вначале обрабатывается узел B:
(?start = http://www.xulplanet.com/rdf/B)
После проверяется условие <triple>, однако из узла B не выходит дуга с меткой relatedItem, поэтому результат отбрасывается. Поскольку нет никаких результатов, контента не создаётся. Аналогичная ситуация и с узлом D. Тем не менее, для узла C условие выполняется и к промежуточным результатам добавляется набор данных:
(?start = http://www.xulplanet.com/rdf/C, ?relateditem = http://www.xulplanet.com/rdf/D)
Поскольку имеются результаты, к контенту, соответствующему узлу C, будет добавлена новая информация - согласно инструкциям в блоке action. Поскольку переменная ?start указывает на узел C и переменная ?relateditem указывает на D, будут добавлены кнопки именно с этими надписями. Посмотрите на приведённый рисунок и проверьте это. Теперь контент для узла C выглядит так:
<hbox id="http://www.xulplanet.com/rdf/C">
<button label="http://www.xulplanet.com/rdf/A"/>
<button label="http://www.xulplanet.com/rdf/C"/>
<hbox id="http://www.xulplanet.com/rdf/D">
<button label="http://www.xulplanet.com/rdf/C"/>
<button label="http://www.xulplanet.com/rdf/D"/>
</hbox>
</hbox>
Рекурсивная природа шаблонов имеет полезное применение при работе с меню и деревьями, позволяя автоматически создавать вложенный контент. Мы узнаем больше о рекурсивных шаблонах позже, а пока что рассмотрим более-менее реалистичный пример.
