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

前端之家收集整理的这篇文章主要介绍了使用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;
        }
    }
}

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

猜你在找的C#相关文章