4

Is there any way in XPath DOM Programming with using System.Xml to run selectNodes (XPATH) with a sort parameter?

For example, with the following XML and program writes values in the same order as the document (descending). Is there a way using XPath to get the values in ascending order?

NOTE. Of course, you could pre-sort in XSL, however I need to update the values as I'm looping through them. Since XSL gives me a sorted copy of the elements, not the actual elements themselves, I can't use XSL.

Here's some XML, a program out output

public static void Main() {

        XmlDocument xml = new XmlDocument();
        xml.Load( "t.xml" );

        // SelectNodes gets in document order, but I want in 
            // ascending order based on @value
        foreach( XmlNode ndNode in xml.SelectNodes( "/xml/ele" ) ) {
            Console.WriteLine( ndNode.Attributes["value"].Value );
        }
    }

Here's the XML

<xml>
<ele value='3' test='Third'/>
<ele value='2' test='Second'/>
<ele value='1' test='First'/>
</xml>

Finally the output in document (descending) order. I'd like an XPath that returns the nodes in ascending order.

3
2
1

PS, I'm using System.Xml in Visual Studio 2008 .NET 3.5

Wayne
  • 59,728
  • 15
  • 131
  • 126
William Walseth
  • 2,803
  • 1
  • 23
  • 25
  • From your sample, I can't see why XSL wouldn't work for you. What exactly is it about the original elements that means you must modify them? – Paul Butcher Dec 12 '11 at 23:03
  • XPath 2.0 has a `reverse` function. – Wayne Dec 12 '11 at 23:04
  • Hi Paul, to clarify, I need to update the elements in the loop. As I iterate each element contains an effective and expiration date. I need the elements sorted by effective date, and set the expiration date to be the next effective date. Sure, I guess it could be done in XSL by outputing a copy of the document, but I'm looking for a more efficient way. – William Walseth Dec 13 '11 at 14:29
  • Does changing the node have any effect anywhere else? e.g. some other object holds a pointer to the nodes, and changing the values changes the behaviour of some other object. If not, then you don't need to modify the original elements. If you are loading, altering and saving a document, then that saved document is no more the original than the output of an XSL transformation would be. – Paul Butcher Dec 13 '11 at 15:25
  • You're right Paul, it could be done in XSL. I've done it that way in the past. I'm just looking for another way. – William Walseth Dec 13 '11 at 16:13
  • It seems that XPath 3.1 offers sorting: https://stackoverflow.com/a/48361579/502187 –  Jan 20 '18 at 22:11

3 Answers3

7

XPath doesn't supprort ordering, however you may look at AddSort method.

Wojteq
  • 1,173
  • 9
  • 23
6

No, there is no way to do sorting in XPath alone.

But you can easily use LINQ to sort your collection of nodes by whatever values you want.

XmlDocument xml = new XmlDocument ();
xml.LoadXml("<xml> <ele value='3' test='Third'/> <ele value='2' test='Second'/> <ele value='1' test='First'/> </xml>");
var nodes = xml.SelectNodes( "/xml/ele" ).Cast<XmlNode>().OrderBy(ndNode => ndNode.Attributes["value"].Value);
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • Interesting, but isn't LINQ just for converting SQL datasets into XML? My XML isn't in a database. – William Walseth Dec 12 '11 at 22:21
  • No. You talking about LINQ-to-SQL that is subset of LINQ functionlaity. I've added sample how to get collection of nodes you need if you want to stick with XmlDocument. You may also want to consider LINQ-to-XML (XDocument,...). – Alexei Levenkov Dec 12 '11 at 22:56
  • Thanks Alexi, LINQ looks like a winner. I appreciate you bringing it to my attention. – William Walseth Dec 13 '11 at 14:25
  • Wrong. XPath 2.0 **can** sort (proof: http://www.ximeco.org/Xime/XPathCanSortHlousek.pdf). With XPath 3.0 it becomes efficient and easy. – Sean B. Durkin Aug 29 '13 at 02:07
  • 1
    @SeanB.Durkin Sure. Note that question was "with using System.Xml" which means OP is limited to XPath 1.0. – Alexei Levenkov Aug 29 '13 at 02:15
1

For anyone stumbling upon this question later, XPath 3.1 has a sort function.

David R
  • 994
  • 1
  • 11
  • 27