#html #xml #xslt
#HTML #xml #xslt
Вопрос:
Я занят некоторыми материалами XSLT и хочу начинать новую строку каждые 3 элемента. Я подумал, что мог бы выполнить оператор if и протестировать position mod 3, чтобы выяснить, являюсь ли я первой или последней ячейкой в моей таблице.
Следующий оператор if действительно работает, но Copernica (инструмент, в котором я использую XSLT) не принимает следующий XSLT. Причина в том, что <tr>
не закрывается в инструкции if.
Я ищу способ обработки разделения ленты продуктов на строки после 3 элементов.
<xsl:if test="position() mod 3 = 1">
<tr>
</xsl:if>
Ответ №1:
Я предполагаю, что вы использовали бы другой <xsl:if/>
позже в своем коде, чтобы закрыть <tr/>
. К сожалению, хотя это было бы допустимо на другом языке программирования, этого не может быть с xslt.
XSLT не является процедурным или императивным языком, поэтому не используйте его как таковой. Вместо этого вы можете сделать что-то вроде этого :
<xsl:template match="element[position() mod 3 = 1]">
<tr>
<xsl:apply-templates mode="single" select=".|following-sibling::element[not(position() > 2)]"
/>
</tr>
</xsl:template>
<xsl:template match="element" mode="single">
<td>
<!--your stuff between rows here-->
</td>
</xsl:template>
<xsl:template match="element[not(position() mod 3 = 1)]"/>
Таким образом, это в основном создает tr каждые три строки и, кроме того, вызывает другой шаблон для обработки элементов, которые находятся между этими строками. «элемент» должен быть элементом, который вы хотите обработать.
Комментарии:
1. 1 хороший ответ. Должно ли это быть,
not(position() >=3)
хотя, вместо> 3
? Похоже, что вы включаете трех следующих братьев и сестер в дополнение к self.2. Хороший ответ, но я думаю, что излишне сильно утверждать, что XSLT не является языком программирования. Это, конечно, не процедурный или императивный язык, но это должен быть язык программирования . Как еще вы бы это назвали?
3. @lwburk Ну и дела… Я перефразировал для краткости, но все в порядке… теперь это «исправлено» (иногда я думаю, что это соревнование, чтобы увидеть, кто может быть самым педантичным)
4. @FailedDev — Точность и педантичность иногда одно и то же, а часто и нет. В любом случае, это был хороший ответ.
Ответ №2:
Если бы Copernica приняла этот XSLT, это было бы неправильно. XSLT — это XML, а XML должен быть строго иерархическим. <xsl:if>
Элемент не может содержать начальный тег like <tr>
без соответствующего конечного тега </tr>
в том же <xsl:if>
элементе. Другими словами, таблица стилей XSLT — это не поток начальных и конечных тегов произвольной формы; это поток начальных и конечных тегов, которые выражают древовидную структуру узлов. <a> <b> </a>
не отображает древовидную структуру, даже если у вас есть </b>
более поздняя. Подумайте о начальных / конечных тегах, таких как круглые скобки:
(1 * [2 3)]
не является грамматическим.
@FailedDev прав, что вы не можете рассматривать XSLT как процедурный язык программирования. Нельзя предполагать, что элементы будут обрабатываться в определенном порядке. Вместо того, чтобы думать «мне нужно начинать новую строку через каждые три элемента» (процедурная концепция «один за другим»), вам нужно представить это как «Мне нужно сгруппировать элементы в группы по три, причем строка содержит каждую группу».
Я не могу придумать лучшей реализации этого, чем @FailedDev в XSLT 1.0, поэтому я не буду ее предлагать. В XSLT 2.0 вы можете использовать
<xsl:for-each-group group-starting-with="element[position() mod 3 = 1]">
<tr>
<xsl:apply-templates select="current-group()" />
</tr>
</xsl:for-each-group>
…
<xsl:template match="element">
<!-- your stuff between rows here -->
</xsl:template>