private void ReorderChildNodes(XElement element)
{
List<NodeCollection> nodeCollections = new List<NodeCollection>();
var children = element.Nodes();
// This indicates if last element matched ChildNodeNames
bool inMatchingChildBlock = false;
// This value changes each time a non matching ChildNodeName is reached ensuring that only sortable elements are reordered
int childBlockIndex = 0;
NodeCollection currentNodeCollection = null;
// Run through children
foreach (var child in children)
{
if (currentNodeCollection == null)
{
currentNodeCollection = new NodeCollection();
nodeCollections.Add(currentNodeCollection);
}
if (child.NodeType == XmlNodeType.Element)
{
XElement childElement = (XElement)child;
var isMatchingChild = ChildNodeNames.Any(match => match.IsMatch(childElement.Name));
if (isMatchingChild == false || inMatchingChildBlock == false)
{
childBlockIndex++;
inMatchingChildBlock = isMatchingChild;
}
if (isMatchingChild)
{
currentNodeCollection.SortAttributeValues = SortByAttributes.Select(x => x.GetValue(childElement)).ToArray();
}
currentNodeCollection.BlockIndex = childBlockIndex;
}
currentNodeCollection.Nodes.Add(child);
if (child.NodeType == XmlNodeType.Element)
currentNodeCollection = null;
}
if (currentNodeCollection != null)
currentNodeCollection.BlockIndex = childBlockIndex + 1;
// sort node list
nodeCollections = nodeCollections.OrderBy(x => x).ToList();
// replace the element's nodes
element.ReplaceNodes(nodeCollections.SelectMany(nc => nc.Nodes));
}