How to loop through a DITA map and build a two-column table?

Questions about XML that are not covered by the other forums should go here.
antoterrence
Posts: 30
Joined: Sat May 04, 2019 5:55 pm

How to loop through a DITA map and build a two-column table?

Post by antoterrence » Wed Nov 20, 2019 2:35 pm

Hi,
I want to loop through a dita map using XSLT and build a two-column html table.
First cell will contain first or even title and the second cell will contain the odd title.
I tried creating the following XSLT script but it skips the odd title. And it also populates the second cell in a row with the even title.
The

Code: Select all

following-sibling::following-sibling::*[contains(@class, 'map/topicref')][1
] axis is not working. It always returns the current even topicref node.
What am I doing wrong in the script?

Code: Select all

<?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:dita-ot="http://dita-ot.sourceforge.net/ns/201007/dita-ot"
    exclude-result-prefixes="xs dita-ot"
    
    version="2.0">
    <xsl:output method="html" doctype-public="html"></xsl:output>
    <xsl:variable name="msgprefix">DOTX</xsl:variable>
    
    <xsl:variable name="newline"><xsl:text>
</xsl:text></xsl:variable>
    
    <!-- *************************** Command line parameters *********************** -->
    <xsl:param name="OUTEXT" select="'.html'"/><!-- "htm" and "html" are valid values -->
    <xsl:param name="WORKDIR" select="'./'"/>
    
    <xsl:template match="/">
        <xsl:value-of select="$newline"/>
        <html>
            <xsl:value-of select="$newline"/>
            <head>
                <xsl:value-of select="$newline"/>
                <xsl:comment> Sitemap 1.0 </xsl:comment>
                <xsl:value-of select="$newline"/>
            </head>
            <xsl:value-of select="$newline"/>
            <body>
                <xsl:apply-templates/>
                <xsl:value-of select="$newline"/>
            </body>
            <xsl:value-of select="$newline"/>
        </html>
    </xsl:template>
    <xsl:template match="/*[contains(@class, ' map/map ')]">
        <table>
            <thead>
                <tr>
                    <th>hello</th>
                    <th>hello</th>
                </tr>
            </thead>
            <tbody>
                
                <xsl:for-each select="*[contains(@class, 'map/topicref')][position() mod 2 = 0]">
                    
                  <tr>
                      <td style="border;1px solid black">
                          <xsl:call-template name="get-document">
                            <xsl:with-param name="node">
                                <xsl:value-of select="."/>
                            </xsl:with-param>
                            <xsl:with-param name="text">
                                <xsl:value-of select="'first'"/>
                            </xsl:with-param>
                        </xsl:call-template>
                      </td>
                      
                      <td style="border;1px solid black">
                          
                          <xsl:call-template name="get-document">
                              
                            <xsl:with-param name="node">
                                <xsl:value-of select="following-sibling::*[1]"/>
                            </xsl:with-param>
                            <xsl:with-param name="text">
                                <xsl:value-of select="'second'"/>
                            </xsl:with-param>
                          </xsl:call-template>
                      </td> 
                  </tr>

                </xsl:for-each>
            </tbody>
            
        
        </table>
    </xsl:template>
    
    <xsl:template name="get-document">
        <xsl:param name="node"/>
        <xsl:param name="text"/>

            <xsl:variable name="FileWithPath"><xsl:choose>
                <xsl:when test="@copy-to"><xsl:value-of select="$WORKDIR"/><xsl:value-of select="@copy-to"/></xsl:when>
                <xsl:when test="contains(@href,'#')">
                    <xsl:value-of select="$WORKDIR"/>
                    <xsl:value-of select="substring-before(@href,'#')"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$WORKDIR"/>
                    <xsl:value-of select="@href"/>
                </xsl:otherwise></xsl:choose>
            </xsl:variable>
            <xsl:variable name="docpath" select="document($FileWithPath,/)"/>
            
            
            <xsl:if test="$docpath/*[contains(@class,' topic/topic ')]/*[contains(@class,' topic/title ')]">
                <xsl:choose>
                    <xsl:when test="not($docpath/*[contains(@class,' topic/topic ')]/*[contains(@class,' topic/title ')]/text()='Legal Notice') or not($docpath/*[contains(@class,' topic/topic ')]/*[contains(@class,' topic/title ')]/text()='Document Revision History')">
                        <xsl:value-of select="$docpath/*[contains(@class,' topic/topic ')]/*[contains(@class,' topic/title ')]"/>
                    </xsl:when>
                </xsl:choose>
            </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Radu
Posts: 6987
Joined: Fri Jul 09, 2004 5:18 pm

Re: How to loop through a DITA map and build a two-column table?

Post by Radu » Wed Nov 20, 2019 3:49 pm

Hi,

I do not quite understand everything but positions and arrays in XSLT are 1 indexed, so the first element in the array is [1] and the first position() value is 1.
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Radu
Posts: 6987
Joined: Fri Jul 09, 2004 5:18 pm

Re: How to loop through a DITA map and build a two-column table?

Post by Radu » Wed Nov 20, 2019 4:07 pm

Also when you pass a parameter to a template and you want it to be a node set you do it like this:

Code: Select all

<xsl:with-param name="node" select="(following-sibling::*)[1]"/>
and then in the "get-document" template when you want to access stuff from that node instead of stuff like:

Code: Select all

<xsl:value-of select="@copy-to"/>
or

Code: Select all

 <xsl:when test="contains(@href,'#')">
you do this:

Code: Select all

<xsl:value-of select="$node/@copy-to"/>
and:

Code: Select all

 <xsl:when test="contains($node/@href,'#')">
because all the relative xpaths need to be relative to the "node" parameter.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

antoterrence
Posts: 30
Joined: Sat May 04, 2019 5:55 pm

Re: How to loop through a DITA map and build a two-column table?

Post by antoterrence » Wed Nov 20, 2019 5:12 pm

Radu wrote:
Wed Nov 20, 2019 4:07 pm
Also when you pass a parameter to a template and you want it to be a node set you do it like this:

Code: Select all

<xsl:with-param name="node" select="(following-sibling::*)[1]"/>
and then in the "get-document" template when you want to access stuff from that node instead of stuff like:

Code: Select all

<xsl:value-of select="@copy-to"/>
or

Code: Select all

 <xsl:when test="contains(@href,'#')">
you do this:

Code: Select all

<xsl:value-of select="$node/@copy-to"/>
and:

Code: Select all

 <xsl:when test="contains($node/@href,'#')">
because all the relative xpaths need to be relative to the "node" parameter.

Regards,
Radu
Hi Radu,
Thank you so much. That worked. I failed to notice my mistake. Thank you for the guidance and help.

Post Reply