在C#的XML处理场景中,XDocument是System.Xml.Linq命名空间下用于操作XML文档的核心类,它提供了Load方法支持从多种数据源加载XML内容,其中从流加载是非常实用的场景,能够适配文件流、网络流、内存流等多种输入形式。

XDocument Load方法的基本用法
XDocument的Load方法有多个重载版本,其中支持流参数的重载为Load(Stream)和Load(Stream, LoadOptions),前者是最基础的流加载方式,后者可以额外指定加载选项,比如是否保留空白、是否记录行号等信息。
使用流加载XML的核心逻辑是先将XML内容写入到对应的流对象中,再调用XDocument.Load方法传入流实例即可完成加载。
从内存流加载XML示例
内存流是开发中最常使用的流类型之一,以下示例演示如何从内存流中加载XML文档:
using System;
using System.IO;
using System.Text;
using System.Xml.Linq;
class Program
{
static void Main()
{
// 定义XML字符串内容
string xmlContent = "<?xml version="1.0" encoding="utf-8"?><root><user id="1">张三</user><user id="2">李四</user></root>";
// 将字符串转换为字节数组
byte[] xmlBytes = Encoding.UTF8.GetBytes(xmlContent);
// 创建内存流并写入字节数组
using (MemoryStream memoryStream = new MemoryStream(xmlBytes))
{
// 从内存流加载XML文档
XDocument xdoc = XDocument.Load(memoryStream);
// 输出根元素名称验证加载结果
Console.WriteLine("根元素名称:" + xdoc.Root.Name);
// 遍历用户节点
foreach (var user in xdoc.Root.Elements("user"))
{
Console.WriteLine($"用户ID:{user.Attribute("id").Value},用户名:{user.Value}");
}
}
}
}
从文件流加载XML示例
如果需要从本地XML文件加载内容,可以使用FileStream作为流参数传入Load方法:
using System;
using System.IO;
using System.Xml.Linq;
class Program
{
static void Main()
{
string filePath = "test.xml";
// 创建文件流,指定读取模式和文件访问权限
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
// 从文件流加载XML文档
XDocument xdoc = XDocument.Load(fileStream);
// 输出XML文档的完整字符串内容
Console.WriteLine("XML内容:");
Console.WriteLine(xdoc.ToString());
}
}
}
加载过程中的注意事项
- 流的位置:调用Load方法前,需要确保流的当前位置在XML内容的起始处,如果流已经被读取过部分内容,需要先调用
stream.Seek(0, SeekOrigin.Begin)将位置重置到开头,否则会出现加载不完整或者报错的情况。 - 编码匹配:XML文档的声明中指定的编码需要和流读取时的编码一致,比如XML声明为
<?xml version="1.0" encoding="gb2312"?>,那么将XML内容转换为字节数组时需要使用GB2312编码,否则会出现乱码或者加载失败。 - 异常处理:如果XML内容格式不正确,Load方法会抛出
XmlException,建议在加载时使用try-catch块捕获异常,避免程序崩溃。 - 流的生命周期:Load方法加载完成后不会自动关闭传入的流,因此需要使用using语句管理流的生命周期,或者手动调用Dispose方法释放资源。
带加载选项的Load方法使用
如果需要保留XML中的空白字符或者获取节点的行号信息,可以使用Load(Stream, LoadOptions)重载,LoadOptions的可选值如下:
| LoadOptions值 | 说明 |
|---|---|
| None | 默认选项,不保留无关紧要的空白,不记录行号 |
| PreserveWhitespace | 保留XML中的所有空白字符 |
| SetLineInfo | 记录XML节点的行号和位置信息,需要引用System.Xml.Schema命名空间 |
| SetLineInfo | PreserveWhitespace | 同时保留空白和记录行号信息 |
以下示例演示带加载选项的使用方式:
using System;
using System.IO;
using System.Text;
using System.Xml.Linq;
using System.Xml.Schema;
class Program
{
static void Main()
{
string xmlContent = "<?xml version="1.0" encoding="utf-8"?>n<root>n <item>内容1</item>n</root>";
byte[] xmlBytes = Encoding.UTF8.GetBytes(xmlContent);
using (MemoryStream memoryStream = new MemoryStream(xmlBytes))
{
// 指定保留空白和记录行号信息
XDocument xdoc = XDocument.Load(memoryStream, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
// 输出根元素下的第一个子元素的行号
XElement firstItem = xdoc.Root.Element("item");
if (firstItem is IXmlLineInfo lineInfo && lineInfo.HasLineInfo())
{
Console.WriteLine($"item节点的行号:{lineInfo.LineNumber}");
}
}
}
}