2011-01-24 104 views
5

Tôi muốn sắp xếp một tệp XML bằng phép chuyển đổi XSL.Sắp xếp XML trong XSLT dựa trên danh sách các giá trị

<root> 
    <element> 
     <name>A</name> 
    </element> 
    <element> 
     <name>B</name> 
    </element> 
    <element> 
     <name>C</name> 
    </element> 
</root> 

Phải được sắp xếp theo danh sách sau đây của tên: C, A, B sao cho XML kết quả là:

<root> 
     <element> 
      <name>C</name> 
     </element> 
     <element> 
      <name>A</name> 
     </element> 
     <element> 
      <name>B</name> 
     </element> 
    </root> 

Rõ ràng là danh sách các giá trị được sắp xếp trên nên được khá năng động (tham số của XSLT, một tệp XML khác ...). Bất kỳ ý tưởng nào về cách thực hiện điều đó trong XSLT?

Cảm ơn, Christophe

+0

Tốt câu hỏi, 1. Xem câu trả lời của tôi cho một giải pháp hoàn chỉnh và ngắn, cộng với lời giải thích đầy đủ. –

Trả lời

8

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:strip-space elements="*"/> 

<xsl:param name="pSortingValues" select="'C,A,B'"/> 
<xsl:variable name="vSortingValues" select= 
    "concat(',', $pSortingValues, ',')"/> 

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="/*"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates select="*"> 
     <xsl:sort data-type="number" select= 
     "string-length(substring-before($vSortingValues,concat(',',name,',')))"/> 
     </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

khi áp dụng trên tài liệu XML cung cấp:

<root> 
    <element> 
     <name>A</name> 
    </element> 
    <element> 
     <name>B</name> 
    </element> 
    <element> 
     <name>C</name> 
    </element> 
</root> 

tạo ra truy nã, kết quả đúng:

<root> 
    <element> 
     <name>C</name> 
    </element> 
    <element> 
     <name>A</name> 
    </element> 
    <element> 
     <name>B</name> 
    </element> 
</root> 

Do lưu ý:

  1. Các mong muốn danh sách các giá trị được sắp xếp là pSortingValues tham số toàn cầu, có thể được cung cấp từ bên ngoài để chuyển đổi.

  2. Quy tắc nhận dạng được sử dụng để sao chép tất cả các nút "nguyên trạng".

  3. Quy tắc nhận dạng được ghi đè cho phần tử trên cùng. Phần tử trên được sao chép một phần, các thuộc tính của nó được sao chép, sau đó các mẫu được áp dụng trên tất cả các phần tử con với lệnh con <xsl:sort>, chỉ định khóa sắp xếp chính xác sẽ được sử dụng - cách trước pSortingValues giá trị tên của element đứa trẻ là.

CẬP NHẬT: Theo ghi nhận của @Alejandro, đây:

 <xsl:sort data-type="number" select= 
     "string-length(substring-before($vSortingValues,concat(',',name,',')))"/> 

có thể được đơn giản hóa như sau:

 <xsl:sort data-type="number" select= 
     "substring-before($vSortingValues,concat(',',name,','))"/> 
+0

+1. Mẹo phân loại ưa thích. – Flack

+1

@Dimitre: +1 Câu trả lời hay. Như các kiểu dữ liệu chuỗi, chuỗi con trước khi hoạt động theo cùng một cách, cũng vậy. –

+1

@Alejandro: Cảm ơn. I * am * sử dụng 'chuỗi con trước()'. –

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