группа смежная с ограничениями? - PullRequest
0 голосов
/ 08 июля 2011

У меня проблема при использовании группы смежных. Ниже приведен упрощенный фрагмент XML:

<Paras>
<Para tag="Bind">
    <Content>some standalone Bind data</Content>
</Para>
<Para tag="L3">
    <Content>some header data</Content>
</Para>
<Para tag="BStep.n=1">
    <Content>some data</Content>
</Para>
<Para tag="Bind">
    <Content>some data</Content>
</Para>
<Para tag="BStep.n+">
    <Content>some data</Content>
</Para>
<Para tag="BStep.n+">
    <Content>some data</Content>
</Para>
<Para tag="Bind">
    <Content>some data</Content>
</Para>
<Para tag="Bind">
    <Content>some data</Content>
</Para>
<Para tag="L1">
    <Content>some header</Content>
</Para>
<Para tag="BBox.n=1">
    <Content>some data</Content>
</Para>
<Para tag="BBox.n+">
    <Content>some data</Content>
</Para>
<Para tag="Bind">
    <Content>some data</Content>
</Para>
<Para tag="BBox.n+">
    <Content>some data</Content>
</Para>
<Para tag="Bind">
    <Content>some data</Content>
</Para>
<Para tag="L2">
    <Content>some header</Content>
</Para>
</Paras>

То, что я хотел бы получить после финальной трансформации, выглядит так:

<Paras>
<Para tag="Bind">
<Content>some standalone Bind data</Content>
</Para>
<Para tag="L3">
<Content>some header data</Content>
</Para>     
<StepGroup>
        <Steps>
            <Para tag="BStep.n=1">some data</Para>
            <Para tag="Bind">some data</Para>
        </Steps>
        <Steps>
            <Para tag="BStep.n+">some data</Para>
        </Steps>
        <Steps>
            <Para tag="BStep.n+">some data</Para>
            <Para tag="Bind">some data</Para>
            <Para tag="Bind">some data</Para>
        </Steps>
    </StepGroup>
    <Para tag="L1">
        <Content>some header</Content>
    </Para>
    <BoxGroup>
        <Steps>
            <Para tag="BBox.n=1">some data</Para>
            <Para tag="BBox.n+">some data</Para>
            <Para tag="Bind">some data</Para>
        </Steps>
        <Steps>
            <Para tag="BBox.n+">some data</Para>
            <Para tag="Bind">some data</Para>
        </Steps>
    </BoxGroup>
    <Para tag="L2">
        <Content>some header</Content>
    </Para>
</Paras>

Или, чтобы сделать его немного текстовым: все теги типа 'bstep' и теги 'bind', которые находятся рядом друг с другом, должны быть сгруппированы в элемент StepGroup, а также все теги типа 'bblock', которые являются смежными , включая теги Bind, должны быть сгруппированы в элементе BoxGroup.

Я использовал следующий xslt (показан только частично):

<!-- Some data above this left out ... -->
<xsl:for-each-group select="current-group()" group-adjacent="@tag='BStep.boxnmb.n=1'  or @tag='BStep.boxnmb.n+' or @tag='Bind' or @tag='BStep.nobox' ">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<StepGroup>
<!-- do some stuff with group / not included now -->
<xsl:apply-templates select="current-group()"/>
</StepGroup>
</xsl:when>

<xsl:otherwise>
<xsl:for-each-group select="current-group()" group-adjacent="@tag='BBox.n=1'  or @tag='BBox.n+' or @tag='Bind'">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<BoxGroup>
<xsl:apply-templates select="current-group()"/>
</BoxGroup>
</xsl:when>

Это работает частично, но поскольку у меня есть теги 'Bind' в обоих типах смежных групп, мне нужно иметь возможность изменять смежные с группой ключи так, чтобы для 'StepGroup' включались только 'Binds', где элемент имеет тег «Тип шага», и для «BoxGroup» только «Связывает», где предыдущий элемент имеет тег «Тип коробки». Я пробовал кое-что, но все это приводило к хорошим сообщениям об ошибках, поэтому я надеюсь, что кто-то может указать мне правильное направление здесь.

1 Ответ

0 голосов
/ 09 июля 2011

Я не совсем понимаю ваши требования, вот частичное решение

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

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

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

  <xsl:template match="Paras">
    <xsl:copy>
      <xsl:for-each-group select="Para" group-adjacent="matches(@tag, 'BStep|Bind')">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <StepGroup>
              <xsl:for-each-group select="current-group()" group-starting-with="Para[matches(@tag, 'BStep')]">
                <Step>
                  <xsl:apply-templates select="current-group()"/>
                </Step>
              </xsl:for-each-group>
            </StepGroup>
          </xsl:when>
          <xsl:otherwise>
            <xsl:for-each-group select="current-group()" group-adjacent="matches(@tag, 'BBox|Bind')">
              <xsl:choose>
                <xsl:when test="current-grouping-key()">
                  <BoxGroup>
                    <xsl:apply-templates select="current-group()"/>
                  </BoxGroup>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:for-each-group>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

[править] Вот адаптация первой таблицы стилей, которая должна выполнить первый уровень группировки, как вы просили:

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

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

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

  <xsl:template match="Paras">
    <xsl:copy>
      <xsl:for-each-group select="Para" 
        group-adjacent="matches(@tag, 'BStep|Bind') 
                         and (self::Para[matches(@tag, 'BStep')] 
                              or preceding-sibling::*[not(matches(@tag, 'Bind'))][1][self::Para[matches(@tag, 'BStep')]])">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <StepGroup>
              <xsl:for-each-group select="current-group()" group-starting-with="Para[matches(@tag, 'BStep')]">
                <Step>
                  <xsl:apply-templates select="current-group()"/>
                </Step>
              </xsl:for-each-group>
            </StepGroup>
          </xsl:when>
          <xsl:otherwise>
            <xsl:for-each-group select="current-group()" group-adjacent="matches(@tag, 'BBox|Bind')">
              <xsl:choose>
                <xsl:when test="current-grouping-key()">
                  <BoxGroup>
                    <xsl:apply-templates select="current-group()"/>
                  </BoxGroup>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:for-each-group>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Когда я применяю это с Saxon 9 к вашему входному документу, я получаю

<Paras>
   <StepGroup>
      <Step>
         <Para tag="BStep.n=1">
            <Content>some data</Content>
         </Para>
         <Para tag="Bind">
            <Content>some data</Content>
         </Para>
      </Step>
      <Step>
         <Para tag="BStep.n+">
            <Content>some data</Content>
         </Para>
      </Step>
      <Step>
         <Para tag="BStep.n+">
            <Content>some data</Content>
         </Para>
         <Para tag="Bind">
            <Content>some data</Content>
         </Para>
         <Para tag="Bind">
            <Content>some data</Content>
         </Para>
      </Step>
   </StepGroup>
   <Para tag="L1">
      <Content>some header</Content>
   </Para>
   <BoxGroup>
      <Para tag="BBox.n=1">
         <Content>some data</Content>
      </Para>
      <Para tag="BBox.n+">
         <Content>some data</Content>
      </Para>
      <Para tag="Bind">
         <Content>some data</Content>
      </Para>
      <Para tag="BBox.n+">
         <Content>some data</Content>
      </Para>
      <Para tag="Bind">
         <Content>some data</Content>
      </Para>
   </BoxGroup>
   <Para tag="L2">
      <Content>some header</Content>
   </Para>
</Paras>

Я понимаю, что это еще не окончательное решение, но я до сих пор не понял, что определяет группировку внутри BoxGroup. Может быть, вы можете объяснить это более подробно, или вы можете исправить эту часть самостоятельно.

...