简体   繁体   中英

HTML table: Expand rowspan and colspan values as entries to validate table using XSLt

I hope you have a beautiful day. I'm creating an XSLT code to validate html table is properly structured or not. To validate the table, first I have to expand rowspan and colspan values as each entries "td" in respective rows. Finally, I will check each rows "td" count against "cols" count.

My HTML table is

<table-wrap id="tbl1" position="float">
            <label>Table 1</label>
            <caption>
                <p></p>
            </caption>
            <alternatives>
                <graphic xmlns:xlink="http://www.w3.org/1999/xlink"/>
                <table frame="hsides">
                    <colgroup>
                        <col align="left"/>
                        <col align="left"/>
                        <col align="left"/>
                        <col align="left"/>
                        <col align="left"/>
                        <col align="left"/>
                        <col align="left"/>
                    </colgroup>
                    <thead>
                        <tr>
                            <th rowspan="2" align="left">1</th>
                            <th colspan="5" align="center">2</th>
                            <th rowspan="2" align="center">3</th>
                        </tr>
                        <tr>
                            <th align="center">4</th>
                            <th align="center">5</th>
                            <th align="center">6</th>
                            <th align="center">7</th>
                            <th align="center">8</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>9</td>
                            <td rowspan="2">10</td>
                            <td>11</td>
                            <td>12</td>
                            <td>13</td>
                            <td>14</td>
                            <td rowspan="2">15</td>
                        </tr>
                        <tr>
                            <td>16</td>
                            <td>17</td>
                            <td>18</td>
                            <td>19</td>
                            <td>20</td>
                        </tr>
                        <tr>
                            <td>21</td>
                            <td colspan="2">22</td>
                            <td rowspan="2">23</td>
                            <td colspan="2">24</td>
                            <td>25</td>
                        </tr>
                        <tr>
                            <td>26</td>
                            <td>27</td>
                            <td>28</td>
                            <td>29</td>
                            <td>30</td>
                            <td>31</td>
                        </tr>
                        <tr>
                            <td rowspan="2">32</td>
                            <td colspan="2">33</td>
                            <td>34</td>
                            <td colspan="2">35</td>
                            <td rowspan="2">36</td>
                        </tr>
                        <tr>
                            <td rowspan="2">37</td>
                            <td>38</td>
                            <td>39</td>
                            <td>40</td>
                            <td>41</td>
                        </tr>
                    </tbody>
                </table>
            </alternatives>
        </table-wrap>

my XSLT code is

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="table">
  <table>
    <xsl:apply-templates select="thead"/>
    <xsl:apply-templates select="tbody"/>
  </table>
</xsl:template>

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

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

<xsl:template match="tr">
  <xsl:variable name="current-row" select="position()"/>
  <xsl:for-each select="td[@rowspan > 1]">
    <xsl:variable name="current-col" select="position()"/>
    <xsl:variable name="rowspan-value" select="@rowspan"/>
    <xsl:for-each select="1 to $rowspan-value">
      <xsl:variable name="next-row" select="$current-row + (position() - 1)"/>
      <xsl:variable name="col-value" select="."/>
      <xsl:variable name="colspan-value" select="@colspan"/>
      <xsl:for-each select="1 to $colspan-value">
        <xsl:variable name="col-position" select="$current-col + (position() - 1)"/>
        <xsl:variable name="row-tag" select="count(../preceding-sibling::tr[position() lt $next-row]) + 1"/>
        <xsl:variable name="col-tag" select="count(./td[position() lt $col-position]) + 1"/>
        <xsl:element name="td">
          <xsl:value-of select="$col-value"/>
        </xsl:element>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:for-each>
  <xsl:for-each select="td[@colspan > 1]">
    <xsl:variable name="current-col" select="position()"/>
    <xsl:variable name="colspan-value" select="@colspan"/>
    <xsl:for-each select="1 to $colspan-value">
      <xsl:variable name="col-position" select="$current-col + (position() - 1)"/>
      <xsl:variable name="col-value" select="."/>
      <xsl:variable name="row-tag" select="count(../preceding-sibling::tr) + 1"/>
      <xsl:variable name="col-tag" select="count(./td[position() lt $col-position] + 1)"/>
            <xsl:element name="td">
        <xsl:value-of select="$col-value"/>
      </xsl:element>
    </xsl:for-each>
  </xsl:for-each>
  <xsl:for-each select="td">
    <xsl:if test="not(@rowspan) and not(@colspan)">
      <xsl:copy-of select="."/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

I want the output like <th rowspan="2" align="left">1</th> and <th rowspan="2" align="center">3</th> as <th align="left">1< /th> and <th align="center">3</th> in first and second rows of <tr>

Similarly, <td colspan="2">22</td> as <td>22</td><td>22</td> two td tags based on value mentioned in it

Expected output:

<table-wrap id="tbl1" position="float">
            <label>Table 1</label>
            <caption>
                <p></p>
            </caption>
            <alternatives>
                <graphic xmlns:xlink="http://www.w3.org/1999/xlink"/>
                <table frame="hsides">
                    <colgroup>
                        <col/>
                        <col/>
                        <col/>
                        <col/>
                        <col/>
                        <col/>
                        <col/>
                    </colgroup>
                    <thead>
                        <tr>
                            <th>1</th>
                            <th>2</th>
                            <th>2</th>
                            <th>2</th>
                            <th>2</th>
                            <th>2</th>
                            <th>3</th>
                        </tr>
                        <tr>
                            <th>1</th>
                            <th>4</th>
                            <th>5</th>
                            <th>6</th>
                            <th>7</th>
                            <th>8</th>
                            <th>3</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>9</td>
                            <td>10</td>
                            <td>11</td>
                            <td>12</td>
                            <td>13</td>
                            <td>14</td>
                            <td>15</td>
                        </tr>
                        <tr>
                            <td>16</td>
                            <td>10</td>
                            <td>17</td>
                            <td>18</td>
                            <td>19</td>
                            <td>20</td>
                            <td>15</td>
                        </tr>
                        <tr>
                            <td>21</td>
                            <td>22</td>
                            <td>22</td>
                            <td>23</td>
                            <td>24</td>
                            <td>24</td>
                            <td>25</td>
                        </tr>
                        <tr>
                            <td>26</td>
                            <td>27</td>
                            <td>23</td>
                            <td>28</td>
                            <td>29</td>
                            <td>30</td>
                            <td>31</td>
                        </tr>
                        <tr>
                            <td>32</td>
                            <td>33</td>
                            <td>33</td>
                            <td>34</td>
                            <td>35</td>
                            <td>35</td>
                            <td>36</td>
                        </tr>
                        <tr>
                            <td>37</td>
                            <td>32</td>
                            <td>38</td>
                            <td>39</td>
                            <td>40</td>
                            <td>41</td>
                            <td>36</td>
                        </tr>
                        <tr>
                        <td>37</td>
                        </tr>
                    </tbody>
                </table>
            </alternatives>
        </table-wrap>

To give you a start using xslt 2.0 :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  >
  <xsl:output indent="yes"/>
  
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="table">
    <xsl:variable name="colcount" select=" count(colgroup/col)"/>
    <table>
      <xsl:apply-templates>
        <xsl:with-param name="colcount" select="$colcount" />
      </xsl:apply-templates>
    </table>
  </xsl:template>

  <xsl:template match="thead|tbody">
    <xsl:param name="colcount"/>
    <xsl:copy>
      <xsl:variable name="entryCheck" as="element()*">
        <xsl:apply-templates select="tr"/>
      </xsl:variable>
      <xsl:variable name="entryCountCheck"      select="count($entryCheck)"/>
      <xsl:variable name="entryCountShouldBe"   select="$colcount * count(tr)"/>
      <xsl:attribute name="entryCountShouldBe"  select="$entryCountShouldBe"/>
      <xsl:attribute name="entryCountCheck"     select="$entryCountCheck"/>
      <xsl:attribute name="isVald"              select="$entryCountShouldBe=$entryCountCheck"/>
      <xsl:copy-of select="$entryCheck"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="tr">
    <xsl:for-each select="*">
      <xsl:variable name="current-col-name" select="local-name()"/>
      <xsl:variable name="current-col-pos"  select="position()"/>
      <xsl:variable name="col-value"        select="text()"/>
      <xsl:variable name="rowspan-value"    select="if(@rowspan) then @rowspan else 1"/>
      <xsl:variable name="colspan-value"    select="if(@colspan) then @colspan else 1"/>
      <xsl:for-each select="1 to $rowspan-value">
        <xsl:for-each select="1 to $colspan-value">
          <xsl:element name="{$current-col-name}">
            <xsl:value-of select="$col-value"/>
          </xsl:element>
        </xsl:for-each>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

will give you this result:

<table-wrap id="tbl1" position="float">
   <label>Table 1</label>
   <caption>
      <p/>
   </caption>
   <alternatives>
      <graphic xmlns:xlink="http://www.w3.org/1999/xlink"/>
      <table xmlns:xs="http://www.w3.org/2001/XMLSchema">
         <colgroup>
            <col align="left"/>
            <col align="left"/>
            <col align="left"/>
            <col align="left"/>
            <col align="left"/>
            <col align="left"/>
            <col align="left"/>
         </colgroup>
         <thead entryCountShouldBe="14" entryCountCheck="14" isVald="true">
            <th>1</th>
            <th>1</th>
            <th>2</th>
            <th>2</th>
            <th>2</th>
            <th>2</th>
            <th>2</th>
            <th>3</th>
            <th>3</th>
            <th>4</th>
            <th>5</th>
            <th>6</th>
            <th>7</th>
            <th>8</th>
         </thead>
         <tbody entryCountShouldBe="42" entryCountCheck="43" isVald="false">
            <td>9</td>
            <td>10</td>
            <td>10</td>
            <td>11</td>
            <td>12</td>
            <td>13</td>
            <td>14</td>
            <td>15</td>
            <td>15</td>
            <td>16</td>
            <td>17</td>
            <td>18</td>
            <td>19</td>
            <td>20</td>
            <td>21</td>
            <td>22</td>
            <td>22</td>
            <td>23</td>
            <td>23</td>
            <td>24</td>
            <td>24</td>
            <td>25</td>
            <td>26</td>
            <td>27</td>
            <td>28</td>
            <td>29</td>
            <td>30</td>
            <td>31</td>
            <td>32</td>
            <td>32</td>
            <td>33</td>
            <td>33</td>
            <td>34</td>
            <td>35</td>
            <td>35</td>
            <td>36</td>
            <td>36</td>
            <td>37</td>
            <td>37</td>
            <td>38</td>
            <td>39</td>
            <td>40</td>
            <td>41</td>
         </tbody>
      </table>
   </alternatives>
</table-wrap>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM