適用場景
- 大型 XML 檔案(避免 DOM 載入整棵樹佔用記憶體)
- 僅需提取特定節點值,不需完整物件模型
- 效能敏感、單向讀取場景
核心代碼
using System.Xml;
public KSBMCONFIG ReadConfig(string XMLConfigFile)
{
KSBMCONFIG conf = new KSBMCONFIG();
try
{
using (XmlTextReader reader = new XmlTextReader(XMLConfigFile))
{
while (reader.Read())
{
// 遇到結束元素 結束讀取
if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "KSBM")
break;
// 僅處理開始元素
if (reader.IsStartElement("ServerPath"))
{
reader.Read(); // 移至文本節點
conf.ServerPath = reader.Value;
}
else if (reader.IsStartElement("SmtpServer"))
{
reader.Read();
conf.SMTPServer = reader.Value;
}
else if (reader.IsStartElement("ConnectString"))
{
reader.Read();
conf.ConnectString = reader.Value;
}
}
}
return conf;
}
catch
{
// 異常時返回空配置
conf.ConnectString = conf.ServerPath = conf.SMTPServer = "";
return conf;
}
}
關鍵 API 對照
| 方法/屬性 | 用途 |
Read() | 移至下一節點,返回 bool 是否成功 |
NodeType | 當前節點類型:Element、Text、EndElement、Attribute 等 |
Name | 元素/屬性名稱 |
Value | 文本節點或屬性的值 |
IsStartElement(name) | 判斷是否為指定名稱的開始標籤 |
GetAttribute(name) | 直接讀取屬性值(無需移動指標) |
現代替代方案
1. XmlReader.Create (推薦)
var settings = new XmlReaderSettings { IgnoreWhitespace = true };
using (XmlReader reader = XmlReader.Create(filePath, settings))
{
while (reader.Read())
{
if (reader.IsStartElement("ServerPath"))
conf.ServerPath = reader.ReadElementContentAsString();
}
}
2. LINQ to XML (XDocument) - 適合中小檔案
var doc = XDocument.Load(filePath);
conf.ServerPath = doc.Root.Element("ServerPath")?.Value;
conf.SMTPServer = doc.Root.Element("SmtpServer")?.Value;
conf.ConnectString = doc.Root.Element("ConnectString")?.Value;
3. System.Text.Json ( .NET 6+ ) - 配合 XmlSerializer
// 需先將 XML 反序列化為 POCO
var serializer = new XmlSerializer(typeof(KSBMCONFIG));
using (var fs = File.OpenRead(filePath))
conf = (KSBMCONFIG)serializer.Deserialize(fs);
選型建議
- 超大檔/流式/低記憶體:
XmlReader
- 結構固定/強類型/開發效率:
XmlSerializer / XDocument
- 動態查詢/轉換:
XDocument + LINQ
- 避免:舊版
XmlTextReader、XmlDocument (DOM,記憶體佔用大)