2011-04-04 32 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