Search code examples
htmlxmlxslt

XSLT parsing a HTML table: need only top level tr not children


I'm transforming a table in XML via XSLT to create tabs with cards under each, like an tab accordion with cards for each tab:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="messin-table.xsl"?>
<table class="messin-table">
        <thead>
            <tr>
                <th>Accordion Heading</th>
                <th>Name, Blurb and image</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td class="heading" colspan="3">Staff</td>
                <tr>
                    <td>
                        <p>head 1</p>
                    </td>
                    <td><p>body 1</p></td>
                    <td>blurb 1</td>
                    <td><p><img src="img/SBU-logo.png" /></p></td>
                </tr>
                <tr>
                    <td>
                        <p>head 2</p>
                    </td>
                    <td><p>body 2</p></td>
                    <td>blurb 2</td>
                    <td><p><img src="img/SBU-logo.png" /></p></td>
                </tr>
                <tr>
                    <td>
                        <p>head 6</p>
                    </td>
                    <td><p>body 9</p></td>
                    <td>blurb 9</td>
                    <td><p><img src="img/SBU-logo.png" /></p></td>
                </tr>
            </tr>
            <tr>
                <td class="heading" colspan="3">Faculty</td>
                <tr>
                    <td>
                        <p>head 4</p>
                    </td>
                    <td><p>body 4</p></td>
                    <td>blurb 4</td>
                    <td><p><img src="img/SBU-logo.png" /></p></td>
                </tr>
                <tr>
                    <td>
                        <p>head 7</p>
                    </td>
                    <td><p>body 7</p></td>
                    <td>blurb 7</td>
                    <td><p><img src="img/SBU-logo.png" /></p></td>
                </tr>
                <tr>
                    <td>
                        <p>head 12</p>
                    </td>
                    <td><p>body 12</p></td>
                    <td></td>
                    <td><p><img src="img/SBU-logo.png" /></p></td>
                </tr>
            </tr>
            <tr>
                <td class="heading" colspan="3">Support</td>
                <tr>
                    <td>
                        <p>head 19</p>
                    </td>
                    <td><p>body 19</p></td>
                    <td>blurb 19</td>
                    <td><p><img src="img/SBU-logo.png" /></p></td>
                </tr>
                <tr>
                    <td>
                        <p>head 22</p>
                        
                        
                    </td>
                    <td><p>body 22</p></td>
                    <td></td>
                    <td><p><img src="img/SBU-logo.png" /></p></td>
                </tr>
                <tr>
                    <td>
                        <p>head 36</p>
                        
                        
                    </td>
                    <td><p>body 36</p></td>
                    <td></td>
                    <td><p><img src="img/SBU-logo.png" /></p></td>
                </tr>
            </tr>
        </tbody>
    </table>

I have nested loops in my XSL. I need the first loop to only loop the top level tr/td class='heading' to make tabs, and then loop through the inner trs to create the content (cards) under the tabs:

<xsl:stylesheet version="3.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:ou="http://omniupdate.com/XSL/Variables"
                xmlns:fn="http://omniupdate.com/XSL/Functions"
                xmlns:ouc="http://omniupdate.com/XSL/Variables"
                xmlns:date="http://exslt.org/dates-and-times"
                xmlns:str="http://exslt.org/strings"  
                xmlns:dm="http://www.digitalmeasures.com/schema/data"
                xmlns:dmd="http://www.digitalmeasures.com/schema/data-metadata"
                extension-element-prefixes="date str"
                exclude-result-prefixes="xs ou fn ouc">
<section id="wrapper">
                     <div class="content"><!-- Tab links -->
                        <div class="tabs">
                        <xsl:for-each select="tbody/tr">
                        <xsl:variable name="datacountry" select="td[@class='heading']" />
                        <button class='tablinks' data-country='{$datacountry}'  aria-controls='{$datacountry}'>
                              <p data-title="{$datacountry}"><xsl:value-of select="td[1]"/></p></button> 
                        </xsl:for-each>
                        </div>


                    <div class="wrapper_tabcontent">
                    <xsl:for-each select="tbody/tr">
                    <xsl:variable name="country" select="td[@class='heading']" />
                           <div id="{$country}" class="tabcontent" role="tabpanel">
                              <div class="wrap">
                                <xsl:for-each select="tr">

                                <xsl:variable name="cardname" select="./td[1]" />
                                <xsl:variable name="cardheader" select="./td[2]" />
                                <xsl:variable name="cardbody" select="./td[3]" />
                                <xsl:variable name="cardimg" select="./td[4]/p/img" />
                                 <div class="item" style="transition-delay: 75ms;">
                                    <article class="card" tabindex="0">
                                       <a href="#" data-bio="{$cardheader}'s bio">
                                       <div><xsl:copy-of select="$cardimg"/></div>
                                       <header>
                                          <p><xsl:value-of select="$cardname"/></p> 
                                          <p><xsl:value-of select="$cardheader"/></p>
                                       </header>
                                       <div class="byline">
                                          <p class="hide caption">
                                             <xsl:value-of select="$cardbody"/>
                                             </p>
                                       </div>
                                       </a>
                                    </article>
                                 </div>
                                 </xsl:for-each>
                              </div>
                           </div>
                           </xsl:for-each>
                        </div>
                                             </div>
                                          </section>
                                           <div class="modals" role="dialog" aria-modal="true" aria-labelledby="modalTitle">
   <span class="close">x</span>
 </div>
                        <script src="js/jquery-3.6.0.min.js"></script>
                        <script src="js/tabbed-accordion-people.js"></script>
                        </body>
                        </html>
                   </xsl:template>
</xsl:stylesheet>

The output should look like this:

enter image description here

What this is doing instead is ALL trs are being created as tabs. Is there a way to select just the trs right under the tbody? And then, loop through the inner trs to create the content?

The irony is when I test on my local machine this works (I know you all know that pain!).

Thank you!!!


Solution

  • Closing the question: the issue is that the system I'm working in is changing the table on render. Apparently this system doesn't like nested table elements so it changes the code before load to what it THINKS it should be. Thank you everyone and sorry.