2012-01-02 31 views
7

Có cách nào để truy vấn tài liệu XML để trả về giá trị tối đa của một thuộc tính đã cho bằng Xpath 1.0 không?Cách tìm thuộc tính tối đa từ tài liệu XML bằng Xpath 1.0

Ví dụ: có cách nào để lấy id tối đa không?

<?xml version="1.0" encoding="utf-8"?> 
<library> 
     <book id="2" name="Dragon Tatoo"/> 
     <book id="7" name="Ender's Game"/> 
     <book id="3" name="Catch 22"/> 
     <book id="1" name="Lord of the rings"/> 
</library> 
+0

+1, cho dứa: P –

+0

Ngôn ngữ máy chủ của bạn để thực thi XPath là gì? Nếu bạn đang sử dụng XPath 1.0 (mà không có hàm 'max') thì có thể nhanh hơn để chọn tất cả các phần tử đầu tiên và tìm số tối đa trong PL của bạn. –

+0

Tôi đang sử dụng Perl 5.10. – HerbSpiral

Trả lời

0

Ví dụ này có thể được sử dụng để tìm giá thầu CPC

XmlDocument doc = new XmlDocument();      
doc.Load("../../Employees.xml"); 
XmlNode node = doc.SelectSingleNode("//Employees/Employee/@Id[not(. <=../preceding-sibling::Employee/@id) and not(. <=../following-sibling::Employee/@Id)]"); 
int maxId = Convert.ToInt32(node.Value); 

Đối với chủ đề tương tự khác trên xpath và LINQ kiểm tra http://rmanimaran.wordpress.com/2011/03/20/xml-find-max-and-min-value-in-a-attribute-using-xpath-and-linq/

3

XPath sau chọn cuốn sách với id cao nhất:

/library/book[not(@id <= preceding-sibling::book/@id) and not(@id <=following-sibling::book/@id)] 
+0

Điều này thực sự hiệu quả, tuy nhiên hiệu suất không tốt (khi hàng nghìn id có trong tài liệu) – HerbSpiral

+0

+1 - Tôi lặp lại cốt lõi của câu trả lời, nhưng tôi chỉ muốn cung cấp thêm thông tin trong câu trả lời của tôi, bao gồm một số những gì được trải ra xung quanh các ý kiến. –

+0

@lwburk Không có vấn đề gì;) – timbooo

2

Nếu bạn sẵn sàng để sử dụng dụng cụ bên ngoài - đó tùy thuộc vào việc triển khai của bạn có tính năng triển khai các công cụ này - hãy thử chức năng EXSLT:Mathhighest().

Thực tế là EXSLT thực hiện điều này ngụ ý rằng tính năng như vậy không có sẵn trực tiếp trong xpath đồng bằng, tất nhiên. Nếu bạn không sử dụng Transforms, hoặc muốn gắn hoàn toàn với đánh dấu tuân thủ tiêu chuẩn, các đề xuất của các áp phích khác sẽ là một lựa chọn tốt hơn.

7

Trong XPath 2.0, hãy sử dụng hàm max. Để tìm cuốn sách với mức cao nhất id, làm

/library/book[@id = max(/library/book/@id)] 
+1

Có vẻ như hàm tối đa không phải là một phần của Xpath 1.0 :( – HerbSpiral

+0

@HerbSpiral: hmm. Đã thử trong chế độ tương thích XQilla XPath 1.0 và nó hoạt động , nhưng có lẽ đó không thực sự là XPath 1.0. –

2

Lưu ý: Thông tin sau đây giả sử dụng XPath 1.0.

Biểu thức sau trả về phần tử (s) với giá trị lớn nhất id:

/*/book[not(@id < preceding-sibling::book/@id) and 
     not(@id < following-sibling::book/@id)] 

Lưu ý rằng đây là hơi khác so với @ timbooo của câu trả lời ở chỗ này sẽ trở lại nhiều hơn một phần tử khi có trùng lắp với cùng một giá trị tối đa (@ timbooo sẽ không trả về giá trị nào). Nếu bạn chỉ muốn có một phần tử trong trường hợp này, thì bạn cần một chiến lược phân giải. Để chọn các yếu tố đầu tiên như vậy theo thứ tự tài liệu, sử dụng này:

/*/book[not(@id < preceding-sibling::book/@id) and 
     not(@id < following-sibling::book/@id)][1] 

để lựa chọn người cuối cùng, sử dụng này:

/*/book[not(@id < preceding-sibling::book/@id) and 
     not(@id < following-sibling::book/@id)][last()] 

Cách tiếp cận này là rất không hiệu quả (O(n^2)) bởi vì nó đòi hỏi bạn phải so sánh mỗi phần tử với mọi CPC tối đa tiềm năng khác Vì lý do này, tốt nhất bạn nên sử dụng ngôn ngữ lập trình máy chủ để chọn phần tử tối đa. Đơn giản chỉ cần chọn tất cả các yếu tố book trước và sau đó chọn giá trị tối đa từ danh sách đó. Đây là (rất có thể) một hoạt động tuyến tính (O(n)), mà sẽ là đáng chú ý nhanh hơn trên các tài liệu rất lớn. Ví dụ: trong Java (JAXP), bạn có thể làm như sau:

XPath xpath = XPathFactory.newInstance().newXPath(); 
NodeList nodes = (NodeList) xpath.evaluate("/*/book", doc, 
     XPathConstants.NODESET); 
Node max = nodes.item(0); 
for (int i = 0; i < nodes.getLength(); i++) { 
    int maxval = Integer.parseInt(max.getAttributes() 
      .getNamedItem("id").getNodeValue()); 
    int curval = Integer.parseInt(nodes.item(i).getAttributes() 
      .getNamedItem("id").getNodeValue()); 
    if (curval >= maxval) 
     max = nodes.item(i); 
} 
System.out.println(max.getAttributes().getNamedItem("name")); 

Lưu ý rằng đây chỉ là một minh chứng; hãy chắc chắn bao gồm kiểm tra null nếu thích hợp.

1

Tôi đã tìm thấy câu trả lời giống như tác phẩm của lwburk hoặc timbooo cho các thuộc tính đại diện cho các số chỉ có một chữ số. Tuy nhiên, nếu thuộc tính là một số có nhiều hơn một chữ số, thì những thứ phụ trội dường như xảy ra khi so sánh giữa các giá trị của thuộc tính.Ví dụ: Ví dụ: thử thay đổi dữ liệu XML gốc bằng một cái gì đó như sau:

<?xml version="1.0" encoding="utf-8"?> 
<library> 
     <book id="250" name="Dragon Tatoo"/> 
     <book id="700123" name="Ender's Game"/> 
     <book id="305" name="Catch 22"/> 
     <book id="1070" name="Lord of the rings"/> 
</library> 

Chạy đoạn trích được đề xuất sẽ không hoạt động. Tôi nhận được giải pháp bằng cách sử dụng toán tử đúc xs: int() được áp dụng trên thuộc tính id, như sau:

/library/book[not(xs:int(@id) <= preceding-sibling::book/@id) and not(xs:int(@id) <=following-sibling::book/@id)] 

Điều đó sẽ đưa ra câu trả lời đúng!

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