[xsl] question on EXSLT data partitioning

Subject: [xsl] question on EXSLT data partitioning
From: Hermann Stamm-Wilbrandt <STAMMW@xxxxxxxxxx>
Date: Tue, 19 Oct 2010 17:02:30 +0200
Hello,

yesterday I was asked by a colleague on data partitioning.
He wanted to partition 100000s of Entities in blocks of 1000
for sending a single Database update for 1000 entities.

Below is the simplified input, partition size is N=3 and the
requested output. Below that is the solution I provided.

Here are my questions:
* can this task be done without recursion in EXSLT?
  [the colleage did not like the idea of doing the partitioning with
   just XPath (1<=position()<=1000, 1001<=position()<=2000, ...)
   because of the 6 digit number of entities]
* is the conversion of Entity to argument by apply-templates
  the way to go?


Input:
<root>
  <data>
    <Entity>1</Entity>
    <Entity>2</Entity>
    <Entity>3</Entity>
    <Entity>4</Entity>
    <Entity>5</Entity>
    <Entity>6</Entity>
    <Entity>7</Entity>
    <Entity>8</Entity>
    <Entity>9</Entity>
    <Entity>10</Entity>
  </data>
</root>

Output:
<all>
  <arguments>
    <argument>1</argument>
    <argument>2</argument>
    <argument>3</argument>
  </arguments>
  <arguments>
    <argument>4</argument>
    <argument>5</argument>
    <argument>6</argument>
  </arguments>
  <arguments>
    <argument>7</argument>
    <argument>8</argument>
    <argument>9</argument>
  </arguments>
  <arguments>
    <argument>10</argument>
  </arguments>
</all>

Solution:
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  xmlns:exslt="http://exslt.org/common";
  xmlns:func="http://exslt.org/functions";
  xmlns:my="urn:my"
  exclude-result-prefixes="exslt func my"
>
  <xsl:output omit-xml-declaration="yes" />

  <xsl:variable name="N" select="3"/>

  <xsl:template match="Entity">
    <argument><xsl:value-of select="."/></argument>
  </xsl:template>

  <func:function name="my:partition">
    <xsl:param name="entities"/>

    <xsl:choose>
      <xsl:when test="count($entities) &lt;= $N">
        <func:result>
          <arguments>
            <xsl:apply-templates select="$entities"/>
          </arguments>
        </func:result>
      </xsl:when>
      <xsl:otherwise>
        <func:result>
          <arguments>
            <xsl:apply-templates select="$entities[position() &lt;= $N]"/>
          </arguments>

          <xsl:copy-of select="my:partition($entities[position() > $N])"/>
        </func:result>
      </xsl:otherwise>
    </xsl:choose>

  </func:function>

  <xsl:template match="/">
    <xsl:variable name="args" select="my:partition(/root/data/Entity)"/>

    <all><xsl:copy-of select="exslt:node-set($args)"/></all>
  </xsl:template>

</xsl:stylesheet>



Mit besten Gruessen / Best wishes,

Hermann Stamm-Wilbrandt
Developer, XML Compiler, L3
Fixpack team lead
WebSphere DataPower SOA Appliances
----------------------------------------------------------------------
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Geschaeftsfuehrung: Dirk Wittkopp
Sitz der Gesellschaft: Boeblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294

Current Thread