2009-07-23 7 views
3

Я пытаюсь перейти от этого вида ввода:Матрица транспозиции в XSLT

<col title="one"> 
    <cell>a</cell> <cell>b</cell> <cell>c</cell> <cell>d</cell> 
</col> 
<col title="two"> 
    <cell>e</cell> <cell>f</cell> <cell>g</cell> 
</col> 

... в этот HTML-вывод с помощью XSLT:

<table> 
    <tr> <th>one</th> <th>two</th> </tr> 
    <tr> <td>a</td> <td>e</td> </tr> 
    <tr> <td>b</td> <td>f</td> </tr> 
    <tr> <td>c</td> <td>g</td> </tr> 
    <tr> <td>d</td>    </tr> 
</table> 

Другими словами, я хочу, чтобы выполнить матричная транспозиция. Я не мог найти простой способ сделать это, вероятно, нет, я думаю; как насчет сложного? Во время поиска в Google я нашел намеки на то, что способ решить это был через рекурсию. Любая идея ценится.

+1

XSLT версии? Платформа? – AnthonyWJones

+0

Имеет ли первый col всегда одинаковое или большее количество ячеек, чем любое другое col? – AnthonyWJones

+0

переменное количество ячеек в столбце. Платформа XSLT 1.0 с EXSLT (Xalan-C или Gnome's libxslt) – niXar

ответ

5

Одним из возможных вариантов является нахождение <col> с большинством клеток, а затем перебрать их в вложенном цикле. Это гарантирует создание структурно обоснованной таблицы HTML.

<!-- this variable stores the unique ID of the longest <col> --> 
<xsl:variable name="vMaxColId"> 
    <xsl:for-each select="/root/col"> 
    <xsl:sort select="count(cell)" data-type="number" order="descending" /> 
    <xsl:if test="position() = 1"> 
     <xsl:value-of select="generate-id()" /> 
    </xsl:if> 
    </xsl:for-each> 
</xsl:variable> 

<!-- and this selects the children of that <col> for later iteration --> 
<xsl:variable name="vIter" select=" 
    /root/col[generate-id() = $vMaxColId]/cell 
" /> 

<xsl:template match="root"> 
    <xsl:variable name="columns" select="col" /> 
    <table> 
    <!-- output the <th>s --> 
    <tr> 
     <xsl:apply-templates select="$columns/@title" /> 
    </tr> 
    <!-- make as many <tr>s as there are <cell>s in the longest <col> --> 
    <xsl:for-each select="$vIter"> 
     <xsl:variable name="pos" select="position()" /> 
     <tr> 
     <!-- make as many <td>s as there are <col>s --> 
     <xsl:for-each select="$columns"> 
      <td> 
      <xsl:value-of select="cell[position() = $pos]" /> 
      </td> 
     </xsl:for-each> 
     </tr> 
    </xsl:for-each> 
    </table> 
</xsl:template> 

<xsl:template match="col/@title"> 
    <th> 
    <xsl:value-of select="." /> 
    </th> 
</xsl:template> 

Применительно к

<root> 
    <col title="one"> 
    <cell>a</cell> <cell>b</cell> <cell>c</cell> <cell>d</cell> 
    </col> 
    <col title="two"> 
    <cell>e</cell> <cell>f</cell> <cell>g</cell> 
    </col> 
</root> 

это производит:

<table> 
    <tr> 
    <th>one</th> <th>two</th> 
    </tr> 
    <tr> 
    <td>a</td> <td>e</td> 
    </tr> 
    <tr> 
    <td>b</td> <td>f</td> 
    </tr> 
    <tr> 
    <td>c</td> <td>g</td> 
    </tr> 
    <tr> 
    <td>d</td> <td></td> 
    </tr> 
</table> 
+0

это именно то, что я бы сделал. Хорошая работа. –

+0

+1. Я боролся с col с максимальным количеством бит. Одной из выдающихся проблем является проблема с отображением HTML, TD без содержимого не получает рендеринг, свопинг cols в оригинальном XML вокруг, и вы поймете, что я имею в виду. – AnthonyWJones

+0

@ AnthonyWJones: Это просто презентационная проблема. * wave hand * :) Разумный современный браузер поймет директиву 'empty-cells: show' CSS. – Tomalak

1

От Сущности:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="html" indent="yes"/> 
<xsl:template match="input"> 
<table border="1"> 
    <xsl:apply-templates select="col[1]/cell"/> 
</table> 
</xsl:template> 

<xsl:template match="cell"> 
    <xsl:variable name="curr-pos" select="position()"/> 
    <tr> 
    <td> 
    <xsl:copy-of select="node()|../following-sibling::col/cell[$curr-pos]/node()"/> 
    </td> 
    </tr> 
</xsl:template> 

</xsl:stylesheet> 

Я ставлю входные теги вокруг XML, чтобы сделать его ближе соответствовать пример я нашел. (приближается).

BTW: Вы можете проверить это, добавив в качестве 2-й линии к вашему XML:

<?xml-stylesheet type="text/xsl" href="NonLinear.xslt"?> 
+0

Это дает вам хорошую часть пути. Можете ли вы получить все остальное? – Kieveli

+0

Это может привести к упорядочению, но не сгенерирует правильный html, сгруппированный в строки. – AnthonyWJones

+0

Он генерирует их в строках, но не в ячейках. Я думаю, что основной вопрос заключался в том, как транспонировать, а не как полностью решить проблему. – Kieveli

Смежные вопросы