C# · 12月 25, 2021

使用C#按Alpha.Numeric对XML节点排序

假设我生成的XmlDocument具有如下所示的InnerXml: <ORM_O01> <MSH> <MSH.9> <MSG.2>O01</MSG.2> </MSH.9> <MSH.6> <HD.1>13702</HD.1> </MSH.6> </MSH> <ORM_O01.PATIENT> <PID> <PID.18> <CX.1>SecondTestFin</CX.1> </PID.18> <PID.3> <CX.1>108</CX.1> </PID.3> </PID> </ORM_O01.PATIENT></ORM_O01>

如您所见,节点< PID.18>在节点< PID.3>之前. (< MSH.9>也在< MSH.6>之前).

重构我的一代将导致我干净的代码变得非常混乱.

有没有办法对节点进行排序,以便它排序alpha直到它到达最后一个句点然后排序数字(如果最后的值是数字)?

通过“数字排序”我的意思是它将查看整数而不是char的char. (所以18> 3).

解决方法 显而易见的答案是肯定的.

如果这是您想要的结果:

<ORM_O01> <MSH> <MSH.6> <HD.1>13702</HD.1> </MSH.6> <MSH.9> <MSG.2>O01</MSG.2> </MSH.9> </MSH> <ORM_O01.PATIENT> <PID> <PID.3> <CX.1>108</CX.1> </PID.3> <PID.18> <CX.1>SecondTestFin</CX.1> </PID.18> </PID> </ORM_O01.PATIENT></ORM_O01>

那么这堂课就会这样做:(我应该为此付出代价…)

using System;using System.IO;using System.Linq;using System.Xml.Linq;namespace Test{ public class SortXmlFile { XElement rootNode; public SortXmlFile(FileInfo file) { if (file.Exists) rootNode = XElement.Load(file.FullName); else throw new FileNotFoundException(file.FullName); } public XElement SortFile() { SortElements(rootNode); return rootNode; } public void SortElements(XElement root) { bool sortWithNumeric = false; XElement[] children = root.Elements().ToArray(); foreach (XElement child in children) { string name; int value; // does any child need to be sorted by numeric? if (!sortWithNumeric && Sortable(child,out name,out value)) sortWithNumeric = true; child.Remove(); // we’ll re-add it in the sort portion // sorting child’s children SortElements(child); } // re-add children after sorting // sort by name portion,which is either the full name,// or name that proceeds period that has a numeric value after the period. IOrderedEnumerable<XElement> childrenSortedByName = children .OrderBy(child => { string name; int value; Sortable(child,out value); return name; }); XElement[] sortedChildren; // if needed to sort numerically if (sortWithNumeric) { sortedChildren = childrenSortedByName .ThenBy(child => { string name; int value; Sortable(child,out value); return value; }) .ToArray(); } else sortedChildren = childrenSortedByName.ToArray(); // re-add the sorted children foreach (XElement child in sortedChildren) root.Add(child); } public bool Sortable(XElement node,out string name,out int value) { var dot = new char[] { ‘.’ }; name = node.Name.ToString(); if (name.Contains(“.”)) { string[] parts = name.Split(dot); if (Int32.TryParse(parts[1],out value)) { name = parts[0]; return true; } } value = -1; return false; } }}

有人可能会写出这种更清洁和更清洁的东西,但这应该会让你前进.