Была бы признательна за помощь в том, как на самом деле работают группы - PullRequest
0 голосов
/ 28 ноября 2018

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

Если бы я хотел использовать «соседний с группой», чтобы переместить все последующие элементы одного и того же имени элемента в первыйпредшествующего родного брата данного типа.Это будет выполнимо?Я знаю, как я могу сделать это с рекурсивными шаблонами, и в некоторой степени с ключами в xslt 1.0.Но я не могу заставить группы 2.0 работать на меня.

Допустим, я хочу переместить все элементы фиги в первый предыдущий абзац, учитывая, что между фигурами нет других видов элементов.и предыдущий элемент para, в этом простом xml.

<root>
    <first_lvl>
        <title>First heading</title>
        <para>First para under first heading</para>
        <para>Second para under first heading</para>
        <fig>fig1</fig>
        <fig>fig 2</fig>
        <table>Table A</table>
        <fig>fig 3</fig>
        <para>Third para under first heading</para>
        <para>Fourth para under first heading</para>
        <fig>fig4</fig>
    </first_lvl>
</root>

Желаемый результат:

<root>
    <first_lvl>
        <title>First heading</title>
        <para>First para under first heading</para>
        <para>Second para under first heading
            <fig>fig1</fig>
            <fig>fig 2</fig>
        </para>
        <table>Table A</table>
        <fig>fig 3</fig>
        <para>Third para under first heading</para>
        <para>Fourth para under first heading
            <fig>fig4</fig>
        </para>
    </first_lvl>
</root>

Как настроить группировку, которая заботится о каждом непосредственно следующем элементе fig?1011 *

Это не работает:

<xsl:template match=para[following-sibling::*[1][self::fig]]>
    <xsl:for-each-group select"folowing-sibling::*" group-adjacent="boolean(self::fig)">
        <xsl:apply-templates select="current-group()" mode="move"/>
    </xsl:for-each-group>
</xsl:template>

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

Не повезло, хотя.

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

Что мне здесь не хватает?

1 Ответ

0 голосов
/ 28 ноября 2018

Я бы начал с group-starting-with на этих para, затем с fig, а затем внутри использовал group-adjacent, чтобы идентифицировать только первую группу смежных fig с.С многословностью XSLT, которая выглядит немного запутанной, но выполняет работу, насколько я понимаю, ваши требования:

<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="xml" indent="yes" />

  <xsl:template match="*[para and fig]">
      <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:for-each-group select="*" group-starting-with="para[following-sibling::*[1][self::fig]]">
              <xsl:choose>
                  <xsl:when test="self::para[following-sibling::*[1][self::fig]]">
                      <xsl:variable name="para-head" select="."/>
                      <xsl:for-each-group select="tail(current-group())" group-adjacent="boolean(self::fig)">
                          <xsl:choose>
                              <xsl:when test="position() = 1">
                                  <xsl:copy select="$para-head">
                                      <xsl:apply-templates select="node(), current-group()"/>
                                  </xsl:copy>
                              </xsl:when>
                              <xsl:otherwise>
                                  <xsl:apply-templates select="current-group()"/>
                              </xsl:otherwise>
                          </xsl:choose>
                      </xsl:for-each-group>
                  </xsl:when>
                  <xsl:otherwise>
                      <xsl:apply-templates select="current-group()"/>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / 6qVRKxh

Я взял на себя смелость использовать XSLT 3 вместо 2, но вам просто пришлось бы разобрать преобразование идентичности, объявленное xsl:mode on-no-match="shallow-copy", и убедиться, что вы используете

<xsl:element name="{name($para-head)}" namespace="{namespace-uri($para-head)}">
  <xsl:apply-templates select="$para-head/node(), current-group()"/>
</xsl:element>

вместо XSLTТолько 3 xsl:copy с select:

                              <xsl:copy select="$para-head">
                                  <xsl:apply-templates select="node(), current-group()"/>
                              </xsl:copy>

и вместо функции XPath 3 tail вы используете subsequence например

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

  <xsl:output method="xml" indent="yes" />

  <xsl:template match="*[para and fig]">
      <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:for-each-group select="*" group-starting-with="para[following-sibling::*[1][self::fig]]">
              <xsl:choose>
                  <xsl:when test="self::para[following-sibling::*[1][self::fig]]">
                      <xsl:variable name="para-head" select="."/>
                      <xsl:for-each-group select="subsequence(current-group(), 2)" group-adjacent="boolean(self::fig)">
                          <xsl:choose>
                              <xsl:when test="position() = 1">
                                    <xsl:element name="{name($para-head)}" namespace="{namespace-uri($para-head)}">
                                      <xsl:apply-templates select="$para-head/node(), current-group()"/>
                                    </xsl:element>
                              </xsl:when>
                              <xsl:otherwise>
                                  <xsl:apply-templates select="current-group()"/>
                              </xsl:otherwise>
                          </xsl:choose>
                      </xsl:for-each-group>
                  </xsl:when>
                  <xsl:otherwise>
                      <xsl:apply-templates select="current-group()"/>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

</xsl:transform>

http://xsltransform.hikmatu.com/bFDb2BN

С другой стороны, я не уверен, является ли попытка не использовать xsl:for-each-group, а скорее шаблон, соответствующий para[following-sibling::*[1][self::fig]], а затем потреблять следующий брат или сестру fig s (что можно легко сделать в XSLT 3 с xsl:iterate) не более компактен:

<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="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="para[following-sibling::*[1][self::fig]]">
      <xsl:copy>
          <xsl:apply-templates select="@*, node()"/>
          <xsl:iterate select="following-sibling::*">
              <xsl:choose>
                  <xsl:when test="self::fig">
                      <xsl:copy-of select="."/>
                  </xsl:when>
                  <xsl:otherwise>
                      <xsl:break/>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:iterate>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="fig[preceding-sibling::*[not(self::fig)][1][self::para]]"/>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / 6qVRKxh / 3

...