LINQ to XML: What is the most efficient way to move nodes up and down

I need to move the sibling nodes before and after certain nodes. Here is the im code that works with

<tabs> <tab> <name>Overview</name> </tab> <tab> <name>Testing</name> </tab> <tab> <name>Performance</name> </tab> <tab> <name>Braking</name> </tab> </tabs> 

I would like to move the tab with testing in it above the Overview. How do I do this using linq for XML?

+6
c # xml linq linq-to-xml
source share
4 answers

Sorry, these are VB.NET and XML Literals, but this can be done in the old school in C #. The idea here is to use the Reverse extension method:

 Sub Main() Dim tab = <tabs> <tab> <name>Overview</name> </tab> <tab> <name>Testing</name> </tab> <tab> <name>Performance</name> </tab> <tab> <name>Braking</name> </tab> </tabs> Console.WriteLine(SwapElements("Testing", "Performance", tab).ToString) Console.ReadLine() End Sub Function SwapElements(ByVal firstElement As String, ByVal secondElement As String, ByVal tab As XElement) As XElement Dim swapped = tab.Elements.Where(Function(e) e.Value = firstElement Or e.Value = secondElement).Reverse Dim middle = tab.Elements.SelectMany(Function(e) e.ElementsAfterSelf.Where(Function(f) e.Value = firstElement).TakeWhile(Function(g) g.Value <> secondElement)) swapped.ElementAt(0).AddAfterSelf(middle) Return <<%= tab.Name %>> <%= tab.Elements.Select(Function(e) e.ElementsBeforeSelf.Where(Function(f) e.Value = firstElement)) %> <%= swapped %> <%= tab.Elements.Select(Function(e) e.ElementsAfterSelf.Where(Function(f) e.Value = secondElement)) %> </> End Function 
+2
source share

You can move elements by deleting them, and then reinserting them in the desired position:

 var doc = XDocument.Parse(@"<tabs>...</tabs>"); var tab = doc.Root.Elements().ElementAt(1); tab.Remove(); doc.Root.AddFirst(tab); 

Alternatively, you can create a new document from existing elements in the desired order:

 var doc = XDocument.Parse(@"<tabs>...</tabs>"); var tabs = doc.Root.Elements(); var result = new XDocument( new XElement("tabs", tabs.ElementAt(1), tabs.ElementAt(0), tabs.ElementAt(2))); 

I have not tested it, but this may work:

 void Swap(XElement a, XElement b) { var c = new XElement("dummy"); a.ReplaceWith(c); b.ReplaceWith(a); c.ReplaceWith(b); } 
+3
source share

You can use something like:

  var tests = from node in doc.Descendants("name") where node.Value == "Testing" select node; var test = tests.Single(); var tab = test.Parent; var tabs = tab.Parent; tab.Remove(); tabs.AddFirst(tab); 

Not sure which part of your XML structure is installed / known.

+1
source share

I know this post is old, but today I ran into the same problem and ended up resolving it like this:

 private void SwapXNodes(bool up, int inUniqueID) { XElement currNode = DocumentManager.xMainDocument.XPathSelectElement("//*[@UniqueID='" + inUniqueID + "']"); // find if (up) { if (currNode.PreviousNode != null) { XElement xPrevious = new XElement((XElement)currNode.PreviousNode); // copy of previous node currNode.PreviousNode.ReplaceWith(currNode); // previous node equal to me currNode.ReplaceWith(xPrevious); // Now I should be equal to previous node } } else { if (currNode.NextNode != null) { XElement xNext = new XElement((XElement)currNode.NextNode); // copy of Next node currNode.NextNode.ReplaceWith(currNode); // Next node equal to me currNode.ReplaceWith(xNext); // Now I should be equal to Next node copy } } } 
+1
source share

All Articles