Hinek
Hinek

Reputation: 9729

XPath to get the element with the highest ID

XML Source:

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

I need the document-element with the highest value in its id-element (so <document><id>7</id></document> in the example). I can't change the C# code, it is XMLDocument.SelectSingleNode(...), I only can modify the XPath used.

Is there something like documents/document[id=max(id)] or like order by id descending to get it?

Upvotes: 12

Views: 17884

Answers (5)

Nick Jones
Nick Jones

Reputation: 6493

documents/document[not(../document/id > id)]/id

Upvotes: 29

user357812
user357812

Reputation:

Besides Nick Jones XPath 1.0 correct answer, in XPath 2.0:

/documents/document[id = max(../document/id)]

Upvotes: 18

Dirk Vollmar
Dirk Vollmar

Reputation: 176169

You can use the preceding and following XPath axes to check whether there is no greater value:

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)]");

If there are several maximum id values in the document the above code will return the first one. If you want the last element with a maximum id you can use

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

If you want to get a list with all elements having a maximum id you can use the SelectNodes method:

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

XSLT version:

<?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>

Upvotes: 2

Mark Thomas
Mark Thomas

Reputation: 37517

Unfortunately, neither XPath 1.0 or XPath 2.0 define a sort() function. However, most implementations have a sort. For example, <xsl:sort> is available in XSLT implementations, and DOM4J has a sort by XPath method. I'm sure there is something similar in C# but you would have to change the C# code a bit.

Upvotes: 0

jimplode
jimplode

Reputation: 3502

Have a gander at this link. It uses a function math:max().

There is a link for source for that function and explains how it can be implemented

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

Hope this helps you

Upvotes: 1

Related Questions