可排序的 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日:首次发布