Это решение довольно сложное, и у меня есть ноющее чувство, что может быть лучший способ сделать это, но, похоже, оно работает:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="TABLE">
<tbody>
<xsl:apply-templates select="ROW[1]" />
</tbody>
</xsl:template>
<xsl:template match="ROW">
<xsl:param name="occupiedcols" />
<row>
<xsl:apply-templates select="CELL[1]">
<xsl:with-param name="occupiedcols" select="$occupiedcols" />
</xsl:apply-templates>
</row>
<xsl:apply-templates select="following-sibling::ROW[1]">
<xsl:with-param name="occupiedcols">
<xsl:apply-templates select="CELL[1]" mode="getoccupied">
<xsl:with-param name="occupiedcols" select="$occupiedcols" />
</xsl:apply-templates>
<xsl:text></xsl:text>
</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="CELL">
<xsl:param name="occupiedcols" />
<xsl:param name="col" select="1" />
<xsl:variable name="thiscol" select="$col + string-length(substring-before(substring($occupiedcols,$col,255),'0'))" />
<xsl:element name="entry">
<xsl:attribute name="colname">
<xsl:value-of select="$thiscol" />
</xsl:attribute>
</xsl:element>
<xsl:apply-templates select="following-sibling::CELL[1]">
<xsl:with-param name="occupiedcols" select="$occupiedcols"/>
<xsl:with-param name="col" select="$thiscol + 1" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="CELL" mode="getoccupied">
<xsl:param name="occupiedcols" />
<xsl:param name="col" select="1" />
<xsl:variable name="thiscol" select="$col + string-length(substring-before(substring($occupiedcols,$col,255),'0'))" />
<xsl:choose>
<xsl:when test="contains(substring($occupiedcols,$col,255),'0')">
<xsl:value-of select="translate(substring-before(substring($occupiedcols,$col,255),'0'),'0123456789','-012345678')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate(substring($occupiedcols,$col,255),'123456789','012345678')" />
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="@ROWSPAN - 1" />
<xsl:if test="not(following-sibling::CELL)">
<xsl:value-of select="translate(substring($occupiedcols,$thiscol + 1, 255),'0123456789','0012345678')" />
</xsl:if>
<xsl:apply-templates select="following-sibling::CELL[1]" mode="getoccupied">
<xsl:with-param name="occupiedcols" select="$occupiedcols"/>
<xsl:with-param name="col" select="$thiscol + 1" />
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
Есть одна известная проблема: она сломается, если ячейка занимает более 9 строк. На самом деле это довольно легко адаптировать, если это проблема.
Кроме того, он не поддерживает использование COLSPAN
.
Он работает, передавая строку цифр, детализирующую количество строк, которые все еще имеют ячейку для каждого столбца, поэтому вторая строка получит в вашем примере значение 21020 и вычислит атрибут colname
на основе где 0 являются. Второй проход по каждой строке уменьшает цифры на единицу, но заменяет 0 на ROWSPAN
для каждой ячейки.
В этом решении также предполагается, что ВСЕ ячейки имеют атрибут ROWSPAN
, даже если они охватывают только один. Если это не так, я могу добавить средства поддержки по умолчанию 1
.