可排序的 XmlDocument 类






4.88/5 (10投票s)
可以轻松地按多种方法对 XmlDocument 的节点进行排序。
引言
这个类使 XmlDocument 类可排序。实际上,我没有花太多时间去查找是否已经存在类似的东西。我需要它,所以我编写了它。而且,我认为有人可能会觉得这个类有用。
背景
基本上,这个类运行一个 TAXmlSorter 类来排序节点。TAXmlSorter 是一个实现 IComparer<XmlNode> 接口的 abstract 类。其他的比较类都是基于 TAXmlSorter 的。
TAXmlDocument.SortType 枚举
public enum SortType
{
    Ascending,
    Descending
}
TAXmlDocument.TAXmlSorter 抽象类
public abstract class TAXmlSorter:IComparer<XmlNode>
{
    Comparison<XmlNode> comparisonDelegate;
    protected TAXmlSorter(SortType st)
    {
        switch (st)
        {
            case SortType.Ascending:
                comparisonDelegate = CompareAsc;
                break;
            case SortType.Descending:
                comparisonDelegate = CompareDesc;
                break;
        }
    }
     protected abstract int CompareAsc(XmlNode x, XmlNode y);
    protected abstract int CompareDesc(XmlNode x, XmlNode y);
     public abstract void InitArray(XmlNode[] array);
     #region IComparer<XmlNode> Members
     int IComparer<XmlNode>.Compare(XmlNode x, XmlNode y)
    {
        return comparisonDelegate(x, y);
    }
     #endregion
}
我使用了一个比较委托以获得更好的性能。 这样,应用程序将在初始化时确定比较函数,因此它不会每次都检查是否为升序排序。
public sealed class TAXSNodeName : TAXmlSorter 
这个类比较节点名称。
public sealed class TAXSNodeAttribute<AttributeType> : TAXmlSorter
       where AttributeType : IComparable, IConvertible
这个类比较当前节点的属性。
public sealed class TAXSChildCount : TAXmlSorter
这个类比较子节点数量。
public sealed class TAXSAttributeCount : TAXmlSorter
这个类比较属性数量。
public sealed class TAXSInnerText : TAXmlSorter
这个类比较节点的内部文本值(string 比较)。
public sealed class TAXSInnerValue<ValueType> : TAXmlSorter
    where ValueType : IComparable, IConvertible 
这个类比较节点的内部文本值(首先转换为给定的类型)。
public sealed class TAXSMulti : TAXmlSorter
这个类是一个多重比较类。
排序
实际上,这个类没有使用任何特殊的排序算法。它是基于 Array.Sort  函数的。
public void Sort(XmlNode parentNode, TAXmlSorter sorter)
{
    if (parentNode == null)
        throw new ArgumentNullException("parentNode");
    if (sorter == null)
        throw new ArgumentNullException("sorter");
    if (parentNode.OwnerDocument != this)
        throw new Exception(
            "parentNode value is not child of this document");
    //if childcount less than 2 then it is not necessary to sort
    if (parentNode.ChildNodes.Count < 2)
        return;
    //copy the child of parent
    XmlNode[] nodes = new XmlNode[parentNode.ChildNodes.Count];
    for (int i = 0; i < nodes.Length; i++)
        nodes[i] = parentNode.ChildNodes[i];
    
    //call abstract initarray method of sorter
    sorter.InitArray(nodes);
     //call array.sort to sort nodes
    Array.Sort(nodes, sorter);
      //remove all child nodes of parent
    parentNode.InnerXml = "";
     //add sorted nodes
    for (int i = 0; i < nodes.Length; i++)
        parentNode.AppendChild(nodes[i]);
}
Using the Code
XmlFile1.xml 内容
<?xml version="1.0" encoding="utf-8" ?>
<root>
  <q>5</q>
  <s/>
  <a/>
  <a id="1">
    <b>
      <c>123</c>
    </b>
  </a>
  <r num="0.1" id="2">false</r>
  <tolgahan id="0" />
  <tolgahanAlbayrak bool="true" date="01.01.2008 15:13:10" />
  <tolgahanAlbayrak bool="false" date="01.02.2008 15:13:10" />
  <tolgahanAlbayrak bool="false" date="01.01.2008 11:13:10" />
  <zoom/>
  <zoom id="-1"/>
</root>
按节点名称排序
升序
TAXmlDocument doc = new TAXmlDocument();
doc.Load("c:\\xmlfile1.xml");
doc.Sort(doc.SelectSingleNode("root"), new TAXmlDocument.TAXSNodeName() ); 
输出
<?xml version="1.0" encoding="utf-8"?>
<root>
  <a id="1">
    <b>
      <c>
      </c>
    </b>
  </a>
  <a />
  <q>
  </q>
  <r num="0.1" id="2">
  </r>
  <s />
  <tolgahan id="0" />
  <tolgahanAlbayrak bool="false" date="01.01.2008 11:13:10" />
  <tolgahanAlbayrak bool="false" date="01.02.2008 15:13:10" />
  <tolgahanAlbayrak bool="true" date="01.01.2008 15:13:10" />
  <zoom id="-1" />
  <zoom />
</root>
降序
TAXmlDocument doc = new TAXmlDocument();
doc.Load("c:\\xmlfile1.xml");
doc.Sort(doc.SelectSingleNode("root"), 
new TAXmlDocument.TAXSNodeName( TAXmlDocument.SortType.Descending ));
输出
?<?xml version="1.0" encoding="utf-8"?>
<root>
  <zoom />
  <zoom id="-1" />
  <tolgahanAlbayrak bool="true" date="01.01.2008 15:13:10" />
  <tolgahanAlbayrak bool="false" date="01.02.2008 15:13:10" />
  <tolgahanAlbayrak bool="false" date="01.01.2008 11:13:10" />
  <tolgahan id="0" />
  <s />
  <r num="0.1" id="2">
  </r>
  <q>
  </q>
  <a />
  <a id="1">
    <b>
      <c>
      </c>
    </b>
  </a>
</root>
所有比较类在构造函数上都有 SortType (升序或降序)参数。
按属性值排序(如果它是布尔值)
TAXmlDocument doc = new TAXmlDocument();
doc.Load("c:\\xmlfile1.xml");
doc.Sort(doc.SelectSingleNode("root"), 
         new TAXmlDocument.TAXSNodeAttribute<Boolean>( "bool" ));
输出
?<?xml version="1.0" encoding="utf-8"?>
<root>
  <tolgahanAlbayrak bool="false" date="01.02.2008 15:13:10" />
  <tolgahan id="0" />
  <tolgahanAlbayrak bool="false" date="01.01.2008 11:13:10" />
  <zoom id="-1" />
  <zoom />
  <a />
  <s />
  <q>
  </q>
  <r num="0.1" id="2">
  </r>
  <a id="1">
    <b>
      <c>
      </c>
    </b>
  </a>
  <tolgahanAlbayrak bool="true" date="01.01.2008 15:13:10" />
</root>
按属性值排序(如果它是日期)
TAXmlDocument doc = new TAXmlDocument();
doc.Load("c:\\xmlfile1.xml");
doc.Sort(doc.SelectSingleNode("root"), 
         new TAXmlDocument.TAXSNodeAttribute<DateTime>( "date", 
                           TAXmlDocument.SortType.Descending ));
输出
?<?xml version="1.0" encoding="utf-8"?>
<root>
  <tolgahanAlbayrak bool="false" date="01.02.2008 15:13:10" />
  <tolgahanAlbayrak bool="true" date="01.01.2008 15:13:10" />
  <tolgahanAlbayrak bool="false" date="01.01.2008 11:13:10" />
  <zoom id="-1" />
  <zoom />
  <tolgahan id="0" />
  <s />
  <q>
  </q>
  <a />
  <r num="0.1" id="2">
  </r>
  <a id="1">
    <b>
      <c>
      </c>
    </b>
  </a>
</root>
按子节点数量排序
TAXmlDocument doc = new TAXmlDocument();
doc.Load("c:\\xmlfile1.xml");
doc.Sort(doc.SelectSingleNode("root"), 
    new TAXmlDocument.TAXSChildCount());
输出
?<?xml version="1.0" encoding="utf-8"?>
<root>
  <tolgahanAlbayrak bool="true" date="01.01.2008 15:13:10" />
  <zoom id="-1" />
  <tolgahanAlbayrak bool="false" date="01.02.2008 15:13:10" />
  <zoom />
  <tolgahanAlbayrak bool="false" date="01.01.2008 11:13:10" />
  <tolgahan id="0" />
  <s />
  <a />
  <q>5</q>
  <a id="1">
    <b>
      <c>123</c>
    </b>
  </a>
  <r num="0.1" id="2">false</r>
</root>
按属性数量排序
TAXmlDocument doc = new TAXmlDocument();
doc.Load("c:\\xmlfile1.xml");
doc.Sort(doc.SelectSingleNode("root"), 
    new TAXmlDocument.TAXSAttributeCount());
输出
?<?xml version="1.0" encoding="utf-8"?>
<root>
  <a />
  <zoom />
  <q>5</q>
  <s />
  <zoom id="-1" />
  <tolgahan id="0" />
  <a id="1">
    <b>
      <c>123</c>
    </b>
  </a>
  <r num="0.1" id="2">false</r>
  <tolgahanAlbayrak bool="true" date="01.01.2008 15:13:10" />
  <tolgahanAlbayrak bool="false" date="01.02.2008 15:13:10" />
  <tolgahanAlbayrak bool="false" date="01.01.2008 11:13:10" />
</root>
按内部值排序(尝试排序整数值)
TAXmlDocument doc = new TAXmlDocument();
doc.Load("c:\\xmlfile1.xml");
doc.Sort(doc.SelectSingleNode("root"), 
    new TAXmlDocument.TAXSInnerValue<Int32>());
输出
<?xml version="1.0" encoding="utf-8"?>
<root>
  <tolgahanAlbayrak bool="true" date="01.01.2008 15:13:10" />
  <zoom id="-1" />
  <tolgahanAlbayrak bool="false" date="01.02.2008 15:13:10" />
  <zoom />
  <tolgahanAlbayrak bool="false" date="01.01.2008 11:13:10" />
  <s />
  <tolgahan id="0" />
  <a />
  <r num="0.1" id="2">false</r>
  <q>5</q>
  <a id="1">
    <b>
      <c>123</c>
    </b>
  </a>
</root>
多重排序
(尝试首先按布尔属性“bool”降序排序,然后按日期属性“date”升序排序,然后按内部值排序)
TAXmlDocument doc = new TAXmlDocument();
doc.Load("c:\\xmlfile1.xml");
doc.Sort(doc.SelectSingleNode("root"),
    new TAXmlDocument.TAXSMulti(
        new TAXmlDocument.TAXSNodeAttribute<Boolean>("bool",
        TAXmlDocument.SortType.Descending),
        new TAXmlDocument.TAXSNodeAttribute<DateTime>("date"),
        new TAXmlDocument.TAXSInnerValue<Int32>()
    )
);
输出
?<?xml version="1.0" encoding="utf-8"?>
<root>
  <tolgahanAlbayrak bool="true" date="01.01.2008 15:13:10" />
  <r num="0.1" id="2">false</r>
  <zoom id="-1" />
  <zoom />
  <s />
  <tolgahan id="0" />
  <a />
  <q>5</q>
  <a id="1">
    <b>
      <c>123</c>
    </b>
  </a>
  <tolgahanAlbayrak bool="false" date="01.01.2008 11:13:10" />
  <tolgahanAlbayrak bool="false" date="01.02.2008 15:13:10" />
</root> 
历史
- 2009年2月2日:Andrew Chudley 添加了对子元素其中一个子值进行排序的操作
- 2009年1月13日:首次发布


