幾種xml讀取方法比較


背景

這幾天手上有個活,解析xml,眾所周知xml的解析方法有:

  1. DOM
  2. SAX
  3. linq to xml
  4. plinq

測試用xml和生成代碼

 1 static void CreateFile()
 2         {
 3             int N = 5000000;
 4             Random rand = new Random();
 5             using (var writer = new XmlTextWriter("VeryHugeXmlFile.xml", Encoding.UTF8))
 6             {
 7                 writer.Formatting = Formatting.Indented;
 8 
 9                 writer.WriteStartDocument();
10                 writer.WriteStartElement("Root");
11                 for (int count = 1; count <= N; count++)
12                 {
13                     writer.WriteStartElement("Person");
14                     writer.WriteElementString("Id", count.ToString());
15                     writer.WriteElementString("Name", rand.Next().ToString());
16                     writer.WriteElementString("Sex", rand.Next(0, 2) == 0 ? "" : "");
17                     writer.WriteElementString("Age", rand.Next(1, 101).ToString());
18                     writer.WriteEndElement();
19                 }
20                 writer.WriteEndElement();
21                 writer.WriteEndDocument();
22             }
23         }

之后會生成類似於下面的xml文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <Root>
 3   <Person>
 4     <Id>1</Id>
 5     <Name>897639886</Name>
 6     <Sex></Sex>
 7     <Age>80</Age>
 8   </Person>
 9   <Person>
10     <Id>2</Id>
11     <Name>2012162696</Name>
12     <Sex></Sex>
13     <Age>60</Age>
14   </Person>
15   <Person>

xml下載鏈接

測試代碼

統計時間(只是粗略統計了一下運行時間)

1 static void Watch(Action<string> way, string file)
2         {
3             Stopwatch watch = new Stopwatch();
4 
5             watch.Start();
6             way(file);
7             watch.Stop();
8             Console.WriteLine(watch.ElapsedMilliseconds);
9         }

DOM

1 static void DomWay(string file)
2         {
3             XmlDocument doc = new XmlDocument();
4             doc.Load(file);
5 
6             Console.WriteLine(doc.SelectNodes(YOUR-XPATH-HERE).Count);
7 
8         }

SAX

 1 static void SaxWay(string file)
 2         {
 3             using (XmlTextReader reader = new XmlTextReader(file))
 4             {
 5                 int count = 0;
 6                 while (reader.Read())
 7                 {
 8                     if (reader.Name == "Person" && reader.NodeType == XmlNodeType.Element)
 9                     {
10                         reader.Read();
11                         reader.Read();
12 
13                         int? Id = null;
14                         int? name = null;
15                         string sex = null;
16                         int? age = null;
17 
18                         if (reader.Name == "Id")
19                         {
20                             Id = reader.ReadElementContentAsInt();
21                             reader.Read();
22                             name = reader.ReadElementContentAsInt();
23                             reader.Read();
24                             sex = reader.ReadElementContentAsString();
25                             reader.Read();
26                             age = reader.ReadElementContentAsInt();
27                             reader.Read();
28                         }
29 
30                         if (reader.Name == "Person" && reader.NodeType == XmlNodeType.EndElement)
31                             reader.Read();
32 
33                         if (Id != null && name != null && sex != null && age != null)
34                         {
35                             if (在此設置自定義過濾條件)
36                                 count++;
37                         }
38                     }
39                 }
40 
41                 Console.WriteLine(count);
42             }
43         }

 

Linq to Xml

 1 static void LinqWay(string file)
 2         {
 3             var root = XElement.Load(file);
 4             var person = from p in root.Elements("Person") 
7
where 在此設置自定義過濾條件
8
select id; 9 Console.WriteLine(person.Count()); 10 }

PLinq to Xml

 1 static void PLinqWay(string file)
 2         {
 3             var root = XElement.Load(file);
 4             var person = from p in root.Elements("Person").AsParallel() 
7
where 在此設置自定義過濾條件
8
select id; 9 Console.WriteLine(person.Count()); 10 }

 統計結果

 在6核8G內存機器上,測試程序設置為x64和release模式,在xml查詢結果相同的情況下取運行時間(ms),沒有詳細采集cpu和內存數據

兩個模式,區別是加了一個素數的判斷。

 

 

Id > 5000 && sex == "男"

&& age > 15 && age < 50

Id > 5000 && sex == "男"

&& age > 15 && age < 50 && IsPrimeInt(name)

sax 13857 40010
linq 27336 53760
plinq 24550 28846
dom 31737 0

由於dom模式本身xpath模式不支持嵌入函數,所以第二個測試沒有采集結果。

 

小結

sax:速度優先,內存占用少,但是代碼復雜度高。

linq:速度較sax慢,但是代碼優雅,維護容易

plinq:同上,在非計算密集型模式中,不比linq和sax模式好多少。但是在計算密集下,后來居上

dom:速度落后,但是原生支持xpath,代碼最優雅。

 

內存方面僅是肉眼觀察了任務管理器,sax基本內存曲線為水平線,而linq&plinq在load的時候分配內存,可能其內部也是用了dom。

倉促行文,其中必有不實之處,往各位勞神指教。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM