2008-09-30 37 views
10

Cách tính các giá trị khác biệt trong một nút trong XSLT?Cách tính các giá trị khác biệt trong một nút?

Ví dụ: Tôi muốn đếm số lượng các nước tồn tại trong các hạch quốc gia, trong trường hợp này, nó sẽ là 3.

<Artists_by_Countries> 
    <Artist_by_Country> 
     <Location_ID>62</Location_ID> 
     <Artist_ID>212</Artist_ID> 
     <Country>Argentina</Country> 
    </Artist_by_Country> 
    <Artist_by_Country> 
     <Location_ID>4</Location_ID> 
     <Artist_ID>108</Artist_ID> 
     <Country>Australia</Country> 
    </Artist_by_Country> 
    <Artist_by_Country> 
     <Location_ID>4</Location_ID> 
     <Artist_ID>111</Artist_ID> 
     <Country>Australia</Country> 
    </Artist_by_Country> 
    <Artist_by_Country> 
     <Location_ID>12</Location_ID> 
     <Artist_ID>78</Artist_ID> 
     <Country>Germany</Country> 
    </Artist_by_Country> 
</Artists_by_Countries> 

Trả lời

24

Nếu bạn có một tài liệu lớn, bạn có thể muốn sử dụng "Muenchian Phương pháp", mà thường được sử dụng cho nhóm, để xác định các nút riêng biệt. Khai báo một chìa khóa mà chỉ những điều bạn muốn đếm bằng các giá trị mà là khác biệt:

<xsl:key name="artists-by-country" match="Artist_by_Country" use="Country" /> 

Sau đó, bạn có thể nhận được <Artist_by_Country> yếu tố đó có các nước khác nhau sử dụng:

/Artists_by_Countries 
    /Artist_by_Country 
    [generate-id(.) = 
    generate-id(key('artists-by-country', Country)[1])] 

và bạn có thể tin tưởng họ bằng cách gói trong cuộc gọi đến chức năng count().

Tất nhiên trong XSLT 2.0, nó đơn giản như

count(distinct-values(/Artists_by_Countries/Artist_by_Country/Country)) 
+0

Đôi mắt của tôi đang lấp lánh trên hàng loạt các dòng sau đó tôi tìm thấy nugget ở cuối –

3

Hãy thử một cái gì đó như thế này:

count(//Country[not(following::Country/text() = text())]) 

"Hãy cho tôi tổng số của tất cả các nút Quốc gia không có Quốc gia sau có văn bản phù hợp "

Bit thú vị của biểu thức đó, IMO, là trục following.

Bạn có thể có lẽ cũng loại bỏ các /text() đầu tiên, và thay thế thứ hai với .

+0

này sẽ chỉ làm việc nếu các nút đều được sắp xếp và các giá trị Nước như do đó liên tiếp. – dacracot

+3

Không, nó sẽ luôn hoạt động. sau :: hoạt động trên toàn bộ tài liệu, nếu có bất kỳ quốc gia nào sau ngữ cảnh có cùng giá trị, thì nút đó sẽ không được tính. –

+0

Đây phải là câu trả lời được chấp nhận, mặc dù tùy chọn 2.0 là rất tốt cho những người có thể sử dụng nó. – Moss

6

Trong XSLT 1.0 này là không rõ ràng, nhưng sau sẽ cho bạn một ý tưởng về các yêu cầu:

count(//Artist_by_Country[not(Location_ID=preceding-sibling::Artist_by_Country/Location_ID)]/Location_ID) 

Càng nhiều phần tử trong XML của bạn càng dài, vì nó kiểm tra từng anh chị em trước của mỗi phần tử đơn lẻ.

+0

Không chắc chắn về hiệu suất, nhưng đối với XSLT 1.0, điều này có vẻ giống như một giải pháp sạch hơn yêu cầu phần tử trong giải pháp bình chọn hàng đầu. –

+0

Thường có ít nhất hai cách để nuôi một con mèo trong XSLT - và cách tốt nhất là tùy thuộc vào hoàn cảnh cụ thể của bạn. xsl: key có thể rất nhanh trong một bộ xử lý tốt trên các tài liệu lớn so với phương pháp của tôi ở trên mà tôi nghi ngờ. – samjudson

0

Nếu bạn có quyền kiểm soát thế hệ xml vào lần xuất hiện đầu tiên của quốc gia, bạn có thể thêm thuộc tính vào nút quốc gia, chẳng hạn như distinct = 'true' gắn cờ quốc gia là "cũ" và không thêm thuộc tính riêng biệt nếu bạn lại gặp lại quốc gia đó.

Sau đó, bạn có thể làm

<xsl:for-each select="Artists_by_Countries/Artist_by_Country/Country[@distinct='true']" /> 
Các vấn đề liên quan