Рекурсивное генерирование контента

В предыдущем примере конструктор создал во второй строке лишний набор из двух кнопок. Тем не менее, надписи на кнопках во втором наборе отличаются от надписей в первом наборе. Если вы посмотрите на граф снова, вы можете догадаться, почему так происходит. На нём видно, что узлы 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)

Image:Template-guide-p9.png

Поскольку имеются результаты, к контенту, соответствующему узлу 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>

Рекурсивная природа шаблонов имеет полезное применение при работе с меню и деревьями, позволяя автоматически создавать вложенный контент. Мы узнаем больше о рекурсивных шаблонах позже, а пока что рассмотрим более-менее реалистичный пример.

Метки документа и участники

 Внесли вклад в эту страницу: chrisdavidmills, Bektur
 Обновлялась последний раз: chrisdavidmills,