從基礎(chǔ)讀寫(xiě)到高級(jí)技巧詳解C#操作XML的全指南
引言
在 .NET 開(kāi)發(fā)生態(tài)中,XML(可擴(kuò)展標(biāo)記語(yǔ)言)雖不如 JSON 那般“時(shí)髦”,但在配置文件(如 app.config、.csproj)、數(shù)據(jù)交換、遺留系統(tǒng)集成等場(chǎng)景中依然廣泛存在。C# 提供了多種方式操作 XML,從簡(jiǎn)單快捷的 XmlDocument 到現(xiàn)代高效的 XDocument(LINQ to XML),再到底層流式處理的 XmlReader/XmlWriter。
然而,很多開(kāi)發(fā)者面對(duì)這些 API 時(shí)常常感到困惑:
- 該用哪種方式?
- 性能如何?
- 如何優(yōu)雅地增刪改查?
- 怎樣避免常見(jiàn)坑點(diǎn)?
本文將帶你系統(tǒng)梳理 C# 操作 XML 的三大主流方式,結(jié)合實(shí)戰(zhàn)代碼,一次講透核心用法與最佳實(shí)踐。
一、三種主流 XML 操作方式概覽
| 方式 | 類型 | 特點(diǎn) | 適用場(chǎng)景 |
|---|---|---|---|
| XmlDocument | DOM(文檔對(duì)象模型) | 老牌 API,.NET Framework 早期主力 | 小型文檔、需要兼容舊項(xiàng)目 |
| XDocument / XElement | LINQ to XML | 現(xiàn)代、簡(jiǎn)潔、支持 LINQ 查詢 | 推薦用于新項(xiàng)目 |
| XmlReader / XmlWriter | 流式(SAX 風(fēng)格) | 內(nèi)存占用低、只讀/只寫(xiě)、高性能 | 大型 XML 文件處理 |
建議:新項(xiàng)目?jī)?yōu)先使用 XDocument;超大文件(>100MB)考慮 XmlReader。
二、XDocument:現(xiàn)代 C# 操作 XML 的首選
1. 創(chuàng)建 XML
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Books",
new XElement("Book",
new XAttribute("Id", "1"),
new XElement("Title", "C# in Depth"),
new XElement("Author", "Jon Skeet")
)
)
);
doc.Save("books.xml");
2. 讀取與查詢(LINQ 強(qiáng)大之處)
var doc = XDocument.Load("books.xml");
// 查詢所有書(shū)名
var titles = doc.Descendants("Title")
.Select(t => t.Value)
.ToList();
// 查詢 Id=1 的書(shū)
var book = doc.Descendants("Book")
.FirstOrDefault(b => b.Attribute("Id")?.Value == "1");
Console.WriteLine(book?.Element("Title")?.Value);
3. 修改與刪除
// 添加新書(shū)
doc.Root?.Add(
new XElement("Book",
new XAttribute("Id", "2"),
new XElement("Title", "Effective C#"),
new XElement("Author", "Bill Wagner")
)
);
// 刪除某本書(shū)
var bookToDelete = doc.Descendants("Book")
.FirstOrDefault(b => b.Attribute("Id")?.Value == "1");
bookToDelete?.Remove();
doc.Save("books.xml");
優(yōu)勢(shì):語(yǔ)法簡(jiǎn)潔、鏈?zhǔn)秸{(diào)用、天然支持 LINQ,代碼可讀性極高。
三、XmlDocument:經(jīng)典但略顯笨重
雖然 XmlDocument 是 .NET 1.0 時(shí)代的產(chǎn)物,但在維護(hù)老系統(tǒng)時(shí)仍會(huì)遇到。
var xmlDoc = new XmlDocument();
xmlDoc.Load("books.xml");
// 查找節(jié)點(diǎn)
XmlNode? bookNode = xmlDoc.SelectSingleNode("http://Book[@Id='1']");
if (bookNode != null)
{
var title = bookNode["Title"]?.InnerText;
Console.WriteLine(title);
}
// 添加節(jié)點(diǎn)
XmlElement newBook = xmlDoc.CreateElement("Book");
newBook.SetAttribute("Id", "3");
var titleElem = xmlDoc.CreateElement("Title");
titleElem.InnerText = "Pro C#";
newBook.AppendChild(titleElem);
xmlDoc.DocumentElement?.AppendChild(newBook);
xmlDoc.Save("books.xml");
缺點(diǎn):API 冗長(zhǎng),需頻繁類型轉(zhuǎn)換,不支持 LINQ。
四、XmlReader / XmlWriter:處理大型 XML 的利器
當(dāng) XML 文件達(dá)到數(shù)百 MB 甚至 GB 級(jí)別時(shí),DOM 方式會(huì)因加載整個(gè)文檔到內(nèi)存而崩潰。此時(shí)應(yīng)使用流式處理。
使用 XmlReader 逐節(jié)點(diǎn)讀取
using var reader = XmlReader.Create("huge_file.xml");
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Book")
{
// 只處理 Book 節(jié)點(diǎn),不加載全文檔
var id = reader.GetAttribute("Id");
// 進(jìn)一步解析子元素(可配合 ReadSubtree)
}
}
使用 XmlWriter 高效寫(xiě)入
using var writer = XmlWriter.Create("output.xml", new XmlWriterSettings { Indent = true });
writer.WriteStartDocument();
writer.WriteStartElement("Books");
writer.WriteStartElement("Book");
writer.WriteAttributeString("Id", "1");
writer.WriteElementString("Title", "Clean Code");
writer.WriteEndElement(); // Book
writer.WriteEndElement(); // Books
writer.WriteEndDocument();
優(yōu)勢(shì):內(nèi)存占用恒定,適合大數(shù)據(jù)量場(chǎng)景。
代價(jià):只能順序讀寫(xiě),無(wú)法隨機(jī)訪問(wèn)或修改已有內(nèi)容。
五、常見(jiàn)陷阱與最佳實(shí)踐
1. 忘記處理命名空間(Namespace)
XML 帶命名空間時(shí),直接用 Descendants("Name") 會(huì)查不到!
<book xmlns="http://example.com/books"> <title>C# Guide</title> </book>
正確做法:
XNamespace ns = "http://example.com/books"; var title = doc.Descendants(ns + "title").First().Value;
2. 字符編碼問(wèn)題
保存 XML 時(shí)指定編碼:
doc.Save(new StreamWriter("file.xml", false, Encoding.UTF8));
// 或使用 XDocument + SaveOptions
3. 安全性:警惕 XXE 攻擊
在解析不受信任的 XML 時(shí),務(wù)必禁用 DTD 和外部實(shí)體:
var settings = new XmlReaderSettings
{
DtdProcessing = DtdProcessing.Prohibit,
XmlResolver = null
};
using var reader = XmlReader.Create(stream, settings);
六、選型建議總結(jié)
| 需求 | 推薦方案 |
|---|---|
| 新項(xiàng)目、中小型 XML | ? XDocument(LINQ to XML) |
| 維護(hù)老系統(tǒng) | ?? XmlDocument(兼容性優(yōu)先) |
| 超大文件(>100MB) | ?? XmlReader / XmlWriter |
| 需要高性能只讀解析 | XmlReader |
| 需要復(fù)雜查詢和動(dòng)態(tài)構(gòu)建 | XDocument |
結(jié)語(yǔ)
C# 對(duì) XML 的支持歷經(jīng)多年演進(jìn),已形成一套完整、靈活且高效的工具鏈。掌握 XDocument 的現(xiàn)代用法,了解 XmlDocument 的歷史背景,熟悉 XmlReader 的性能優(yōu)勢(shì),你就能在任何 XML 場(chǎng)景下游刃有余。
記住:沒(méi)有“最好”的 API,只有“最合適”的選擇。根據(jù)你的數(shù)據(jù)規(guī)模、性能要求和維護(hù)成本,做出明智決策,才是專業(yè)開(kāi)發(fā)者的標(biāo)志。
到此這篇關(guān)于從基礎(chǔ)讀寫(xiě)到高級(jí)技巧詳解C#操作XML的全指南的文章就介紹到這了,更多相關(guān)C#操作XML內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
將Qt項(xiàng)目升級(jí)到Qt6吐血經(jīng)驗(yàn)總結(jié)
很多朋友向小編反饋將Qt項(xiàng)目升級(jí)到Qt6頻繁出錯(cuò),該如何處理呢,今天小編給大家?guī)?lái)了將Qt項(xiàng)目升級(jí)到Qt6吐血經(jīng)驗(yàn)總結(jié),感興趣的朋友一起看看吧2021-07-07
c#訪問(wèn)this關(guān)鍵字和base關(guān)鍵字示例
this關(guān)鍵字引用類的當(dāng)前實(shí)例。靜態(tài)成員方法中不能使用this關(guān)鍵字,this關(guān)鍵字只能在實(shí)例構(gòu)造函數(shù)、實(shí)例方法或?qū)嵗L問(wèn)器中使用。base關(guān)鍵字用于從派生類中訪問(wèn)基類的成員。下面學(xué)習(xí)一下這二個(gè)關(guān)鍵字的使用方法2014-01-01
C#/VB.NET實(shí)現(xiàn)HTML轉(zhuǎn)為XML的示例代碼
可擴(kuò)展標(biāo)記語(yǔ)言(XML)文件是一種標(biāo)準(zhǔn)的文本文件,它使用特定的標(biāo)記來(lái)描述文檔的結(jié)構(gòu)以及其他特性。本文將利用C#實(shí)現(xiàn)HTML轉(zhuǎn)為XML,需要的可以參考一下2022-06-06
基于C#實(shí)現(xiàn)SM2加簽驗(yàn)簽工具
這篇文章主要為大家詳細(xì)介紹了如何基于C#實(shí)現(xiàn)一個(gè)SM2加簽驗(yàn)簽工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-10-10
使用C#的aforge類庫(kù)識(shí)別驗(yàn)證碼實(shí)例
這篇文章主要介紹了使用C#的aforge類庫(kù)識(shí)別驗(yàn)證碼實(shí)例,aforge類庫(kù)是一個(gè)非常強(qiáng)大的類庫(kù),包括計(jì)算機(jī)視覺(jué)與人工智能、圖像處理、神經(jīng)網(wǎng)絡(luò)、遺傳算法、機(jī)器學(xué)習(xí)、機(jī)器人等領(lǐng)域,需要的朋友可以參考下2014-08-08
C#使用WMI實(shí)現(xiàn)監(jiān)聽(tīng)進(jìn)程的啟動(dòng)和關(guān)閉
Windows Management Instrumentation(WMI)是用于管理基于 Windows 操作系統(tǒng)的數(shù)據(jù)和操作的基礎(chǔ)結(jié)構(gòu),本文將使用WMI實(shí)現(xiàn)監(jiān)聽(tīng)進(jìn)程的啟動(dòng)和關(guān)閉,感興趣的可以了解下2024-01-01
關(guān)于C#生成MongoDB中ObjectId的實(shí)現(xiàn)方法
本篇文章小編為大家介紹,關(guān)于C#生成MongoDB中ObjectId的實(shí)現(xiàn)方法。需要的朋友參考下2013-04-04
C#實(shí)現(xiàn)排列組合算法完整實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)排列組合算法的完整實(shí)例,文中實(shí)例主要展示了排列循環(huán)方法和排列堆棧方法,需要的朋友可以參考下2014-09-09

