与约束相邻的组?

发布于 2024-11-18 22:22:04 字数 3922 浏览 1 评论 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>

这部分有效,但由于我在两种类型的相邻组中都有“Bind”标签,因此我需要能够修改组相邻键,以便“StepGroup”仅“Binds” ' 包含在元素具有 'Step type' 标签的情况下,对于 'BoxGroup' 仅包含 'Binds',其中前一个元素具有 'Box type' 标签。我尝试了一些方法,但都产生了很好的错误消息,所以我希望有人能在这里指出正确的方向。

I'm having an issue while using group-adjacent. Below a simplified XML snippet :

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

What I like to get after final transformation is something as below :

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

Or, to make it a bit textual : All 'bstep' type of tags and 'bind' tags that are adjacent to each other should be grouped in a StepGroup Element, and also all 'bblock' type of tags that are adjacent, including Bind tags, should be grouped in a 'BoxGroup' element.

I used following xslt (only partly shown) :

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

This works partly, but as I have 'Bind' tags in both types of adjacent groups I need to be able to modify the group-adjacent keys so that for the 'StepGroup' only 'Binds' are included where the element has a 'Step type' tag, and for the 'BoxGroup' only 'Binds' where the previous element has a 'Box type' tag. I've tried some things but all resulting in nice error messages, so I hope someone can point me in the right direction here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

睫毛溺水了 2024-11-25 22:22:04

我不完全理解你的要求,这是一些部分解决方案

<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 内部的分组。也许您可以更详细地解释这一点,或者您可以自己修复该部分。

I don't fully understand your requirements, here is some partial solution

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

[edit]
Here is an adaption of the first stylesheet that should do the first level of grouping as you asked for:

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

When I apply that with Saxon 9 to your input document I get

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

I realize this is not yet a final solution but I have so far not understood what defines the grouping inside of a BoxGroup. Maybe you can explain that in more detail or you can fix that part yourself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文