相邻的组有约束?

时间:2011-07-08 18:51:35

标签: grouping xslt-2.0

使用群组邻居时遇到问题。下面是简化的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>

这部分工作,但由于我在两种类型的相邻组中都有'绑定'标签,我需要能够修改组相邻的键,这样对于'StepGroup',只有'Binds'包含在元素所在的位置一个'Step type'标签,'BoxGroup'只有'Binds',前一个元素有一个'Box type'标签。我尝试了一些东西,但都产生了很好的错误信息,所以我希望有人能指出我正确的方向。

1 个答案:

答案 0 :(得分:0)

我不完全了解您的要求,这里有一些部分解决方案

<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内部的分组。也许你可以更详细地解释一下,或者你可以自己解决这个问题。