Convert XHTML table to LaTeX using XSLT

I am new to XSLT (v1.0) and I cannot convert complex XHTML tables to LaTeX using XSLT.

What I mean when I say complex tables is tables with rows with different number of columns. In other words, td with colspan .

i.e. (xhtml table)

 <table border="1" cellspacing="0" cellpadding="0"> <tr> <td valign="top" width="68" colspan="3"> <p>Values</p> </td> </tr> <tr> <td valign="top" width="68"> <p>95</p> </td> <td valign="top" width="68"> <p>169</p> <p> </p> </td> <td valign="top" width="68"> <p>180</p> <p> </p> </td> </tr> </table> 

What am I doing in the XSL file:

 <xsl:template match="xhtml:table[@border='1']"> <xsl:text>\begin{center}</xsl:text> <xsl:text>\begin{tabular}{</xsl:text> <xsl:for-each select="xhtml:tr[1]/*"> <xsl:text>c</xsl:text> <xsl:if test="position() = last()"> <xsl:text>}&#10;</xsl:text> </xsl:if> </xsl:for-each> <xsl:text>\toprule&#10;</xsl:text> <xsl:for-each select="xhtml:tr"> <xsl:if test="position() != 1"> <xsl:text>\midrule&#10;</xsl:text> </xsl:if> <xsl:if test="position() = 2"> <xsl:text>\midrule&#10;</xsl:text> </xsl:if> <xsl:for-each select="xhtml:td|xhtml:th"> <xsl:if test="name() = 'th'">{\bf </xsl:if> <xsl:apply-templates /> <xsl:if test="name() = 'th'">}</xsl:if> <xsl:if test="position() != last()"> <xsl:text>&amp;</xsl:text> </xsl:if> </xsl:for-each> <xsl:text> \\&#10;</xsl:text> </xsl:for-each> <xsl:text>\bottomrule&#10;</xsl:text> <xsl:text>\end{tabular}&#10;</xsl:text> <xsl:text>\end{center}&#10;</xsl:text> </xsl:template> 

But, as you can see, this code just works for simple tables without the colspan attribute. The code moves around the first tr , and for each td it writes "c". Thus, in the above example, only one column table will be created.

What I want to do is count the number of td and the number of colspans, if it exists, create the correct table with three columns.

Does anyone know how to do this? Thanks in advance.

+6
source share
1 answer

This is easier in XSLT2, but you can use the idiom (//*)[position() &lt;= n] in XSLT 1 to repeat n times. I also fixed your TeX a bit: \bf deprecated since latex2e was released in 1993 :-)


 <table xmlns="http://www.w3.org/1999/xhtml" border="1" cellspacing="0" cellpadding="0"> <tr> <td valign="top" width="68" colspan="3"> <p>Values</p> </td> </tr> <tr> <td valign="top" width="68"> <p>95</p> </td> <td valign="top" width="68"> <p>169</p> <p> </p> </td> <td valign="top" width="68"> <p>180</p> <p> </p> </td> </tr> </table> 

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <xsl:output method="text"/> <xsl:template match="xhtml:table[@border='1']"> <xsl:text>\begin{center}&#10;</xsl:text> <xsl:text>\begin{tabular}{</xsl:text> <xsl:for-each select="xhtml:tr[1]/*"> <xsl:choose> <xsl:when test="@colspan"> <xsl:for-each select="(//*)[position()&lt;=current()/@colspan]">c</xsl:for-each> </xsl:when> <xsl:otherwise>c</xsl:otherwise> </xsl:choose> </xsl:for-each> <xsl:text>}&#10;</xsl:text> <xsl:text>\toprule&#10;</xsl:text> <xsl:for-each select="xhtml:tr"> <xsl:if test="position() != 1"> <xsl:text>\midrule&#10;</xsl:text> </xsl:if> <xsl:if test="position() = 2"> <xsl:text>\midrule&#10;</xsl:text> </xsl:if> <xsl:for-each select="xhtml:td|xhtml:th"> <xsl:if test="self::xhtml:th">\bfseries </xsl:if> <xsl:apply-templates /> <xsl:if test="position() != last()"> <xsl:text>&amp;</xsl:text> </xsl:if> </xsl:for-each> <xsl:if test="position()!=last()"> \\&#10;</xsl:if> </xsl:for-each> <xsl:text>\end{tabular}&#10;</xsl:text> <xsl:text>\end{center}</xsl:text> </xsl:template> </xsl:stylesheet> 

 \begin{center} \begin{tabular}{ccc} \toprule Values \\ \midrule \midrule 95 & 169 & 180 \end{tabular} \end{center} 
+6
source

Source: https://habr.com/ru/post/957147/


All Articles