-1

I have the below XML (table):

<table-wrap id="tbl4" position="float">
            <label>Table E3</label>
            <caption>
                <p></p>
            </caption>
            <alternatives>
                <graphic xmlns:xlink="http://www.w3.org/1999/xlink"
                         xlink:href="EEMCS-01-2021-001110.tif"/>
                <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="4" 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>37</td>
                            <td>38</td>
                            <td>39</td>
                            <td>40</td>
                            <td>41</td>
                        </tr>
                    </tbody>
                </table>
            </alternatives>
        </table-wrap>

I want to validate missing tr or td in each based on colspan and rowspan I would like to explain colspan and rowspan conditions:

  1. If colspan="2" in a td, it means two column entries are merged (spanned) so the count of td in that row will be decreased
  2. If rowspan="2" in a td, it means two-row entries are merged (spanned) so the count of td in next row will be decreased

Is there is an additional column or row in the table I have to throw it as an error.

BWin
  • 25
  • 5

1 Answers1

0

This is a tough problem, and you have to think quite carefully about edge cases, for example where a cell with colspan="2" partially overlaps a cell with rowspan="2" in the row above. There are many errors possible other than having an additional row or column and I assume you want to catch these too.

There may be faster solutions, but I think the simplest is to have a first pass that creates a temporary data structure of the form

<cell row="1" column="1"/>
<cell row="1" column="2"/>
<cell row="1" column="3"/>

with one entry for each "real" (1 by 1) cell encountered, and then in a second pass check this data structure for discrepancies, e.g. no duplicates (overlapping cells) and no raggedness (max column for all rows must be the same, max row for all columns must be the same).

You'll need to process the rows and columns in the input either using recursion, or if you can use XSLT 3.0 using xsl:iterate, so you can keep track of the current row and column number. Using xsl:iterate it will be something like this:

<xsl:iterate select="tr">
  <xsl:param name="currentRow" select="1"/>
  <xsl:iterate select="td">
     <xsl:param name="currentCol" select="1"/>
     .... (see below)
     <xsl:next-iteration>
       <xsl:with-param name="currentCol" 
             select="$currentCol + (@colspan, 1)[1]"/>
       </xsl:with-param>
     </xsl:next-iteration>
  </xsl:iterate>
  <xsl:next-iteration>
     <xsl:with-param name="currentRow" 
             select="$currentRow + 1"/>
     </xsl:with-param>
  </xsl:next-iteration>
</xsl:iterate>
 

Then the processing for a td is fairly straightforward: you just do

<xsl:for-each select="$currentRow to $currentRow + (@rowspan, 1)[1] - 1">
  <xsl:variable name="row" select="."/>
  <xsl:for-each select="$currentCol to $currentCol + (@colspan, 1)[1] - 1">
    <xsl:variable name="col" select="."/>
    <cell row="{$row}" col="{$col}"/>
  </xsl:for-each>
</xsl:for-each>

Hope this sketch is enough to give you some ideas.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • Thanks, @Michael Kay for the idea. Is there any possible solution to create a dummy table from original by expanding the colspan and rowspan entries so that validation of 'td' across 'tr' is possible – BWin Dec 14 '22 at 04:59
  • Hi @MichaelKay I have tried your code but it throws an error "Error 1 at line 10:38 : The required item type of the context item for the attribute axis is node(), but the supplied expression {.} has item type xs:integer", Please guide me to resolve this `` – BWin Jan 04 '23 at 04:00
  • Yes, sorry, it should be `$td/@colspan` where `$td` is the `td` element. – Michael Kay Jan 04 '23 at 21:34
  • Is there any possible solution in xslt 2.0 because xslt 3.0 is not applicable on my end – BWin Jan 09 '23 at 03:51
  • Sure, it can be done in XSLT 2.0 with recursion - xsl:iterate can always be replaced with a recursive template call. But I'll leave the coding to you. – Michael Kay Jan 09 '23 at 11:35