| 模式 | 類別 | 存取方式 | 記憶體 | 可讀/可寫 | 導航 | 適用場景 |
|---|---|---|---|---|---|---|
| 推模型 (SAX) | 不支援 | 事件回呼 | 極低 | 唯讀 | 僅前向 | .NET 不直接支援 |
| 拉模型 | XmlReader / XmlTextReader | Pull (Read()) | 極低 (串流) | 唯讀 | 僅前向 | **大型 XML、高效能、單向處理** |
| DOM 模型 | XmlDocument | 樹狀載入 | 高 (全載入記憶體) | 可讀寫 | 隨機 (XPath) | 中小型 XML、需修改/複雜查詢 |
| LINQ to XML | XDocument / XElement | 樹狀載入 (函數式) | 中高 | 可讀寫 | 隨機 + LINQ | **現代首選、語法優雅、型別安全** |
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}");
}
}
}
}
優點:記憶體恆定、速度最快、支援非同步。
缺點:唯讀、無法回溯、程式碼較冗長、錯誤處理複雜。
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、命名空間處理繁瑣。
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");
| 操作 | XmlReader | XmlDocument | XDocument |
|---|---|---|---|
| 完整讀取+解析 | ~120 ms | ~350 ms | ~300 ms |
| 記憶體峰值 | ~2 MB | ~85 MB | ~70 MB |
| XPath/查詢靈活度 | 低 | 高 | 最高 (LINQ) |
| 修改/儲存 | 不可 | 可 | 可 |
XmlReader 未正確處理 `Read()` 迴圈導致漏讀/卡住。XDocument 載入超大檔案造成 LOH 壓力 → 改用 `XmlReader` 分塊處理。