2017-06-29 54 views
2

我對xslt比較陌生,一直在嘗試使用xml結構創建表,但是我發現很難限制每行中字段的數量..xslt - 限制xslt轉換中的行

<report> 
<status> 
    <statuscheck> 
     <node>node1</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area1</area> 
    </statuscheck> 
    <statuscheck> 
     <node>node2</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area1</area> 
    </statuscheck> 
    <statuscheck> 
     <node>node3</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area1</area> 
    </statuscheck> 
    <statuscheck> 
     <node>node4</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area1</area> 
    </statuscheck> 
    <statuscheck> 
     <node>node5</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area1</area> 
    </statuscheck> 
    <statuscheck> 
     <node>node1</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area2</area> 
    </statuscheck> 
</status> 
<area> 
    <area_name>area1</area_name> 
    <area_name>area2</area_name> 
</area> 

我有以下XSLT,但有什麼辦法,我可以得到它的每4個項目後開始一個新行?實際的xml將有多達20個組件每個區域。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <html> 
      <head> 
       <style> 
       </style> 
      </head> 

      <body style="font-family: Sky Text;"> 
      <xsl:for-each select="/report/area/area_name"> 
          <div style="font-size: 20px; font-weight: bold; margin: 10px 0 10px 0;"><xsl:value-of select="."/></div> 
          <table style="font-family: Sky Text; border-collapse: collapse; width: 960px;"> 
           <tbody> 
            <xsl:variable name="active_area" select="./text()"></xsl:variable> 
            <xsl:for-each select="/report/status/statuscheck[area/text() = $active_area]"> 
             <td style="width: 240px; border: 1px solid black; text-align: center;" valign="middle"> 
              <xsl:attribute name="class"> 
               <xsl:value-of select="RAG"/> 
              </xsl:attribute> 
              <div style="margin: 10px; font-size: 16px;"> 
              <a> 
               <xsl:attribute name="href"> 
                <xsl:value-of select="url"/> 
               </xsl:attribute> 
               <xsl:value-of select="node"/> 
              </a> 
              </div> 
             </td> 
            </xsl:for-each> 
           </tbody> 
          </table> 
         </xsl:for-each> 
      </body> 
     </html> 
    </xsl:template> 

</xsl:stylesheet> 

在此先感謝 加文

+0

參見[XSLT 1.0分組主要針對不同的節點和元素(https://stackoverflow.com/q/7061614/ 205233)提出了一個非常類似的問題。 [相關搜索](https://www.google.com/search?q=site%3Astackoverflow.com+xslt+group+by+key)以及更多類似的問題。 – Filburt

+1

有什麼理由你真的需要這是一張桌子?誠實地從你的HTML看起來,你最好爲每個'statuscheck'創建一個div塊,然後用CSS放置這些塊。 – Flynn1179

+0

謝謝..我對html很新,但使用了CSS佈局,看起來像它會做我所需要的。謝謝 – gav1nb

回答

1

我傾向於同意@同意從文體的角度Flynn1179的評論。應該使用HTML表格來呈現表格數據,而不是嚴格地用於佈局目的。如果你的數據是固有的表格,那麼將它們映射到列和行是很自然的。但這並不意味着XSLT無法完成所介紹的工作。

然而,在談論如何將XSLT應用於任務之前,我應該首先指出您的XSLT是像程序性程序一樣編寫的,這不是XSLT的自然範例。即使在這種情況下,它也無法利用一些XSLT功能,使其更加清晰和簡單。一般建議:

  • 不要使用xsl:for-each其中xsl:apply-templates和一個單獨的模板可以成爲代替。
  • 除此之外,不要猶豫,使用多個頂級模板。將一個大模板拆分爲多個較小的模板就像是將一個較長的函數分成幾個較短的模板,並具有許多與可讀性,可維護性和可重用性相同的優點。
  • 優選使用xsl:elementxsl:attribute的文字結果元素和屬性。後者很少,如果需要的話,除非元素/屬性名稱需要通過變換來計算。
  • 尤其要注意的是,文字結果屬性的值是「屬性值模板」,您可以在其中計算XPath表達式。
  • 瞭解xsl:keykey()功能。這些比新人可能想到的更有用。除此之外,它們對於分組非常有用。

雖這麼說,然後,請考慮您的樣式表的這個重構:

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

    <xsl:output method="html"/> 

    <!-- group the statuscheck elements by their areas -->  
    <xsl:key name="area" match="/report/status/statuscheck" use="area"/> 

    <!-- Provides the top-level document structure --> 
    <xsl:template match="/"> 
    <html> 
     <head> 
     <style> 
     </style> 
     </head> 
     <body style="font-family: Sky Text;"> 
     <!-- generate the body contents by transforming the area_name elements --> 
     <xsl:apply-templates select="report/area/area_name"/> 
     </body> 
    </html> 
    </xsl:template> 

    <!-- Transforms area_name elements to produce area information. Note that 
     The template is not restricted to drawing on the subtree rooted at the 
     context node. --> 
    <xsl:template match="area_name"> 
    <xsl:variable name="active_area" select="string(.)"/> 
    <div style="font-size: 20px; font-weight: bold; margin: 10px 0 10px 0;"><xsl:value-of select="$active_area"/></div> 
    <table style="font-family: Sky Text; border-collapse: collapse; width: 960px;"> 
     <tbody> 
     <!-- each row is generated by transforming a distinguished element; 
      specifically, the first --> 
     <xsl:apply-templates select="key('area', $active_area)[position() mod 4 = 1]" mode="row-head"> 
      <!-- this is one way to tell the template we're about to apply which are 
       the other statuscheck element's in the context node's group: --> 
      <xsl:with-param name="area-checks" select="key('area', $active_area)"/> 
     </xsl:apply-templates> 
     </tbody> 
    </table> 
    </xsl:template> 

    <!-- transform a statuscheck node by emitting a <tr> element with a <td> child 
     for each item in the row --> 
    <xsl:template match="statuscheck" mode="row-head"> 
    <xsl:param name="area-checks"/> 
    <xsl:variable name="row-start" select="position() * 4 - 3"/> 
    <tr> 
     <!-- the <td> elements are generated by a separate template --> 
     <xsl:apply-templates select="$area-checks[position() >= $row-start and position() &lt; $row-start + 4]"/> 
    </tr> 
    </xsl:template> 

    <!-- This template and the other matching the same elements are distinguished 
     by their modes. --> 
    <xsl:template match="statuscheck"> 
    <!-- Note how the value of the 'class' literal result attribute is expressed 
     via an XPath expression. You don't need xsl:attribute for that. --> 
    <td class="{RAG}" style="width: 240px; border: 1px solid black; text-align: center;" valign="middle"> 
     <div style="margin: 10px; font-size: 16px;"> 
     <a href="{url}"><xsl:value-of select="node"/></a> 
     </div> 
    </td> 
    </xsl:template> 

</xsl:stylesheet>