How to avoid O (n ^ 2) complexity when grouping records in XSLT?

I often run into performance issues when XSL converts large amounts of data to HTML. This data is usually just a couple of very large tables of approximately this form:

<table>
  <record>
    <group>1</group>
    <data>abc</abc>
  </record>
  <record>
    <group>1</group>
    <data>def</abc>
  </record>
  <record>
    <group>2</group>
    <data>ghi</abc>
  </record>
</table>

During the conversion, I want to visually group records like this

+--------------+
| Group 1      |
+--------------+
|   abc        |
|   def        |
+--------------+
| Group 2      |
+--------------+
|   ghi        |
+--------------+

This stupid implementation is this (from http://exslt.org . The actual implementation is a little different, it's just an example)

<xsl:for-each select="set:distinct(/table/record/group)">
  <xsl:variable name="group" select="."/>

  <!-- This access needs to be made faster : -->
  <xsl:for-each select="/table/record[group = $group]">
    <!-- Do the table stuff -->
  </xsl:for-each>
</xsl:for-each>

, O(n^2). , . , , , 5000. 50 . , , O(n^3)

:

  • Java , . XSLT, .
  • , , Xerces/Xalan/Exslt,
  • - /table/record/group
  • , <xsl:apply-templates/> , <xsl:for-each/>.

, O(n^2)?

+5
4

Muenchian XSLT 1.0 - :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kGroupByVal" match="group" use="."/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match=
  "group
      [generate-id()
      =
       generate-id(key('kGroupByVal', .)[1])
      ]">
  <group gid="{.}">
   <xsl:apply-templates select="key('kGroupByVal', .)/node()"/>
  </group>
 </xsl:template>
 <xsl:template match="group/text()"/>
</xsl:stylesheet>

( XML-!!!) ,

3 record 80 .

, 1000 record , 136 .

10000 record 284 .

100000 record 1667 .

.

( ) , Muenchian XSLT 1.0.

+4

( ), , . , . O (n) .

+4

:

for every [group] record
  for every [data] record
    // actions

,

 for every [record]
       take [data]
       take [group]
       add [data] to [group]

.

, O (n)

+2

- xsl: XSLT 2.0 Muenchian XSLT 1.0. (n * log (n)).

"/table/record[group = $group]" key().

XSLT- , Saxon-EE, , , .

+2

All Articles