Полезные ссылки на документацию по XSL

#
Re: Полезные ссылки на документацию по XSL
Уважаемый модератор, объясните пожалуйста, почему ваш способ работает:
<SCRIPT>
<xsl:comment>
<xsl:text disable-output-escaping="yes">
<![CDATA[
ЗДЕСЬ_КОД
]]>
</xsl:text>
</xsl:comment>
</SCRIPT>

Т.е. спасибо вам большое за этот пример, все ОК, работает.
Но хочется понять, зачем вокруг xsl:text еще и xsl:comment писать? Без коммента пробовал - эскейпятся тэги, встречающиеся в javascript коде.
#
Re: Полезные ссылки на документацию по XSL
Как посчитать количество уже выведенных элементов?
Элементы выводятся через шаблон, но не подряд.
#
Re: Полезные ссылки на документацию по XSL
Stepan0v писал(а):
Как посчитать количество уже выведенных элементов?

position()
всегда возвращает номер текущего элемента в выборкенапример
<xsl:if test="position() &gt; 5">Мы вывели уже, как минимум, 5 элементов</xsl:if>


Stepan0v писал(а):
Элементы выводятся через шаблон, но не подряд.
Тогда два варианта -
- неправильный это учитывать "вывод не подряд" в условии, при этом у вас position() будет равен номеру текущего элемента в выборке, но не обязательно равен кол-ву выведенных элементов,
- и правильный, это передавать в темплейт только те элементы, которые надо выводить.

И пару примеров, для наглядности.
Задача по выводу только четных элементов:

Допустим, у нас есть xml (кстати, от облака тегов в магазине), в котором есть некоторое количество узлов tag:
<?xml version="1.0"?>
<shop id="1">
   <shop_dir_id>0</shop_dir_id>
   <shop_company_id>1</shop_company_id>
   <site_id>1</site_id>
   ...
   <tag id="69">
      <tag_dir_id>0</tag_dir_id>
      <name>Ardo</name>
      <path>Ardo</path>
      <user_id>0</user_id>
      <description></description>
      <urlencode>Ardo</urlencode>
      <count>2</count>
   </tag>
   <tag id="65">
      <tag_dir_id>0</tag_dir_id>
      <name>Ariston</name>
      <path>Ariston</path>
      <user_id>0</user_id>
      <description></description>
      <urlencode>Ariston</urlencode>
      <count>2</count>
   </tag>
   <tag id="87">
      <tag_dir_id>0</tag_dir_id>
      <name>Ballu</name>
      <path>Ballu</path>
      <user_id>0</user_id>
      <description></description>
      <urlencode>Ballu</urlencode>
      <count>1</count>
   </tag>
   ...
</shop>

И мы хотим вывести только четные узлы.
По первому способу это будет так:
<xsl:template match="/shop">
   <ol>
      <xsl:apply-templates select="tag"/>
   </ol>
</xsl:template>

<xsl:template match="tag">
   <xsl:if test="position() mod 2 = 0">
      <li>Уже выведено <xsl:value-of select="position()"/> тегов -
         <xsl:value-of select="name"/>
      </li>
   </xsl:if>
</xsl:template>
и в результате получится: Цитата:
1. Уже выведено 2 тегов - Ariston
2. Уже выведено 4 тегов - BBK
3. Уже выведено 6 тегов - Bosch
4. Уже выведено 8 тегов - Cowon
5. Уже выведено 10 тегов - Electrolux
6. Уже выведено 12 тегов - Indesit
7. Уже выведено 14 тегов - JVC Everio
8. Уже выведено 16 тегов - LG
9. Уже выведено 18 тегов - Nexx
10. Уже выведено 20 тегов - Noirot
11. Уже выведено 22 тегов - Panasonic
12. Уже выведено 24 тегов - Polaris
13. Уже выведено 26 тегов - Sony
14. Уже выведено 28 тегов - Timberk
15. Уже выведено 30 тегов - Whirlpool
16. Уже выведено 32 тегов - Атлант
17. Уже выведено 34 тегов - Гефест
18. Уже выведено 36 тегов - плита
19. Уже выведено 38 тегов - телевизор
20. Уже выведено 40 тегов - холодильник

И при этом мы создадим паразитную нагрузку на сервер, потому что обработаем все 40 узлов, даром, что выведем только 20 из них.

Вторым, правильным способом, это будет так:
<xsl:template match="/shop">
   <ol>
      <xsl:apply-templates select="tag[position() mod 2 = 0]"/>
   </ol>
</xsl:template>

<xsl:template match="tag">
   <li>Уже выведено <xsl:value-of select="position()"/> тегов -
      <xsl:value-of select="name"/>
   </li>
</xsl:template>
и в результате получим полное соответствие Цитата:
1. Уже выведено 1 тегов - Ariston
2. Уже выведено 2 тегов - BBK
3. Уже выведено 3 тегов - Bosch
4. Уже выведено 4 тегов - Cowon
5. Уже выведено 5 тегов - Electrolux
6. Уже выведено 6 тегов - Indesit
7. Уже выведено 7 тегов - JVC Everio
8. Уже выведено 8 тегов - LG
9. Уже выведено 9 тегов - Nexx
10. Уже выведено 10 тегов - Noirot
11. Уже выведено 11 тегов - Panasonic
12. Уже выведено 12 тегов - Polaris
13. Уже выведено 13 тегов - Sony
14. Уже выведено 14 тегов - Timberk
15. Уже выведено 15 тегов - Whirlpool
16. Уже выведено 16 тегов - Атлант
17. Уже выведено 17 тегов - Гефест
18. Уже выведено 18 тегов - плита
19. Уже выведено 19 тегов - телевизор
20. Уже выведено 20 тегов - холодильник
и сэкономим на нагрузке сервера


P.S. Кстати, возможно вам еще понадобится функция
last()
- она возвращает общее число элементов в выборке. Для первого из приведенных примеров она вернет 40, а для второго - 20.

<xsl:if test="position() = last()">
- проверка, что текущий обрабатываемый элемент - последний.
Заказов не беру. Консультирую редко.
#
Re: Полезные ссылки на документацию по XSL
Ну и - да, операция mod возвращает остаток от целочисленного деления.
Заказов не беру. Консультирую редко.
#
Re: Re: Полезные ссылки на документацию по XSL
Kotoff, спасибо.
position() - это первое, что я попробовал
Ещё пробовал что-то типа
count(./preceding-sibling::informationsystem_item)


Но вся проблема в том, что элементы выводятся не из одной выборки.
Выводятся элементы из разных групп (подгрупп). Соответственно, для каждой группы своя выборка.
position() выдает номер внутри группы, когда выводится следующая группа, то счетчик идет сначала.
#
Re: Полезные ссылки на документацию по XSL
Так значит надо собрать их в одну выборку.
Они же у вас все равно выводятся в одном месте, только не все, да?

Ну или опишите задачу целиком.
Заказов не беру. Консультирую редко.
#
Re: Re: Полезные ссылки на документацию по XSL
Они выводятся не подряд, а по группам. Т.е. сначала выводится название группы, потом название подгруппы, потом все элементы этой подгруппы. Потом название следующей подгруппы, её элементы и т.д.
Я хочу ограничить этот вывод, например 10ю элементами. Т.е. не важно сколько групп будет выведено. Но если 10 элементов уже есть, то вывод прекращается.

Ограничить в ТДС не могу, потому что ограничение идет независимо от групп. Т.е. элементы сортируются среди всех элементов, не важно в какой группе они находятся. А мне нужно выводить по группам.
#
Re: Полезные ссылки на документацию по XSL
Хм. А вот это уже интересно

Ограничить в ТДС, строго говоря, можно, если у группы организовать цикл по всем подгруппам, вытаскивая из них элементы и получая их идентификаторы и складывая их в массивчик, до тех пор, пока число элементов в нем не будет равно 10. Тут мы сразу делаем циклу break, (точнее обоим циклам - их будет два вложенных - первый для подгрупп, второй - для элементов) а затем через queryBuilder для items добавляем ограничение
WHERE id IN ( а тут наш массивчик с идентификаторами ).
Таким образом, мы получим в XML ровно 10 элементов. Правда будут лишние подгруппы. Поэтому надо в темплейте завести условие на обработку только тех групп, для которых в XML существуют элементы.

Есть изрядные основания полагать, что такой способ будет внезапно быстрее, чем решение на чистом XSL.

Впрочем, на XSL это тоже можно реализовать, и с правильной выборкой из 10 темплейтов, но уже немного сложнее.

Например, сначала делаем выборку из 10 элементов, и сохраняем ее в переменную.
И потом обрабатываем ее в два прохода темплейтами с разным mode, один из них вызывает обработку подгрупп по id, при чем уникализируя при этом идентификаторы, а из темплейта обрабатывающего подгруппы вызывается второй темплейт, на который матчится все та же выборка из переменной, с уточнением по id группы.

Это довольно сумбурно, но если бы у меня был под руками подходящий XML то это было бы проще показать в коде, чем описывать словами.
Заказов не беру. Консультирую редко.
#
Re: Полезные ссылки на документацию по XSL
Kotoff писал(а):
их будет два вложенных — первый для подгрупп, второй — для элементов

Проблема в том что не два, а, как минимум три: для групп, подгрупп и элементов. Но в некоторый случаях подгрупп нет, элементы лежат сразу в группе.
Я подозреваю, что это самое верное решение, но пока не в состоянии его реализовать.

Возможно, было бы правильным пересортировать элементы по группам, а потом использовать штатный limit(). Но при этом нужно ещё не сбить существующую сортировку (может быть по порядку, алфавиту и обратно).

Kotoff писал(а):
сначала делаем выборку из 10 элементов, и сохраняем ее в переменную.

Элементы могут быть из разных групп разной вложенности и просто так подряд их не вытащить. Надо обходить группы с дочерними подгруппами. Но с выборками в переменной можно бы было заморочиться.

В идеале бы просто поставить переменную-счетчик и инкрементить её при выводе элемента. Но с xsl, как я понимаю, такие вольности не прокатывают, когда есть переходы между темплейтами.

Kotoff писал(а):
 если бы у меня был под руками подходящий XML

Могу предложить свой. Но он большой (самый верхний уровень структуры) http://deleuze.ru/max.xml
#
Re: Полезные ссылки на документацию по XSL
Stepan0v писал(а):
Могу предложить свой.
Вечерком гляну
Заказов не беру. Консультирую редко.
Авторизация