2011-04-04 31 views
1

我在看一個類似的問題是什麼在這裏XSL:將XML爲有序多列的HTML表格

Transforming List into a 2-D Table

覆蓋但有輕微的皺紋。我的XML沒有任何特定的順序,我想對它進行排序以供顯示。例如我的XML是

<items> 
    <item>A</item> 
    <item>C</item> 
    <item>E</item> 
    <item>B</item> 
    <item>D</item> 
    <!-- ... any number of item nodes ... --> 
<item> 

,我想我的輸出是(這裏我忽略用於說明目的的非命名節點)

<table> 
    <tr> 
     <td>A</td> 
     <td>C</td> 
     <td>E</td> 
    </tr> 
    <tr> 
     <td>B</td> 
     <td>D</td> 
     <td /> 
    </tr> 
</table> 

我立足這一關的XSL是從以上的鏈接(我需要使用XSL 1.0):

<xsl:template match="/*"> 
    <table> 
     <xsl:call-template name="make-columns"> 
      <xsl:with-param name="nodelist" select="item"/> 
     </xsl:call-template> 
    </table> 
</xsl:template> 

<xsl:template name="make-columns"> 
    <xsl:param name="nodelist"/> 
    <xsl:param name="columns-number" select="3"/> 

    <tr> 
     <xsl:apply-templates select="$nodelist[ 
         not(position() > $columns-number) 
         ]"/> 
     <xsl:if test="count($nodelist) &lt; $columns-number"> 
      <xsl:call-template name="empty-cells"> 
       <xsl:with-param name="finish" 
           select="$columns-number - count($nodelist)"/> 
      </xsl:call-template> 
     </xsl:if> 
    </tr> 

    <!-- If some nodes are left, recursively call current 
    template, passing only nodes that are left --> 
    <xsl:if test="count($nodelist) > $columns-number"> 
     <xsl:call-template name="make-columns"> 
      <xsl:with-param name="nodelist" select="$nodelist[ 
            position() > $columns-number 
            ]"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 

<xsl:template match="item"> 
    <td> 
     <xsl:apply-templates/> 
    </td> 
</xsl:template> 

<xsl:template name="empty-cells"> 
    <xsl:param name="finish"/> 
    <td/> 
    <xsl:if test="not($finish = 1)"> 
     <xsl:call-template name="empty-cells"> 
      <xsl:with-param name="finish" select="$finish - 1"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 

我已經嘗試在各種應用程序模板中插入命令,但不起作用。

想法?從評論

傑夫

更新

我想輸出multicolum表 3列,其中的條目按字母順序排列的 垂直

回答

1

這種轉變

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" 
    exclude-result-prefixes="ext"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:param name="pNumCols" select="3"/> 

<xsl:variable name="vNumRows" select= 
     "ceiling(count(/*/*) div $pNumCols)"/> 

<xsl:variable name="vrtfSorted"> 
    <xsl:for-each select="/*/*"> 
    <xsl:sort/> 
    <xsl:copy-of select="."/> 
    </xsl:for-each> 
</xsl:variable> 

<xsl:variable name="vSorted" 
     select="ext:node-set($vrtfSorted)/*"/> 

<xsl:template match="/"> 
    <table> 
    <xsl:apply-templates select= 
    "$vSorted[not(position() > $vNumRows)]"/> 
    </table> 
</xsl:template> 

<xsl:template match="item"> 
    <tr> 
    <xsl:apply-templates select= 
    "(.|following-sibling::*[position() mod $vNumRows =0])/text()"/> 
    </tr> 
</xsl:template> 

<xsl:template match="text()"> 
    <td><xsl:value-of select="."/></td> 
</xsl:template> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<items> 
    <item>A</item> 
    <item>C</item> 
    <item>E</item> 
    <item>B</item> 
    <item>D</item> 
</items> 

產生想要的,正確的結果:

<table> 
    <tr> 
    <td>A</td> 
    <td>C</td> 
    <td>E</td> 
    </tr> 
    <tr> 
    <td>B</td> 
    <td>D</td> 
    </tr> 
</table> 
+0

謝謝!這很好用! – 2011-04-05 00:10:41

+0

@ Jeffrey-Hersh:在所以你應該接受兩個答案中的一個 - @Alejandro和我都提供了正確和很好的答案。要接受答案,請點擊旁邊的綠色複選標記。 – 2011-04-05 01:50:18

1

更新:現在,隨着新的重新解釋,這個樣式表:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
exclude-result-prefixes="msxsl"> 
    <xsl:strip-space elements="*"/> 
    <xsl:param name="pColumns" select="3"/> 
    <xsl:template match="items"> 
     <xsl:variable name="vrtfChilds"> 
      <xsl:for-each select="*"> 
       <xsl:sort/> 
       <xsl:copy-of select="."/> 
      </xsl:for-each> 
     </xsl:variable> 
     <xsl:variable name="vChilds" select="msxsl:node-set($vrtfChilds)/*"/> 
     <xsl:variable name="vRows" 
         select="ceiling(count($vChilds) div $pColumns)"/> 
     <table> 
      <xsl:for-each select="$vChilds[$vRows >= position()]"> 
       <tr> 
        <xsl:call-template name="columns"> 
         <xsl:with-param name="pRows" select="$vRows"/> 
        </xsl:call-template> 
       </tr> 
      </xsl:for-each> 
     </table> 
    </xsl:template> 
    <xsl:template name="columns"> 
     <xsl:param name="pData" select="."/> 
     <xsl:param name="pColumn" select="$pColumns"/> 
     <xsl:param name="pRows" select="0"/> 
     <xsl:if test="$pColumn"> 
      <td> 
       <xsl:apply-templates select="$pData"/> 
      </td> 
      <xsl:call-template name="columns"> 
       <xsl:with-param name="pData" 
        select="$pData/following-sibling::*[$pRows]"/> 
       <xsl:with-param name="pColumn" select="$pColumn - 1"/> 
       <xsl:with-param name="pRows" select="$pRows"/> 
      </xsl:call-template> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

輸出:

<table> 
    <tr> 
     <td>A</td> 
     <td>C</td> 
     <td>E</td> 
    </tr> 
    <tr> 
     <td>B</td> 
     <td>D</td> 
     <td></td> 
    </tr> 
</table> 

注意:對於兩個相變node-set擴展功能。

+0

謝謝,但這並不奏效。雖然它對我指定的XML的順序作爲示例正常工作。但是,比方說,我在XML中的任何位置添加項目 F。 XSL不會按我需要的順序排序(第一行:A C E,第二行:B D F)。 – 2011-04-04 20:55:01

+0

@Jeffrey Hersh:你寫了「不太合適」的_ _還有_「它正常工作」_。我認爲你需要下定決心......如果涉及到一些排序,你應該在你的問題中描述。 – 2011-04-04 21:15:03

+0

對不起,我不清楚。您的解決方案適用於我提出的說明性示例,但它在一般情況下不起作用。一般情況下,我需要什麼。 – 2011-04-04 21:23:37