2010-09-24 27 views
12

XML Nguồn cao nhất:XPath để có được những phần tử với ID

<documents> 
    <document> 
     <id>3</id> 
    </document> 
    <document> 
     <id>7</id> 
    </document> 
    <document> 
     <id>1</id> 
    </document> 
</documents> 

Tôi cần tài liệu phần tử với giá trị cao nhất trong id phần tử của nó (vì vậy <document><id>7</id></document> trong ví dụ). Tôi không thể thay đổi mã C#, nó là XMLDocument.SelectSingleNode(...), tôi chỉ có thể sửa đổi XPath được sử dụng.

Có điều gì đó như documents/document[id=max(id)] hoặc thích order by id descending để tải xuống?

Trả lời

24
documents/document[not(../document/id > id)] 
+2

+1 Đối với biểu thức tối đa XPath 1.0 ngắn nhất và chính xác, bên cạnh sự phức tạp cuadratic ... –

+0

cảm ơn, giải pháp tuyệt vời, bạn sẽ nhận được điểm thưởng cho cái này! – Hinek

+2

Giải pháp thông minh! –

1

Tìm kiếm tại liên kết này. Nó sử dụng một hàm toán học: max().

Có một liên kết cho nguồn cho chức năng đó và giải thích cách nó có thể được thực hiện

http://www.exslt.org/math/functions/max/index.html

Hy vọng điều này sẽ giúp bạn

+0

Và sau khi triển khai, bạn có thể làm như sau:/documents/document/id [number (child :: text()) Restuta

+0

như tôi thấy, nó được hỗ trợ bởi một số bộ xử lý XSLT, nhưng không phải bởi .NET ... Tôi có thiếu cái gì đó không? – Hinek

+0

@Restuts, tôi cần nút tài liệu, không được giống như:/documents/document [number (id/child :: text()) = math: max (số (id/child :: text()))] – Hinek

0

Thật không may, không phải XPath 1.0 hoặc XPath 2.0 định nghĩa một loại() chức năng. Tuy nhiên, hầu hết các triển khai đều có sắp xếp. Ví dụ: <xsl:sort> khả dụng trong các triển khai XSLT và DOM4J có sắp xếp theo phương thức XPath. Tôi chắc rằng có cái gì đó tương tự trong C# nhưng bạn sẽ phải thay đổi mã C# một chút.

2

Bạn có thể sử dụng precedingfollowing XPath trục để kiểm tra xem không có giá trị lớn:

XmlDocument doc = new XmlDocument(); 
doc.LoadXml("<documents>" 
    + " <document><id>3</id></document>" 
    + " <document><id>7</id></document>" 
    + " <document><id>1</id></document>" 
    + "</documents>"); 

var max = doc.SelectSingleNode(
    "/documents/document[not(id < preceding::document/id) 
         and not(id < following::document/id)]"); 

Nếu có nhiều giá trị id tối đa trong tài liệu mã trên sẽ trở lại đầu tiên. Nếu bạn muốn yếu tố cuối cùng với một id tối đa mà bạn có thể sử dụng

var max = doc.SelectSingleNode(
    "/documents/document[not(id < preceding::document/id) 
         and not(id <= following::document/id)]"); 

Nếu bạn muốn có được một danh sách tất cả các yếu tố có một id tối đa mà bạn có thể sử dụng SelectNodes phương pháp: phiên bản

var maxList = doc.SelectNodes(
    "/documents/document[not(id < preceding::document/id) 
         and not(id < following::document/id)]"); 

XSLT :

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <root> 
     <xsl:value-of 
      select="/documents/document/id[not(. &lt;= preceding::document/id) 
        and not(. &lt;= following::document/id)]"/> 
     </root> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Điều này không chỉ cung cấp cho bạn cái đầu tiên mà nó vượt qua mà còn cao hơn cái trước và cái sau nó? – jimplode

+0

xin lỗi, sai lầm của tôi. – jimplode

11

Bên cạnh Nick Jones XPath 1.0 câu trả lời đúng, trong XPath 2.0:

/documents/document[id = max(../document/id)] 
Các vấn đề liên quan