Split large table into several smaller tables

前端 未结 3 634
感动是毒
感动是毒 2020-12-20 23:40

I have a problem where a table has 100s of rows. It causes an issue and needs to be split into several smaller tables with fewer rows each.

My html is valid xml as

相关标签:
3条回答
  • 2020-12-20 23:45

    This is the classical XSLT 1.0 solution for such kind of problems:

    <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:param name="prowLimit" select="12"/>
    
        <xsl:variable name="vTable" select="/*"/>
    
     <xsl:template match="node()|@*" name="identity">
         <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
     </xsl:template>
    
     <xsl:template match="tr">
      <xsl:if test="position() mod $prowLimit = 1">
        <table>
          <xsl:copy-of select="$vTable/@*"/>
          <xsl:copy-of select=
          ". | following-sibling::tr[not(position() > $prowLimit -1)]"/>
        </table>
      </xsl:if>
     </xsl:template>
    </xsl:stylesheet>
    
    0 讨论(0)
  • 2020-12-20 23:48

    Here's an XSLT2 solution using for-each-group. To change the number of items per table change the divisor in the group-adjacent attribute. Tested in Oxygen/XML with Saxon 9.2.

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
      exclude-result-prefixes="xs xd"
      version="2.0">
      <xsl:output method="xml" indent="yes"/>
      <xsl:template match="table">
        <xsl:variable name="tblNode" select="."/>
        <xsl:variable name="header"  select="tr[1]"/>
        <xsl:for-each-group select="tr[position() > 1]" group-adjacent="(position()-1) idiv 3">
          <xsl:element name="table">
            <xsl:copy-of select="$tblNode/@*"/>
            <xsl:copy-of select="$header"/>
            <xsl:apply-templates select="current-group()"/>
          </xsl:element>
        </xsl:for-each-group>
      </xsl:template>
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    

    Explanation:

    1. In the "table" template create a variable for the table node itself, so we can copy its attributes later, and a variable containing the first row to be reused as the header.
    2. Use for-each-group to select adjacent sets where the result of "position()-1 idiv 3" gives the same result. For the first three rows this returns 0; for the next three, the result is 1, and so on. The divisor controls how many rows get grouped into each set.
    3. For each set, generate a table element, then copy all of the original table's attributes, followed by the header row, then use the identity template (at the end of the stylesheet) to copy all the rows.

    Note that if you had nested tables inside the rows you'd have to modify this slightly to avoid having the "table" template match the inner tables.

    0 讨论(0)
  • 2020-12-21 00:05

    This XSLT 1.0 stylesheet:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:param name="pMaxRow" select="2"/>
        <xsl:template match="/">
            <html>
                <xsl:apply-templates
                     select="table/tr[(position()-1) mod $pMaxRow = 1]"
                     mode="table"/>
            </html>
        </xsl:template>
        <xsl:template match="node()|@*" name="identity">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="tr" mode="table">
            <table>
                <xsl:apply-templates select="../@*|../tr[1]|.|following-sibling::tr
                                                 [$pMaxRow > position()]"/>
            </table>
        </xsl:template>
    </xsl:stylesheet>
    

    Output:

    <html>
        <table class="..." style="...">
            <tr>
                <td>head 1</td>
                <td>head 2</td>
            </tr>
            <tr>
                <td>col1</td>
                <td>col2</td>
            </tr>
            <tr>
                <td>col1</td>
                <td>col2</td>
            </tr>
        </table>
        <table class="..." style="...">
            <tr>
                <td>head 1</td>
                <td>head 2</td>
            </tr>
            <tr>
                <td>col1</td>
                <td>col2</td>
            </tr>
            <tr>
                <td>col1</td>
                <td>col2</td>
            </tr>
        </table>
        <table class="..." style="...">
            <tr>
                <td>head 1</td>
                <td>head 2</td>
            </tr>
            <tr>
                <td>col1</td>
                <td>col2</td>
            </tr>
            <tr>
                <td>col1</td>
                <td>col2</td>
            </tr>
        </table>
    </html>
    

    Edit: Compact code.

    0 讨论(0)
提交回复
热议问题