Как обернуть список при сохранении содержимого с помощью xslt 2.0 - PullRequest
0 голосов
/ 05 сентября 2018

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

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Я бы использовал match="*[listitem]" или match="*[listitem[@class]]", чтобы сопоставить родительский элемент, содержащий элементы listitem, которые вы хотите сгруппировать / обернуть, а затем использовать for-each-group для дочерних элементов родителя, если вы ожидаете их только чтобы быть элементами, вы можете использовать select="*" composite="yes" group-adjacent="boolean(self::listitem), @class" в XSLT 3 для идентификации смежных listitem с тем же значением атрибута class:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:output method="html" indent="yes" html-version="5"/>

  <xsl:template match="*[listitem]">
      <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:for-each-group select="*" composite="yes" group-adjacent="boolean(self::listitem), @class">
              <xsl:choose>
                  <xsl:when test="current-grouping-key()[1]">
                      <xsl:element name="{current-grouping-key()[2]}">
                          <xsl:apply-templates select="current-group()"/>
                      </xsl:element>
                  </xsl:when>
                  <xsl:otherwise>
                      <xsl:apply-templates select="current-group()"/>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="listitem">
      <li>
          <p>
              <xsl:apply-templates/>
          </p>
      </li>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / gWmuiJK

С XSLT 2 вы можете использовать два вложенных for-each-group например.

      <xsl:for-each-group select="*" group-adjacent="boolean(self::listitem)">
          <xsl:choose>
              <xsl:when test="current-grouping-key()">
                  <xsl:for-each-group select="current-group()" group-adjacent="@class">
                      <xsl:element name="{current-grouping-key()}">
                          <xsl:apply-templates select="current-group()"/>
                      </xsl:element>                          
                  </xsl:for-each-group>
              </xsl:when>
              <xsl:otherwise>
                  <xsl:apply-templates select="current-group()"/>
              </xsl:otherwise>
          </xsl:choose>
      </xsl:for-each-group>

см. https://xsltfiddle.liberty -development.net / gWmuiJK / 1 , для полного решения XSLT 2 вам, конечно, необходимо заменить объявление xsl:mode шаблоном преобразования идентификаторов (вы уже Ваш опубликованный код).

0 голосов
/ 05 сентября 2018

Поскольку шаблон для listitem соответствует каждому отдельному элементу, а ваш fo-each-group применяется только к . (текущий элемент), это приводит к переносу каждого элемента.

Вам нужно больше подправить выбор.

Ваш шаблон нужно применять только к listitem, чей предшественник не listitem (возможно, listitem с тем же классом). Внутри шаблона вам нужно открыть тег ol, а затем использовать другое правило для вывода содержимого элемента и всех наследников, пока они listitem.

Проверьте оси XPath: https://www.w3schools.com/xml/xpath_axes.asp

Должно быть возможно сделать что-то вроде:

<xsl:template match="listitem[preceding-sibling::self[position()=1 and name() != 'listitem']]">
    <ol>
    <xsl:apply-templates mode="inlist" select="."/>
    </ol>
</xsl:template>
<xsl:template match="listitem" mode="inlist">
    <li><xsl:value-of select="."/></li>
    <xsl:apply-templates  select="following-sibling::self[position() = 1 and name() = 'listitem']" mode="inlist"/>
</xsl:template>
...