Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
858 views
in Technique[技术] by (71.8m points)

xslt 2.0 - Group-adjacent groups all items instead of just the adjacent ones

I have an XML where I want to group some of the items:

    <Topic id="2807" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2808" variant="Release" versionorder="5"/>
    <Topic id="2809" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2813" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2814" variant="Release" versionorder="9"/>
    <Topic id="2815" variant="Release" versionorder="14"/>
    <Topic id="2816" variant="Release" versionorder="12"/>
    <Topic id="2817" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2820" variant="Release" versionorder="5"/>
    <Topic id="2821" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2824" variant="Release" versionorder="5"/>
    <Topic id="2825" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2855" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2875" variant="Release" versionorder="12"/>
    <Topic id="2881" variant="Release" versionorder="17"/>
    <Topic id="2883" variant="Release" versionorder="19"/>  
    <Topic id="2879" variant="Release" versionorder="15"/>
    <Topic id="2885" variant="Release" versionorder="21"/>
    <Topic id="2887" variant="noVariant" versionorder="noVersion"/>

If there are several nodes with variant="Release" in a row, I want to sort just that group using the versionorder attribute. All other nodes must be output in the order they're in now.

Desired result:

    <Topic id="2807" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2808" variant="Release" versionorder="5"/>
    <Topic id="2809" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2813" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2814" variant="Release" versionorder="9"/>
    <Topic id="2816" variant="Release" versionorder="12"/>
    <Topic id="2815" variant="Release" versionorder="14"/>
    <Topic id="2817" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2820" variant="Release" versionorder="5"/>
    <Topic id="2821" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2824" variant="Release" versionorder="5"/>
    <Topic id="2825" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2855" variant="noVariant" versionorder="noVersion"/>
    <Topic id="2875" variant="Release" versionorder="12"/>
    <Topic id="2879" variant="Release" versionorder="15"/>
    <Topic id="2881" variant="Release" versionorder="17"/>
    <Topic id="2883" variant="Release" versionorder="19"/>
    <Topic id="2885" variant="Release" versionorder="21"/>
    <Topic id="2887" variant="noVariant" versionorder="noVersion"/>

I'm trying to use groups to achieve this:

<xsl:template match="Objects">
    <xsl:for-each-group select="Topic[not(@versionorder='noVersion')]" group-adjacent="@variant">
        <xsl:for-each select="current-group()">
        <xsl:sort select="number(@versionorder)"/>
            <xsl:copy>
            <xsl:apply-templates select="@* | node()" xml:space="preserve"/>
            </xsl:copy>
        </xsl:for-each>
    </xsl:for-each-group>
    
    <xsl:for-each select="Topic[@versionorder='noVersion']">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" xml:space="preserve"/>
        </xsl:copy>
    </xsl:for-each>
</xsl:template>

I expect the group-adjacent statement to make 5 groups. Instead it makes a single group and sorts that:

<Topic id="2808" variant="Release" versionorder="5"/>
<Topic id="2820" variant="Release" versionorder="5"/>
<Topic id="2824" variant="Release" versionorder="5"/>
<Topic id="2814" variant="Release" versionorder="9"/>
<Topic id="2816" variant="Release" versionorder="12"/>
<Topic id="2875" variant="Release" versionorder="12"/>
<Topic id="2815" variant="Release" versionorder="14"/>
<Topic id="2815" variant="Release" versionorder="14"/>
<Topic id="2879" variant="Release" versionorder="15"/>
<Topic id="2881" variant="Release" versionorder="17"/>
<Topic id="2883" variant="Release" versionorder="19"/>
<Topic id="2885" variant="Release" versionorder="21"/>

How can I get the desired result?

question from:https://stackoverflow.com/questions/65919730/group-adjacent-groups-all-items-instead-of-just-the-adjacent-ones

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think you want

  <xsl:template match="Objects">
      <xsl:for-each-group select="Topic" group-adjacent="@variant = 'Release'">
          <xsl:choose>
              <xsl:when test="current-grouping-key()">
                  <xsl:apply-templates select="current-group()">
                      <xsl:sort select="xs:decimal(@versionorder)"/>
                  </xsl:apply-templates>
              </xsl:when>
              <xsl:otherwise>
                  <xsl:apply-templates select="current-group()"/>
              </xsl:otherwise>
          </xsl:choose>
      </xsl:for-each-group>
  </xsl:template>

This assumes the identity transformation template is set up as the base template to copy nodes through.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...