2010-05-10 36 views
5

Làm thế nào để sử dụng xsl:for-each trong XSLT để nhận được giá trị lặp đi lặp lại từ một file xml và để dispaly nó trong bảng fromatLàm thế nào để sử dụng cho vòng lặp trong XSLT

Ví dụ: file xml là như

<order> 
    <item name ="a"/> 
    <item name ="b"/> 
    <item name ="c"/> 
    <item name ="d"/> 
    <item name ="e"/> 
    <item name ="f"/> 
    <item name ="g"/> 
</order> 

và đầu ra nên

a b c d 

    e f g 

vòng lặp nên tính mục và nếu nó là divisble 4 nó

nên đóng hàng hiện tại và thêm một hàng mới và vân vân ..

Tôi đang sử dụng XSLT sau này

nhưng tôi không thể hiển thị nó trong định dạng bảng

<xsl:template match="/"> 
    <html> 
    <body> 
    <xsl:call-template name ="incr"> 
     <xsl:with-param name ="value">1</xsl:with-param> 
     <xsl:with-param name ="limit"> 
      <xsl:value-of select ="count(//item)"/> 
     </xsl:with-param> 
     </xsl:call-template> 
    </body> 
</html> 
</xsl:template > 
<xsl:template name="incr"> 
    <xsl:param name="value"/> 
    <xsl:param name ="limit"/> 
    <xsl:if test ="$value!=$limit+1"> 
    <xsl:value-of select ="//item[$value]/@name"/> 
    <xsl:if test ="$value mod 4 =0"> 
     <br/> 
     <br/> 
    </xsl:if> 
    <xsl:call-template name ="incr"> 
     <xsl:with-param name ="value" select ="$value+1"/> 
     <xsl:with-param name ="limit" select ="$limit"/> 
    </xsl:call-template> 
    </xsl:if> 

</xsl:template> 

xin vui lòng giúp tôi để làm điều này

Cảm ơn trước

+1

Bạn đã làm gì để giải quyết vấn đề này cho đến nay? Điều này trông giống như bài tập về nhà. –

+0

+1 cho câu hỏi. Xem câu trả lời của tôi cho một giải pháp hoàn chỉnh và chính xác. :) –

Trả lời

-4
<table> 
<tr> 
    <xsl:for-each select="//order/item"> 
    <td> 
    <xsl:value-of select ="current()/@name"/> 
    </td> 
    <xsl:if test="position() mod 4 = 0"> 
    <xsl:text disable-output-escaping="yes"><![CDATA[</tr><tr>]]></xsl:text> 
    </xsl:if> 
    </xsl:for-each> 
</tr> 
</table> 
+0

đưa ra kết quả chính xác nhưng có đúng không? –

+0

Không. Cách điên rồ đó nằm. Một thẻ mở và đóng tuyên bố một điều duy nhất. Các giải pháp trên là một nhà nghỉ. –

-1

tôi không chắc chắn 100% nhưng mã dưới đây sẽ làm điều đó:

<table> 
    <tr> 
    <xsl:for-each select="//order/item"> 
     <td> 
     <xsl:value-of select ="current()/@name"/> 
     </td> 
    <xsl:if test="position() mod 4 = 0"> 
    <xsl:text disable-output-escaping="yes"><![CDATA[</tr><tr>]]></xsl:text> 
    </xsl:if> 
    </xsl:for-each> 
    <xsl:variable name="item_count_mod4" select="count(//order/item) mod 4"/> 
    <xsl:choose> 
     <xsl:when test="$item_count_mod4 = 1"> 
     <td></td><td></td><td></td> 
     </xsl:when> 
     <xsl:when test="$item_count_mod4 = 2"> 
     <td></td><td></td> 
     </xsl:when> 
     <xsl:when test="$item_count_mod4 = 3"> 
     <td></td> 
     </xsl:when> 
     <xsl:otherwise> 
     </xsl:otherwise> 
    </xsl:choose> 
    </tr> 
</table> 
+0

chúng tôi không thể làm như thế này vì không thể đóng đúng và lỗi hiển thị của nó –

+0

Bạn hoàn toàn đúng về vấn đề "". CDATA lừa dễ dàng giải quyết nó. Bạn có thể kiểm tra mã đã chỉnh sửa của tôi ở trên. Tôi đã thử nghiệm với XML Notepad và nó biến đổi thành công. – Cagdas

+1

Đây là cách hoàn toàn sai để thực hiện việc này. –

7

chuyển đổi này:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:variable name="vNumCols" select="4"/> 

<xsl:template match="/*"> 
    <table> 
    <xsl:for-each select= 
    "item[position() mod $vNumCols = 1]"> 

    <tr> 
     <xsl:for-each select= 
     ". | following-sibling::* 
       [not(position() >= $vNumCols)]"> 
     <td><xsl:value-of select="@name"/></td> 
     </xsl:for-each> 
    </tr> 
    </xsl:for-each> 
    </table> 
</xsl:template> 
</xsl:stylesheet> 

khi áp dụng trên tài liệu XML được cung cấp, sản xuất các kết quả đúng mong muốn:

<table> 
    <tr> 
     <td>a</td> 
     <td>b</td> 
     <td>c</td> 
     <td>d</td> 
    </tr> 
    <tr> 
     <td>e</td> 
     <td>f</td> 
     <td>g</td> 
    </tr> 
</table> 
+0

Giải pháp tốt, nhưng tôi đã tìm thấy sự cố, nếu "vNumCols" được đặt thành "1", nó sẽ không hiển thị gì cả. –

+2

@XiaodanMao, Có, và cùng một vấn đề tồn tại đối với '$ vNumCols' được đặt thành 0. Điều này là do các giá trị đó nằm ngoài phạm vi theo định nghĩa cho vấn đề này. Bạn có thể thấy rằng bất kỳ giải pháp làm thế nào để lỗ nước vào N chén không hoạt động nếu nhiệt độ là -1 độ Celsius. –

+0

Cảm ơn phản hồi của bạn. –

8

Các cách để suy nghĩ về những vấn đề phức tạp bất kỳ trong XSLT không phải là "làm thế nào tôi viết một chương trình để tạo ra Y, cho X là đầu vào?" nhưng đúng hơn là, "cho ra Y, cái gì tôi sẽ biến đổi để tạo ra nó?" Nó không phải là một nguyên tắc dễ dàng để nắm bắt (hoặc rõ ràng), nhưng một khi bạn nhận được nó, những gì có vẻ như vấn đề khó khăn trong XSLT trở nên tầm thường.

Nếu đầu ra là một loạt các tr yếu tố, như thế này:

<tr> 
    <td>a</td><td>b</td><td>c</td> 
</tr> 
<tr> 
    <td>d</td><td>e</td><td>f</td> 
</tr> 
<tr> 
    <td>g</td><td>h</td><td>i</td> 
</tr> 
<tr> 
    <td>j</td><td/><td/> 
</tr> 

có, trong bản chất, bốn yếu tố đầu ra. Vì vậy, phải có bốn yếu tố đầu vào.

Câu hỏi đầu tiên là bốn câu hỏi nào? Khá rõ ràng, nó sẽ là ngày 1, 4, 7 và 10 - tức là, mỗi 3 yếu tố, bắt đầu với phần tử đầu tiên. Vì vậy, điểm khởi đầu của bạn là để chuyển đổi những bốn yếu tố:

<xsl:apply-templates select="/order/item[position() mod 3 = 1]"/> 

Được rồi, và bây giờ mà chúng tôi đã chọn tất cả các yếu tố thứ ba, làm thế nào chúng ta sẽ tạo ra một tr ra khỏi nó và các yếu tố ngay sau khi nó? Sử dụng trục following-sibling:

Điều đó tốt cho đến khi nó xảy ra. Nhưng có một số tiền hợp lý của mã trùng lặp và rất nhiều bạn phải sửa đổi nếu bạn muốn (nói) thay đổi số cột từ 3 đến 6.Bạn có thể loại bỏ mã trùng lặp bằng cách tạo một mẫu khác:

<xsl:template match="item"> 
    <tr> 
     <xsl:apply-templates select="@name | following-sibling::item[position() &lt;= 3]/@name"/> 
    </tr> 
</xsl:template> 

<xsl:template match="@name"> 
    <td><xsl:value-of select="."/></td> 
</xsl:template> 

Và bạn có thể tham số hóa số cột bằng cách đặt nó vào biến, như Dimitre đã làm trong ví dụ của mình.

Các vấn đề liên quan