C#中XmlDocument类如何读取和写入XML文件?

来源:AI智能体作者:辉辉头衔:草根站长
导读:本期聚焦于小伙伴创作的《C#中XmlDocument类如何读取和写入XML文件?》,敬请观看详情。把一段格式混乱的字符串硬塞进XmlDocument却报错,往往是因为忽略了编码声明与根节点约束。XmlDocument作为C#老牌DOM解析器,将XML映射为树状节点对象,适合需要随机修改节点的场景。它提供Load读文件、LoadXml读字符串、CreateElement造节点、AppendChild挂子树与Save落盘等方法。相比轻量的XDocument,XmlDocument在旧框架与严格节点顺序控制上更稳,但内存占用偏高。掌握命名空间处理和转义规则,才能避免特殊字符写入失败。

在C#桌面与后台服务开发中,操作XML配置或报文是常见任务。XmlDocument是.NET框架提供的基于W3C DOM标准的XML文档对象模型,它将整份XML加载到内存形成节点树,允许程序任意遍历、查询、新增、删除与修改节点,最后写回文件或流。理解它的核心类和常用方法,是处理传统系统对接的基础。

C#中XmlDocument类如何读取和写入XML文件?

一、XmlDocument核心概念

XmlDocument位于System.Xml命名空间,使用前需添加using引用。它本身代表整个XML文档,内部通过XmlNode作为抽象基类,派生出XmlElement(元素)、XmlAttribute(属性)、XmlText(文本)等具体节点类型。文档必须拥有且仅有唯一根元素,所有业务节点挂在根下。

与后来推出的XDocument(LINQ to XML)不同,XmlDocument强调显式的节点创建与挂载,例如用CreateElement生成元素,用AppendChild建立父子关系。这种方式虽然代码稍长,但在需要精确控制节点顺序、处理XML命名空间或兼容老旧代码时依然可靠。下面是一个最基础的加载示例:

using System;
using System.Xml;

class Demo
{
    static void Main()
    {
        XmlDocument doc = new XmlDocument();
        // 从字符串加载XML,注意根节点必须存在
        doc.LoadXml("<root><item>测试</item></root>");
        XmlElement root = doc.DocumentElement;
        Console.WriteLine(root.Name); // 输出 root
    }
}

二、读取XML文件的常用方式

实际项目中XML常驻留于磁盘。XmlDocument提供了Load方法,可接受文件路径、Stream或TextReader。若文件包含中文,务必确认文件本身是UTF-8编码且与声明一致,否则会出现乱码或解析异常。以下代码演示从本地文件读取并遍历子节点:

using System;
using System.Xml;

class ReadDemo
{
    static void Main()
    {
        XmlDocument doc = new XmlDocument();
        // 加载当前目录下的config.xml
        doc.Load("config.xml");
        XmlNodeList nodes = doc.SelectNodes("/root/item");
        if (nodes != null)
        {
            foreach (XmlNode node in nodes)
            {
                Console.WriteLine(node.InnerText);
            }
        }
    }
}

除了直接遍历,XmlDocument支持XPath查询。SelectSingleNode可定位唯一节点,SelectNodes返回集合。XPath中若遇命名空间,需配合XmlNamespaceManager,否则查不到节点。很多初学者在带ns前缀的XML上卡住,就是漏了管理器注册这一步。

读取属性也很简单:通过XmlAttributeCollection或Element.GetAttribute。当节点可能不存在时,先判空再取InnerText,能避免空引用异常。对于深层嵌套,建议封装一个安全取值方法,减少重复判断代码。

三、创建与写入XML文档

生成新XML时,先构造XmlDocument,用AppendChild加入根,再逐步添加子元素与属性。CreateElement的第二个参数可传命名空间URI,处理带前缀的文档。写完用Save方法输出,可保存到路径或写入StringWriter得到字符串。

using System;
using System.Xml;

class WriteDemo
{
    static void Main()
    {
        XmlDocument doc = new XmlDocument();
        // 创建XML声明
        XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null);
        doc.AppendChild(dec);

        XmlElement root = doc.CreateElement("root");
        doc.AppendChild(root);

        XmlElement item = doc.CreateElement("item");
        item.SetAttribute("id", "1");
        item.InnerText = "第一条数据";
        root.AppendChild(item);

        doc.Save("output.xml");
    }
}

上述代码会生成带声明、根及子项的文件。注意InnerText赋值时,若内容含有<、>、&等符号,XmlDocument会自动转义,无需手动替换,这比字符串拼接安全得多。但如果用InnerXml直接塞片段,则要自己保证片段合法。

需要修改已有节点时,先SelectSingleNode找到目标,改其InnerText或属性,再Save覆盖原文件。由于DOM全量载入,文件很大时会吃内存,此时应考虑XmlReader流式处理。对于普通几兆以内的配置,XmlDocument足够直观好用。

四、特殊字符与命名空间处理

XML规范限定部分字符必须转义。在C#侧,只要走XmlDocument的节点文本赋值,框架会替你完成。但如果你从外部拼好字符串再LoadXml,就要先清理非法字符(如控制符),否则抛异常。下表列出常见转义对应关系:

原始字符XML实体
<&lt;
>&gt;
&&amp;

命名空间方面,假设XML带<ns:root xmlns:ns="http://ipipp.com/schema">,查询时要先建管理器:

using System;
using System.Xml;

class NsDemo
{
    static void Main()
    {
        XmlDocument doc = new XmlDocument();
        doc.LoadXml("<ns:root xmlns:ns='http://ipipp.com/schema'><ns:item>值</ns:item></ns:root>");
        XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
        mgr.AddNamespace("ns", "http://ipipp.com/schema");
        XmlNode node = doc.SelectSingleNode("//ns:item", mgr);
        Console.WriteLine(node != null ? node.InnerText : "未找到");
    }
}

忽略命名空间是XmlDocument查询失败的主因之一。另外,Save默认按声明编码写文件,若想内存中转字符串,用StringWriter并指定Encoding,可避免BOM带来的接口解析问题。

五、XmlDocument与XDocument的选择

新项目若目标框架是.NET Core或现代.NET,官方更推荐XDocument,语法更简洁且 LINQ 友好。但维护旧工控软件、Web Service早期契约,或需严格按节点顺序生成报文时,XmlDocument仍是稳妥方案。二者可共存,不必强行迁移。

总结来看,XmlDocument以树形操作平衡了灵活与可控,掌握Load、Save、XPath与命名空间四件事,就能覆盖绝大多数C# XML读写场景。写代码时优先让框架处理转义,少用字符串硬拼,可显著降低线上故障率。

XmlDocumentC#_XMLXML操作修改时间:2026-08-05 18:21:32

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。