Вывод HTML в XSLT, если основан на позиции

#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>