2014-02-13 35 views
1

所以,我需要使用xslt 1.0创建一个动态表。我看过几篇文章/帖子,但似乎无法将它们放在一起。在很多情况下,会有几个表格单元格为空数据。在其他情况下,会有多个值需要并置到一个单元格中。下面是示例XML:创建一个表(带有XSLT 1.0和连接多个值)

<Document> 
<Records> 
    <User> 
    <Name>User1</Name> 
    <list xid="data.set"> 
     <Data> 
     <Column>2</Column> 
     <Type>Carbs</Type> 
     <RowValue>Oatmeal</RowValue> 
     </Data> 
     <Data> 
     <Column>1</Column> 
     <Type>Protein</Type> 
     <RowValue>sausage</RowValue> 
     <RowValue>eggs</RowValue> 
     <RowValue>turkey</RowValue> 
     </Data> 
    </list> 
    </User> 
    <User> 
    <Name>User2</Name> 
    <list xid="data.set"> 
     <Data> 
     <Type>Vegetables</Type> 
     <Column>8</Column> 
     <RowValue>Squash</RowValue> 
     </Data> 
     <Data> 
     <Column>3</Column> 
     <Type>Sweets</Type> 
     <RowValue>cake</RowValue> 
     <RowValue>cookies</RowValue> 
     </Data> 
     <Data> 
     <Column>5</Column> 
     <Type>Other</Type> 
     </Data> 
     <Data> 
     <Column>6</Column> 
     <Type>Beverage</Type> 
     <RowValue>grape juice</RowValue> 
     </Data> 
    </list> 
    </User> 
    <User> 
    <Name>User4</Name> 
    <list xid="data.set"> 
     <Data> 
      <Column>7</Column> 
      <Type>Fats</Type> 
      <RowValue>cashews</RowValue> 
     </Data> 
     <Data> 
      <Column>8</Column> 
      <Type>Vegetables</Type> 
      <RowValue>Green Beans</RowValue> 
     </Data> 
     <Data> 
      <Column>2</Column> 
      <Type>Carbs</Type> 
      <RowValue>Brown Rice</RowValue> 
     </Data> 
     </list> 
    </User> 
    <User> 
     <Name>User5</Name> 
     <list xid="data.set"> 
     <Data> 
      <Column>3</Column> 
      <Type>Sweets</Type> 
      <RowValue>gummy worms</RowValue> 
     </Data> 
     <Data> 
      <Column>4</Column> 
      <Type>Fruit</Type> 
      <RowValue>apples</RowValue> 
     </Data> 
     </list> 
    </User> 
    <User> 
     <Name>User5</Name> 
     <list xid="data.set"> 
     <Data> 
      <Column>3</Column> 
      <Type>Sweets</Type> 
      <RowValue>gummy worms</RowValue> 
     </Data> 
     <Data> 
      <Column>4</Column> 
      <Type>Fruit</Type> 
      <RowValue>grapes</RowValue> 
     </Data> 
     </list> 
    </User> 
    <User> 
     <Name>User5</Name> 
     <list xid="data.set"> 
     <Data> 
      <Column>3</Column> 
      <Type>Sweets</Type> 
      <RowValue>gummy worms</RowValue> 
     </Data> 
     <Data> 
      <Column>4</Column> 
      <Type>Fruit</Type> 
      <RowValue>grapes</RowValue> 
     </Data> 
     </list> 
    </User> 
</Records> 
</Document> 

编辑:在HTML输出有重复的值在表格单元中时的用户名存在不止一次(见下文)。我想删除每个单元格中存在的重复值,例如“胶粘蠕虫,胶粘蠕虫,胶粘蠕虫”。例如,列出了三个“用户5”。我想保留包含“user5”的每一行,但删除那些行的每个单元格中的重复值。

<table border="1"> 
<thead> 
<tr> 
<th> 
</th> 
<th>Protein</th> 
<th>Carbs</th> 
<th>Sweets</th> 
<th>Fruit</th> 
<th>Other</th> 
<th>Beverage</th> 
<th>Fats</th> 
<th>Vegetables</th> 
</tr> 
<tr> 
<th></th> 
<th>1</th> 
<th>2</th> 
<th>3</th> 
<th>4</th> 
<th>5</th> 
<th>6</th> 
<th>7</th> 
<th>8</th> 
</tr></thead><tbody><tr><th>User1</th> 
<td>sausage, eggs, turkey</td> 
<td>Oatmeal</td> 
<td></td> 
<td></td> 
<td></td> 
<td></td> 
<td></td> 
<td></td> 
</tr> 
<tr><th>User2</th> 
<td></td> 
<td></td> 
<td>cake, cookies</td> 
<td></td> 
<td></td> 
<td>grape juice</td> 
<td></td> 
<td>Squash</td> 
</tr> 
<tr><th>User4</th> 
<td></td> 
<td>Brown Rice</td> 
<td></td> 
<td></td> 
<td></td> 
<td></td> 
<td>cashews</td> 
<td>Green Beans</td> 
</tr> 
<tr><th>User5</th> 
<td></td> 
<td></td> 
<td>gummy worms, gummy worms, gummy worms</td> 
<td>apples, grapes, grapes</td> 
<td></td> 
<td></td> 
<td></td> 
<td></td> 
</tr> 
<tr><th>User5</th> 
<td></td> 
<td></td> 
<td>gummy worms, gummy worms, gummy worms</td> 
<td>apples, grapes, grapes</td> 
<td></td> 
<td></td> 
<td></td> 
<td></td> 
</tr> 
<tr><th>User5</th> 
<td></td> 
<td></td> 
<td>gummy worms, gummy worms, gummy worms</td> 
<td>apples, grapes, grapes</td> 
<td></td> 
<td></td> 
<td></td> 
<td></td> 
</tr> 
</tbody> 
</table> 

这是我非常微弱的努力,试图使这项工作。我是个新手,温柔的请...

<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:key name="food-by-Category" match="Data" use="Column" /> 
<xsl:key name="food-by-Value" match="Columns" use="RowValue" /> 

    <xsl:template match="/Document/Records/User/list[@xid = 'data.set']"> 

<table><tr> 
    <xsl:for-each select="Data[count(. | key('food-by-Category', Column)[1]) = 1]"> 
     <!-- Sort by the Category --> 
     <xsl:sort select="Column" /> 
<td> 
     <xsl:value-of select="Type" /> 
</td> 
</xsl:for-each> 
</tr> 

    <xsl:for-each select="Data[count(. | key('food-by-Category', Column)[1]) = 1]"> 
<tr> 
     <xsl:for-each select="key('food-by-Category', Column)"> 
     <!-- Sort by the item Value --> 
     <xsl:sort select="RowValue" /> 
<td> 
     <xsl:value-of select="RowValue" /> 
</td>  
    </xsl:for-each> 
</tr> 
</xsl:for-each> 
</table> 
    </xsl:template> 
</xsl:stylesheet> 

正如你可以看到它不是分组表头/细胞一起或在有多个< RowValue串接值>。

回答

1

哇。我认为你至少有三个不同的问题值得在那里:

  1. 如何产生独特的列标题;
  2. 如何从稀疏数组中获取数据到表中;
  3. 如何将多个匹配数据项连接成一个单元格。

如果这还不够复杂,你确信这将是重整的最后一个用户的数据(使<Name><list>,而不是一个兄弟姐妹的孩子)。

无论如何,看看下面的样式表:

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

<xsl:key name="data_by_column" match="Data" use="Column" /> 
<xsl:key name="value_by_cell" match="RowValue" use="concat(ancestor::User/Name, '|', preceding-sibling::Column)" /> 

<xsl:template match="/"> 
<table border="1"> 
<thead> 
    <tr> 
     <th/> 
     <!--unique column headers --> 
     <xsl:for-each select="Document/Records/User/list/Data[count(. | key('data_by_column', Column)[1]) = 1]"> 
     <xsl:sort select="Column" data-type="number" order="ascending"/> 
     <th><xsl:value-of select="Type"/></th> 
     </xsl:for-each> 
    </tr> 
    <tr> 
     <th/> 
     <!--unique column headers --> 
     <xsl:for-each select="Document/Records/User/list/Data[count(. | key('data_by_column', Column)[1]) = 1]"> 
     <xsl:sort select="Column" data-type="number" order="ascending"/> 
     <th><xsl:value-of select="Column"/></th> 
     </xsl:for-each> 
    </tr> 
</thead> 
<tbody> 
    <xsl:for-each select="Document/Records/User"> 
    <xsl:variable name="row" select="Name" /> 
    <tr> 
     <th><xsl:value-of select="$row"/></th> 
     <!-- for each unique column header --> 
     <xsl:for-each select="/Document/Records/User/list/Data[count(. | key('data_by_column', Column)[1]) = 1]"> 
     <xsl:sort select="Column" data-type="number" order="ascending"/> 
     <xsl:variable name="col" select="Column" /> 
     <!-- new cell --> 
     <td> 
      <!-- get matching data --> 
      <xsl:for-each select="key('value_by_cell', concat($row, '|', $col))"> 
       <xsl:value-of select="."/> 
       <xsl:if test="position()!=last()"> 
        <xsl:text>, </xsl:text> 
       </xsl:if> 
      </xsl:for-each>  
     </td> 
     </xsl:for-each> 
    </tr> 
    </xsl:for-each> 
</tbody> 
</table> 
</xsl:template> 
</xsl:stylesheet> 

注:我可能已经消除重复独特的列相同的代码通过先卸到一个变量标头三次,但我跑了出去的时间。

+0

这工作得很好。我遇到的唯一问题是当文档中存在&或任何其他html实体时,它会中断。我尝试在第44行放置,,但它似乎不起作用。如何解决这个问题? – user3303297

+0

@ user3303297无法重现问题。你为什么不发表一个关于这个问题的新问题,最好与其他问题隔离? –

+0

谢谢。我明白了这一点,但我想知道你能否帮我解决最后一个问题。看起来,当有一个用户名称相同时,每个用户的值都会被复制。如果用户名不止一次存在,那很好,但我不希望不止一次为该用户复制数据。即​​胶状蠕虫,胶粘蠕虫,胶粘蠕虫。胶粘的蠕虫应该只出现一次。 – user3303297

0

我做了它使用递归模板。我只是没有对数据进行排序,并且列的数量是硬连线的。您可以改进它,在所有列中添加一个键并选择最大的数字,或通过变量或参数进行设置。

<?xml version="1.0" encoding="UTF-8"?> 
<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:output method="html" indent="yes"/> 

    <xsl:key name="food-by-Category" match="Data" use="Type" /> 

    <!-- Match the Records tree, set the table elements and first row --> 
    <xsl:template match="Records"> 
     <table width="800" border="1"> 
      <tbody> 
       <tr> 
        <td>Name</td> 
        <xsl:for-each select="User/list/Data[count(. | key('food-by-Category', Type)[1]) = 1]"> 
         <td><xsl:value-of select="Type"/></td> 
        </xsl:for-each> 
       </tr> 
       <!-- Apply the templates for each User subtree --> 
       <xsl:apply-templates select="User" /> 
      </tbody> 
     </table> 
    </xsl:template> 

    <!-- Set up one row for each User, get User name --> 
    <xsl:template match="User"> 
     <tr> 
      <td><xsl:value-of select="Name"/></td> 
      <!-- Apply the templates for the list subtree --> 
      <xsl:apply-templates select="list" /> 
     </tr> 
    </xsl:template> 

    <!-- This is a recursive template used to generate the columns 
     It's hardwired to generate 8 columns --> 
    <xsl:template name="empty-tds"> 
     <xsl:param name="columns" /> 
     <xsl:param name="i" /> 
     <xsl:if test="$i &lt;= 8"> 
      <!-- Fills in each column with RowValues --> 
      <td><xsl:apply-templates select="Data[Column = $i]/RowValue" /></td> 
      <xsl:call-template name="empty-tds"> 
       <xsl:with-param name="i" select="$i + 1" /> 
      </xsl:call-template> 
     </xsl:if> 
    </xsl:template> 

    <!-- This calls the template above and generates columns --> 
    <xsl:template match="list"> 
     <xsl:call-template name="empty-tds"> 
      <xsl:with-param name="i" select="1" /> 
     </xsl:call-template> 
    </xsl:template> 

    <!-- This one concatenates multiple RowValues within Data --> 
    <xsl:template match="RowValue"> 
     <xsl:value-of select="."/> 
     <xsl:if test="position() != last()"> 
      <xsl:text>, </xsl:text> 
     </xsl:if> 
    </xsl:template> 

</xsl:stylesheet> 

的最后一个用户(#6)不会打印因为在源它被放置在list内部。