使用XSLT生成多个动态行的html表

时间:2011-05-23 16:33:52

标签: xml xslt

我想根据XML中的内容动态地在表中创建行。在下面的代码中,我尝试创建一个包含5列的行(<tr>)。填写5列后,我想创建一个新行。

根据以下代码,行只能包含5列。如果我在XML上应用XSL,则会显示错误

  

XSLT编译错误。第574行的'tr'开始标记与'xsl:when'的结束标记不匹配。第578行,第7位。

570:<table>
571:    <xsl:for-each select="/alert/account_links/account_links_info">
572:                <xsl:choose>
573:                <xsl:when test="position() mod 5 = 1">
574:                    <tr>
575:                        <td>
576:                            <xsl:value-of select="account_id"/>
577:                        </td>                           
578:                </xsl:when>
579:                <xsl:when test="position() mod 5 = 0">
580:                    <td>
581:                        <xsl:value-of select="account_id"/>
582:                    </td>
583:                    </tr>
584:                </xsl:when>
585:                <xsl:otherwise>
586:                    <td>
587:                        <xsl:value-of select="account_id"/>
588:                    </td>
589:                </xsl:otherwise>
590:                </xsl:choose>
591:                </xsl:for-each>         
592:            </table>

输入Xml:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<alert>
  <account_links>
    <account_links_info>
      <account_id>1</account_id>
    </account_links_info>
    <account_links_info>
      <account_id>2</account_id>
    </account_links_info>
    <account_links_info>
      <account_id>3</account_id>
    </account_links_info>
    <account_links_info>
      <account_id>4</account_id>
    </account_links_info>
    <account_links_info>
      <account_id>5</account_id>
    </account_links_info>
  </account_links>
</alert>

有人能帮助我如何继续这个吗?

3 个答案:

答案 0 :(得分:7)

试试这个解决方案:

<table>
       <xsl:for-each select="/alert/account_links/account_links_info[position()mod5=1]">
        <xsl:variable name = "current-pos" select="(position()-1) * 5+1"/>
        <tr>
        <xsl:for-each select="../account_links_info[position()&gt;=$current-pos and position() &lt; $current-pos+5]" >
            <td>
                <xsl:value-of select="account_id"/>
            </td>
        </xsl:for-each>
        </tr>           
       </xsl:for-each>         
</table>

(我们的想法是让<tr>输出的外部循环每隔五个account_links_info element运行一次,内部循环填充account_id个值的行。

答案 1 :(得分:2)

XSLT指令在结果树上生成节点,而不是词法的开始和结束标记。输出节点是单个操作,不能将其分成两个操作,每个操作写半个节点。因此,您的想法应该是“输入中我想要在输出中生成节点的每五个节点”,这自然会导致构造如

<xsl:for-each select="*[position() mod 5 = 1]">

不要引诱使用disable-output-escaping。这是毒药。它打破了转换引擎和序列化之间的干净架构边界,这意味着你的样式表无法在任意管道中干净地部署和重用(这就是它在Firefox中不起作用的原因,如果你感兴趣的话在实际后果中。)

答案 2 :(得分:0)

由于您要在不同位置设置<tr></tr>标记,因此必须将它们作为文本输出,以使其保持XSL文件的有效XML。此外,如果</tr>标记是表中的最后一个元素,或者最后一行可能未关闭,则应输出<table> <xsl:for-each select="/alert/account_links/account_links_info"> <xsl:if test="position()mod5=1"> <xsl:text disable-output-escaping="yes">&lt;tr&gt;</xsl:text> </xsl:if> <td> <xsl:value-of select="account_id"/> </td> <xsl:if test="position()mod5=0 or position()=last()"> <xsl:text disable-output-escaping="yes">&lt;/tr&gt;</xsl:text> </xsl:if> </xsl:for-each> </table> 标记:

{{1}}