2014-02-13 58 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內部。