首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# XML 解析三大模式深度比較:XmlReader、XmlDocument、LINQ to XML

     編輯:關於C語言

三大解析模式架構

模式類別存取方式記憶體可讀/可寫導航適用場景
推模型 (SAX)不支援事件回呼極低唯讀僅前向.NET 不直接支援
拉模型XmlReader / XmlTextReaderPull (Read())極低 (串流)唯讀僅前向**大型 XML、高效能、單向處理**
DOM 模型XmlDocument樹狀載入高 (全載入記憶體)可讀寫隨機 (XPath)中小型 XML、需修改/複雜查詢
LINQ to XMLXDocument / XElement樹狀載入 (函數式)中高可讀寫隨機 + LINQ**現代首選、語法優雅、型別安全**

1. XmlReader (拉模型) - 高效能串流處理


using System.Xml;

public void ProcessLargeXml(string filePath)
{
    var settings = new XmlReaderSettings
    {
        Async = true,
        IgnoreWhitespace = true,
        // ValidationType = ValidationType.Schema, schemas...
    };

    using (var reader = XmlReader.Create(filePath, settings))
    {
        while (await reader.ReadAsync())
        {
            if (reader.NodeType == XmlNodeType.Element && reader.Name == "Order")
            {
                string id = reader.GetAttribute("Id");
                decimal amount = 0;

                // 讀取子元素
                while (await reader.ReadAsync())
                {
                    if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "Order") break;
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "Amount")
                    {
                        amount = await reader.ReadElementContentAsAsync();
                    }
                }
                // 處理單筆訂單...
                Console.WriteLine($"Order {id}: {amount:C}");
            }
        }
    }
}

優點:記憶體恆定、速度最快、支援非同步。
缺點:唯讀、無法回溯、程式碼較冗長、錯誤處理複雜。

2. XmlDocument (DOM) - 傳統樹狀操作


using System.Xml;

var doc = new XmlDocument();
doc.Load("orders.xml"); // 或 LoadXml(string)

// XPath 查詢
XmlNodeList orders = doc.SelectNodes("//Order[@Status='Shipped']");
foreach (XmlNode order in orders)
{
    string id = order.Attributes["Id"]?.Value;
    string amount = order.SelectSingleNode("Amount")?.InnerText;
    // 修改
    order.Attributes["Processed"].Value = "true";
}
doc.Save("orders_updated.xml");

優點:隨機存取、XPath 強大、可修改/建立新節點。
缺點:整份文件載入記憶體、大檔案易 OOM、命名空間處理繁瑣。

3. LINQ to XML (XDocument) - 現代首選


using System.Xml.Linq;

var doc = XDocument.Load("orders.xml");

// 查詢 + 投射
var shippedOrders = doc.Descendants("Order")
    .Where(o => (string)o.Attribute("Status") == "Shipped")
    .Select(o => new
    {
        Id = (string)o.Attribute("Id"),
        Amount = (decimal)o.Element("Amount"),
        Customer = (string)o.Element("Customer")?.Element("Name")
    })
    .ToList();

// 修改
foreach (var order in doc.Descendants("Order")
    .Where(o => (string)o.Attribute("Status") == "Pending"))
{
    order.SetAttributeValue("Status", "Processing");
    order.Element("ProcessedDate")?.SetValue(DateTime.Now);
}

// 建立新文件
var newDoc = new XDocument(
    new XDeclaration("1.0", "utf-8", "yes"),
    new XElement("Orders",
        from o in shippedOrders
        select new XElement("Order",
            new XAttribute("Id", o.Id),
            new XElement("Amount", o.Amount),
            new XElement("Customer", o.Customer)
        )
    )
);
newDoc.Save("shipped_orders.xml");

優點:函數式語法、強型別轉換 (`(string)element`)、命名空間支援優雅 (`XNamespace`)、建構文件直觀 (`new XElement(...)`)。
缺點:同樣載入完整樹狀結構,超大檔案仍有記憶體壓力。

命名空間處理比較


// XmlDocument: 較繁瑣
var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ns", "https://example.com/orders");
var nodes = doc.SelectNodes("//ns:Order", nsmgr);

// LINQ to XML: 直觀
XNamespace ns = "https://example.com/orders";
var orders = doc.Descendants(ns + "Order");

效能基準參考 (10MB XML, 10萬節點)

操作XmlReaderXmlDocumentXDocument
完整讀取+解析~120 ms~350 ms~300 ms
記憶體峰值~2 MB~85 MB~70 MB
XPath/查詢靈活度低高最高 (LINQ)
修改/儲存不可可可

選擇決策樹

  1. 檔案 > 50MB 或記憶體受限 → XmlReader (必要時搭配 `XmlWriter` 邊讀邊寫轉換)。
  2. 需複雜 XPath、修改文件、檔案 < 50MB → XDocument (LINQ to XML)。
  3. 維護舊代碼、需 `XmlDocument` 特定 API → 繼續用 XmlDocument。
  4. 單純序列化/反序列化物件 → System.Text.Json / XmlSerializer (勿手寫 XML)。

常見陷阱

  • XmlReader 未正確處理 `Read()` 迴圈導致漏讀/卡住。
  • 預設不驗證 Schema,惡意 XML 可能導致實體擴充攻擊 (XXE) → 設定 `XmlReaderSettings.DtdProcessing = DtdProcessing.Prohibit`。
  • XDocument 載入超大檔案造成 LOH 壓力 → 改用 `XmlReader` 分塊處理。
  • 命名空間前綴不一致導致 XPath 查不到 → 善用 `XNamespace`。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved