Reputation: 529
Given the following XML:
<xml>
<Table>
<Product>
<CaseName>Test 1</CaseName>
<Beta>banana</Beta>
<Alpha>apple</Alpha>
<Delta>dates</Delta>
<Chi>chiku</Chi>
</Product>
<Product>
<CaseName>Test 2</CaseName>
<Beta>borange</Beta>
<Alpha>ared</Alpha>
<Delta>dblue</Delta>
<Chi>cgreen</Chi>
</Product>
</Table>
</xml>
I would like to use XPath and the "or" operator to dictate the order the nodes under Product are returned, but regardless of the XPath statement that I use, the query results are always returned in the order of the original XML. For example, the following XPath statements:
All return nodes in the following order: CaseName, Beta, Delta, CaseName, Beta, Delta. This order matches the original XML node structure. What XPath statement can I use with the "or" operator to return the nodes in the order that I desire?
I'm using C# as my development environment.
Upvotes: 0
Views: 333
Reputation: 167516
In terms of XPath, you need to understand that XPath 1.0 only knows unordered node sets so with //foo | //bar
you get a set of foo
and bar
element nodes. Most implementations then return the result in document order.
If you want to be able to define the order you need to use XPath 2.0 (or XQuery 1.0) where the data model knows ordered sequences of nodes (and atomic items), there you could use the comma operator ,
as in //foo, //bar
to get a sequence of foo
and bar
element nodes. However the Microsoft .NET framework class library does not come with an XPath 2.0 implementation, you would need to use to switch to third party solutions like XmlPrime or the .NET version of Saxon 9.
Upvotes: 0
Reputation: 116118
If XPath is not a must, you can use LinqToXml to sort the elements
XDocument xDoc = XDocument.Parse(xmlstring); //or XDocument.Load(filename)
var products = xDoc.Descendants("Product")
.Select(p => p.Elements().OrderBy(e => e.Name.LocalName).ToList())
.ToList();
Or maybe something like this
List<string> names = new List<string>{ "CaseName", "Beta", "Delta" };
XDocument xDoc = XDocument.Parse(xml);
var products = xDoc.Descendants("Product")
.Select(p => p.Elements()
.Where(e => names.Contains(e.Name.LocalName))
.OrderBy(e => names.IndexOf(e.Name.LocalName)).ToList())
.ToList();
Upvotes: 1