XSLT中的矩阵转置

niX*_*Xar 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>
Run Code Online (Sandbox Code Playgroud)

...使用XSLT对此HTML输出:

<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>
Run Code Online (Sandbox Code Playgroud)

换句话说,我想执行矩阵转置.我想找不到一个简单的方法,可能没有,我想; 复杂的怎么样?在Google上搜索时,我发现提示解决这个问题的方法是通过递归.任何想法都赞赏.

Tom*_*lak 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>
Run Code Online (Sandbox Code Playgroud)

应用于

<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>
Run Code Online (Sandbox Code Playgroud)

这会产生:

<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>
Run Code Online (Sandbox Code Playgroud)