Evenly grouped items.

Given the following xml document

<root>
  <a pos="0" total="2"/>
  <a pos="1" total="2"/>

  <a pos="0" total="3"/>
  <a pos="1" total="3"/>
  <a pos="2" total="3"/>

  <a pos="0" total="4"/>
  <a pos="1" total="4"/>
  <a pos="2" total="4"/>
  <a pos="3" total="4"/>
</root>

I need to translate it to

<root>
  <group>
    <a pos="0" total="2"/>
    <a pos="1" total="2"/>
  </group>
  <group>
    <a pos="0" total="3"/>
    <a pos="1" total="3"/>
    <a pos="2" total="3"/>
  </group>
  <group>
    <a pos="0" total="4"/>
    <a pos="1" total="4"/>
    <a pos="2" total="4"/>
    <a pos="3" total="4"/>
  </group>
</root>

using the XSLT 1.0 style sheet.

That is, each element <a>with an attribute @pos 0in the document implicitly starts a group consisting of it, and @total-1 of the following elements <a>. To explain this, in other words, @posdenotes an index (position) based on 0 element in a group of @totaladjacent elements.

I came up with the following stylesheet that works:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

    <xsl:template match="/">
        <xsl:apply-templates select="root" />
    </xsl:template>

    <xsl:template match="root">
        <xsl:apply-templates select="a[@pos=0]" mode="leader"/>
    </xsl:template>

    <xsl:template match="a" mode="leader">
        <group>
            <xsl:apply-templates select="." />
            <xsl:apply-templates select="following-sibling::a[position() &lt;= current()/@total - 1]" />
        </group>
    </xsl:template>

    <xsl:template match="a">
         <xsl:copy-of select="." />
    </xsl:template>

</xsl:stylesheet>

The problem with my solution is that it does those a[@pos=0]“special” ones: for further processing of each element <a>in the intended group, I must separately apply the corresponding template first to the “group leader” and then the rest of the elements in the group.

, - ()

    <xsl:template match="a" mode="leader">
        <group>
            <xsl:apply-templates select=". and following-sibling::a[position() &lt;= current()/@total - 1]" />
        </group>
    </xsl:template>

<xsl:template match="a"> . ( , select: " , & hellip;".)

, , XSLT 1.0, exslt:node-set()? , ​​ , , ( )?


, , , .

+4
1

:

<xsl:apply-templates select=". | following-sibling::a[position() &lt;= current()/@total - 1]" />

P.S. node-set() "".

+1

Source: https://habr.com/ru/post/1661690/


All Articles