2010-04-07 24 views
8

Tôi có một tình huống mà vòng lặp thông qua một nodeset sắp xếp và áp dụng một mẫu trên mỗi nút:Sắp xếp một nodeset trước khi đi qua để xsl: for-each

<div id="contractscontainer"> 
    <xsl:for-each select="document"> 
    <xsl:sort select="content[@name='ClientName']/text()" /> 
    <xsl:apply-templates select="." mode="client-contract" /> 
    </xsl:for-each> 
</div> 

Tôi muốn làm điều gì đó đặc biệt với " đầu tiên "5 nút trong tập hợp nút và hiển thị chúng thành phần tử lồng nhau. Vấn đề là họ cần phải được theo thứ tự như thể họ đã được sắp xếp (như họ đang ở trong vòng lặp).

Tôi đã lên kế hoạch thực hiện việc này bằng cách sử dụng hai phần tử xsl:for-each, mỗi phần tử có các nút chính xác được chọn từ bộ này. Tôi không thể làm được điều này, tuy nhiên, bởi vì họ cần phải được sắp xếp trước tôi có thể chọn "đầu tiên" 5.

Ví dụ:

<div id="contractscontainer"> 
    <div class="first-five"> 
    <xsl:for-each select="document[position() < 6]"> 
     <xsl:sort select="content[@name='ClientName']/text()" /> 
     <xsl:apply-templates select="." mode="client-contract" /> 
    </xsl:for-each> 
    </div> 
    <div class="rest-of-them"> 
    <xsl:for-each select="document[position() > 5]"> 
     <xsl:sort select="content[@name='ClientName']/text()" /> 
     <xsl:apply-templates select="." mode="client-contract" /> 
    </xsl:for-each> 
    </div> 
</div> 

Tôi không nghĩ rằng điều này sẽ làm việc vì tôi đang chọn các nút theo vị trí trước khi phân loại chúng, nhưng tôi không thể sử dụng xsl:sort bên ngoài số xsl:for-each.

Tôi có đang tiếp cận điều này không chính xác không?

Sửa: giải pháp hiện tại của tôi là để sắp xếp chúng và lưu trữ các sắp xếp đặt trong một biến khác:

<xsl:variable name="sorted-docs"> 
    <xsl:for-each select="document"> 
    <xsl:sort select="content[@name='ClientName']/text()" /> 
    <xsl:copy-of select="." /> 
    </xsl:for-each> 
</xsl:variable> 

Nó hoạt động, nhưng là có một cách tốt hơn?

+0

Câu hỏi hay (+1). Giải pháp hiện tại của bạn không phải là xấu, nhưng biến xsl: với các phần tử được sắp xếp là kiểu RTF và bạn cần sử dụng hàm mở rộng xxx: node-set() trong XSLT 1.0. Xem giải pháp của tôi làm thế nào để làm điều này mà không cần bất kỳ chức năng mở rộng. –

+0

Có, tôi đã kết thúc việc đó: sử dụng exsl: node-set(). Cảm ơn bạn đã giải pháp! –

Trả lời

14

Dưới đây là một cách để làm điều này trong XSLT 1.0 mà không cần phải sử dụng chức năng xxx:node-set() mở rộng:

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

<xsl:template match="/*"> 
    <html> 
    <div class="first-five"> 
    <xsl:apply-templates select="num"> 
     <xsl:sort select="." data-type="number"/> 
     <xsl:with-param name="pStart" select="1"/> 
     <xsl:with-param name="pEnd" select="5"/> 
    </xsl:apply-templates> 
    </div> 
    <div class="rest-of-them"> 
    <xsl:apply-templates select="num"> 
     <xsl:sort select="." data-type="number"/> 
     <xsl:with-param name="pStart" select="6"/> 
    </xsl:apply-templates> 
    </div> 
    </html> 
</xsl:template> 

<xsl:template match="num"> 
    <xsl:param name="pStart"/> 
    <xsl:param name="pEnd" select="999999999999"/> 

    <xsl:if test="position() >= $pStart 
       and 
       not(position() > $pEnd)"> 
    <p><xsl:value-of select="."/></p> 
    </xsl:if> 
</xsl:template> 

</xsl:stylesheet> 

Khi việc chuyển đổi trên được áp dụng trên tài liệu này đơn giản XML:

<nums> 
    <num>5</num> 
    <num>3</num> 
    <num>6</num> 
    <num>8</num> 
    <num>4</num> 
    <num>1</num> 
    <num>9</num> 
    <num>2</num> 
    <num>7</num> 
    <num>10</num> 
</nums> 

kết quả mong muốn được tạo ra:

<html> 
    <div class="first-five"> 
     <p>1</p> 
     <p>2</p> 
     <p>3</p> 
     <p>4</p> 
     <p>5</p> 
    </div> 
    <div class="rest-of-them"> 
     <p>6</p> 
     <p>7</p> 
     <p>8</p> 
     <p>9</p> 
     <p>10</p> 
    </div> 
</html> 
+0

Giải quyết được sự cố của tôi, cảm ơn –

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