XML XDocument与XmlDocument递归读取xml文件
在.NET开发中,处理XML文件是常见的需求。传统的XmlDocument和较新的XDocument都是操作XML的常用类,二者都支持递归方式读取XML文件的所有节点与属性。本文将分别介绍两种方式的递归实现逻辑,并附上完整代码示例。
一、XmlDocument递归读取XML
XmlDocument是.NET中较早提供的XML文档操作类,基于W3C的DOM模型,将整个XML文档加载到内存中形成节点树。递归读取时,我们可以通过遍历节点的子节点和属性,逐层处理所有内容。
首先创建测试用的XML文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<root>
<user id="1">
<name>张三</name>
<age>25</age>
<hobbies>
<hobby>篮球</hobby>
<hobby>阅读</hobby>
</hobbies>
</user>
<user id="2">
<name>李四</name>
<age>30</age>
</user>
</root>下面是基于XmlDocument的递归读取实现,方法会输出每个节点的名称、内容以及属性信息:
using System;
using System.Xml;
class XmlDocumentRecursionReader
{
static void Main(string[] args)
{
string xmlPath = "test.xml";
XmlDocument xmlDoc = new XmlDocument();
try
{
xmlDoc.Load(xmlPath);
// 从根节点开始递归
RecursionXmlNode(xmlDoc.DocumentElement, 0);
}
catch (Exception ex)
{
Console.WriteLine($"读取XML失败:{ex.Message}");
}
}
/// <summary>
/// 递归读取XmlDocument节点
/// </summary>
/// <param name="node">当前遍历的XML节点</param>
/// <param name="depth">当前节点的深度,用于缩进显示</param>
static void RecursionXmlNode(XmlNode node, int depth)
{
// 缩进字符串,根据深度控制层级显示
string indent = new string(' ', depth * 2);
// 如果节点是元素节点
if (node.NodeType == XmlNodeType.Element)
{
Console.Write($"{indent}元素节点:{node.Name}");
// 输出当前节点的所有属性
if (node.Attributes != null && node.Attributes.Count > 0)
{
Console.Write(",属性:");
foreach (XmlAttribute attr in node.Attributes)
{
Console.Write($"{attr.Name}={attr.Value} ");
}
}
Console.WriteLine();
}
// 如果是文本节点,输出内容
else if (node.NodeType == XmlNodeType.Text)
{
Console.WriteLine($"{indent}文本内容:{node.Value}");
}
// 递归遍历所有子节点
if (node.HasChildNodes)
{
foreach (XmlNode childNode in node.ChildNodes)
{
RecursionXmlNode(childNode, depth + 1);
}
}
}
}上述代码中,RecursionXmlNode方法首先判断当前节点的类型,元素节点会输出名称和属性,文本节点直接输出内容,之后通过HasChildNodes判断是否存在子节点,存在则遍历子节点并递归调用自身,深度参数depth用于控制输出时的缩进,让层级关系更清晰。
二、XDocument递归读取XML
XDocument是LINQ to XML中的核心类,相比XmlDocument,它的API更简洁,对LINQ的支持更好,操作XML更符合现代C#的开发习惯。同样的,我们可以使用递归的方式遍历所有节点。
继续使用上面的测试XML文件,以下是基于XDocument的递归读取实现:
using System;
using System.Linq;
using System.Xml.Linq;
class XDocumentRecursionReader
{
static void Main(string[] args)
{
string xmlPath = "test.xml";
try
{
XDocument xDoc = XDocument.Load(xmlPath);
// 从根元素开始递归
RecursionXElement(xDoc.Root, 0);
}
catch (Exception ex)
{
Console.WriteLine($"读取XML失败:{ex.Message}");
}
}
/// <summary>
/// 递归读取XDocument元素
/// </summary>
/// <param name="element">当前遍历的XElement元素</param>
/// <param name="depth">当前元素的深度,用于缩进显示</param>
static void RecursionXElement(XElement element, int depth)
{
string indent = new string(' ', depth * 2);
// 输出当前元素名称和属性
Console.Write($"{indent}元素:{element.Name}");
if (element.Attributes().Any())
{
Console.Write(",属性:");
foreach (var attr in element.Attributes())
{
Console.Write($"{attr.Name}={attr.Value} ");
}
}
Console.WriteLine();
// 处理元素的直接子元素
foreach (var child in element.Elements())
{
RecursionXElement(child, depth + 1);
}
// 处理元素的文本内容(排除子元素带来的文本拆分)
if (!element.Elements().Any() && !string.IsNullOrWhiteSpace(element.Value))
{
Console.WriteLine($"{indent} 文本内容:{element.Value}");
}
}
}这段代码的RecursionXElement方法首先输出当前元素的名称和属性,然后遍历所有直接子元素递归处理,最后判断如果当前元素没有子元素且存在非空文本内容,就输出文本信息。XDocument的Attributes()方法可以直接获取所有属性,Elements()方法获取所有直接子元素,相比XmlDocument的API更简洁直观。
三、两种方式对比
两种方式都可以实现XML文件的递归读取,存在以下差异:
- XmlDocument基于传统DOM模型,兼容性更好,适合需要严格遵循W3C DOM规范的场景;XDocument是LINQ to XML的核心类,API更现代,与LINQ结合更紧密,代码更简洁。
- XmlDocument的节点遍历需要手动判断节点类型,处理属性时需要访问
Attributes集合;XDocument提供了更直观的方法获取属性和子元素,不需要过多关注节点类型的判断。 - 如果是新项目且不需要兼容旧代码,更推荐使用XDocument,开发效率更高;如果是维护旧项目,可能需要在原有XmlDocument的基础上扩展递归逻辑。
实际开发中可以根据项目需求选择合适的XML操作类,递归逻辑的核心都是遍历节点树,遇到子节点就继续深入处理,直到所有节点都被访问完毕。
XmlDocumentXDocument递归读取XML文件.NET开发 本作品最后修改时间:2026-05-22 23:49:53