使用XSLT的两列表

时间:2013-05-03 07:34:29

标签: xslt xmltable

以下是我正在处理的XML数据的一小部分

<?xml version="1.0" encoding="utf-16"?>
<ScorecardSummary>
  <DivisionSummary>
    <DivisionName>
      <string> SYSTEM</string>
    </DivisionName>
    <ScorecardSummaryByDivision>
      <ScorecardSummaryByKPI>
        <Header>
          <string>Committed Time of Arrival</string>
          <string>Goal</string>
          <string>1D</string>
          <string>7D</string>
          <string>QTD</string>
          <string>YTD</string>
          <string>YTD Event Cars</string>
        </Header>
        <Data>
          <ScorecardContract>
            <TypeName>System</TypeName>
            <Goal>68</Goal>
            <GoalWarning>64.6</GoalWarning>
            <TotalCountYear>1234</TotalCountYear>
            <Value1D>79</Value1D>
            <Value7D>79.2</Value7D>
            <ValueQTD>79.1</ValueQTD>
            <ValueYTD>73.3</ValueYTD>
          </ScorecardContract>
          <ScorecardContract>
            <TypeName>AG</TypeName>
            <Goal>68</Goal>
            <GoalWarning>64.6</GoalWarning>
            <TotalCountYear>1111</TotalCountYear>
            <Value1D>80.9</Value1D>
            <Value7D>78.7</Value7D>
            <ValueQTD>78.4</ValueQTD>
            <ValueYTD>69.7</ValueYTD>
          </ScorecardContract>

这是产生表格的XSL的一小部分:

<xsl:template match="ScorecardSummary/DivisionSummary/DivisionName">
  <h1>
    <xsl:value-of select="current()/string"/>
  </h1>
</xsl:template>

<xsl:template match="ScorecardSummaryByDivision">
  <xsl:apply-templates select="current()/ScorecardSummaryByKPI"/>
</xsl:template>

<xsl:template match="ScorecardSummaryByKPI">
  <table border="1" cellspacing="0" cellpadding="5">
    <tr>
      <xsl:choose>
        <xsl:when test="count(preceding-sibling::ScorecardSummaryByKPI) mod 6 &lt; 4">
          <td>
            <table border="1" cellspacing="0" cellpadding="5">
              <xsl:apply-templates select="Header"/>
              <xsl:apply-templates select="Data"/>
            </table>
          </td>
        </xsl:when>
        <xsl:otherwise>
          <td>
            <table border="1" cellspacing="0" cellpadding="5">
              <xsl:apply-templates select="Header"/>
              <xsl:apply-templates select="Data"/>
            </table>
          </td>
        </xsl:otherwise>
      </xsl:choose>
    </tr>
  </table>
</xsl:template>

XSL重复生成6个表:

1  
2  
3  
4  
5  
6  

1  
2  
3  
4  
5  
6  

但我想这样订购:

1 4  
2 5  
3 6  

1 4  
2 5  
3 6  

等等。我尝试使用此检查,但它不起作用。

count(preceding-sibling::ScorecardSummaryByKPI) mod 6 &lt; 4

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:6)

<强>解释

您的表每行必须有两个<td>(如果您想要两列)。您的XSLT只生成一个。

解决方案是对列表的一半进行交互,每次迭代生成两个<td>

首先我要定义表的大小。例如:

  <xsl:param name="size" select="count(catalog/cd)"/>

然后只迭代它的一半($size div 2)。如果输入列表可以包含非偶数个元素,则必须舍入该数字:ceiling($size div 2)(向上舍入以捕获最后一个元素)

      <xsl:for-each select="catalog/cd[ceiling($size div 2) &gt;= position()]">

在每次迭代中,首先渲染一个元素:

        <td><xsl:value-of select="title"/></td>

然后从表格的后半部分渲染一个合适的元素(offset是之前定义的数字:ceiling($size div 2)表格的一半大小)

        <td><xsl:value-of select="following::cd[ceiling($size div 2)]/title"/></td>

您可以将元素渲染包装在单独的模板中,以避免重复代码。

工作示例

使用W3C XSL TryIt(http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog)检查此转换示例:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <xsl:param name="size" select="count(catalog/cd)"/>
  <html>
  <body>
  <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Title</th>
        <th>Title</th>
      </tr>
      <xsl:for-each select="catalog/cd[ceiling($size div 2) &gt;= position()]">
      <tr>
        <td><xsl:value-of select="title"/></td>
        <td><xsl:value-of select="following::cd[ceiling($size div 2)]/title"/></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

它将CD目录(在上面的示例链接中给出)分成两列。

答案 1 :(得分:0)

也许这就是你要找的东西: (这只显示了这个想法,你必须根据你的意见进行调整。)

 <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/" >
        <xsl:apply-templates select="//t[count(preceding-sibling::t) &lt; 3]" mode="tables" />

    </xsl:template>
    <xsl:template match="t" >
        {<xsl:value-of select="text()"/>}
    </xsl:template>

    <xsl:template match="t" mode="tables">
        <table border="1">
            <tr>
                <td>
                    <table border="1" >
                        <xsl:apply-templates select="." />
                    </table>
                </td>
                <td>
                    <table border="1">
                        <xsl:apply-templates select="following-sibling::t[count(preceding-sibling::t) = count(current()/preceding-sibling::t) +3]" />
                    </table>
                </td>
            </tr>
        </table>
    </xsl:template>
</xsl:stylesheet>

使用这个简短的测试输入xml:

<?xml version="1.0" encoding="utf-8"?>
<xml>
    <tables>
        <t>1</t>
        <t>2</t>
        <t>3</t>
        <t>4</t>
        <t>5</t>
        <t>6</t>
    </tables>
</xml>

它将生成此输出:

<?xml version="1.0"?>
<table xmlns="http://www.w3.org/1999/xhtml" border="1">
  <tr>
    <td>
      <table border="1">
        {1}
    </table>
    </td>
    <td>
      <table border="1">
        {4}
    </table>
    </td>
  </tr>
</table><table xmlns="http://www.w3.org/1999/xhtml" border="1">
  <tr>
    <td>
      <table border="1">
        {2}
    </table>
    </td>
    <td>
      <table border="1">
        {5}
    </table>
    </td>
  </tr>
</table><table xmlns="http://www.w3.org/1999/xhtml" border="1">
  <tr>
    <td>
      <table border="1">
        {3}
    </table>
    </td>
    <td>
      <table border="1">
        {6}
    </table>
    </td>
  </tr>
</table>