在 .NET9 中使用 XML

作者:微信公众号:【架构师老卢】
10-4 10:23
119

XML(可扩展标记语言)仍然是一种广泛使用的数据格式,用于在应用程序之间存储和交换结构化数据。无论您是使用遗留系统、集成不同的平台还是管理复杂的配置,XML 都是一项必不可少的技术。在 .NET 中,使用 XML 很常见,并且可以使用多个库来有效地处理 XML 文档。

在 .NET 中使用 XML 的常见挑战

尽管 XML 具有结构化性质,但使用 XML 可能会带来一些挑战,包括:

  • 处理大文件:XML 文档可能会变得很大,使其难以加载到内存中或难以有效处理。
  • 复杂性:深度嵌套或架构复杂的 XML 文件可能更难导航和操作。
  • 安全风险:XML 容易受到某些漏洞的影响,例如 XML 外部实体 (XXE) 攻击,需要缓解这些漏洞。
  • Namespace Management:许多 XML 文档依赖于命名空间,这可能会使查询和操作复杂化。

.NET 提供了各种 API 和技术来有效管理这些挑战。让我们探索不同的方法。

在 .NET 中处理 XML 的方法

1. 使用XmlDocument

XmlDocument自 .NET 的早期就已经存在。它遵循基于 DOM 的方法,其中整个 XML 文档被加载到内存中,允许您逐个节点导航和操作它。

读取 XMLXmlDocument

using System.Xml;

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("employees.xml");

XmlNodeList employeeNodes = xmlDoc.GetElementsByTagName("Employee");
foreach (XmlNode employee in employeeNodes)
{
    string id = employee.Attributes["id"].Value;
    string name = employee["Name"].InnerText;
    Console.WriteLine($"Employee ID: {id}, Name: {name}");
}

这是加载和查询 XML 文件的一种简单方法。但是,对于大型文件,将整个文档加载到内存中可能效率低下。

编写 XMLXmlDocument

XmlDocument xmlDoc = new XmlDocument();  
  
XmlElement root = xmlDoc.CreateElement("Company");  
XmlElement employee = xmlDoc.CreateElement("Employee");  
employee.SetAttribute("id", "101");  
  
XmlElement name = xmlDoc.CreateElement("Name");  
name.InnerText = "Alice";  
employee.AppendChild(name);  
  
root.AppendChild(employee);  
xmlDoc.AppendChild(root);  
xmlDoc.Save("company.xml");

虽然提供了对 XML 结构的精细控制,但它可能很冗长且效率低下,尤其是对于大型文件。XmlDocument

2. 使用 LINQ to XML (XDocument)

对于现代 .NET 应用程序,LINQ to XML () 是首选方法。它提供了一种更具声明性和直观的 XML 处理方式。使用 LINQ,您可以编写更简洁、可读性更强的代码。XDocument

使用 LINQ to XML 读取 XML

using System.Xml.Linq;  
  
XDocument xdoc = XDocument.Load("employees.xml");  
  
var employees = from e in xdoc.Descendants("Employee")  
                select new  
                {  
                    Id = e.Attribute("id").Value,  
                    Name = e.Element("Name").Value  
                };  
  
foreach (var employee in employees)  
{  
    Console.WriteLine($"Employee ID: {employee.Id}, Name: {employee.Name}");  
}

LINQ to XML 比 更简洁,并且使复杂的查询更易于表达。它允许您直接对 XML 数据使用 LINQ 强大的筛选和转换功能。XmlDocument

使用 LINQ to XML 编写 XML

XDocument xdoc = new XDocument(  
    new XElement("Company",  
        new XElement("Employee",  
            new XAttribute("id", "102"),  
            new XElement("Name", "Bob")  
        )  
    )  
);  
  
xdoc.Save("company.xml");

语法更具声明性和直观性,因此更易于使用 XML 结构。使用 LINQ to XML,您可以毫不费力地创建、修改和查询 XML 文档。

高级 XML 处理技术

在现代 .NET 开发中,还有其他功能和改进可以增强 XML 的处理能力,特别是对于大型文件和安全应用程序。

1. 处理大型 XML 文件XmlReader

对于大型 XML 文件,使用 或 将整个文档加载到内存中效率低下。相反,您可以使用 ,它以流式处理方式读取 XML 文件,一次处理一个节点。XmlDocumentXDocumentXmlReader

using System.Xml;  
  
using (XmlReader reader = XmlReader.Create("largefile.xml"))  
{  
    while (reader.Read())  
    {  
        if (reader.NodeType == XmlNodeType.Element && reader.Name == "Employee")  
        {  
            string id = reader.GetAttribute("id");  
            reader.ReadToFollowing("Name");  
            string name = reader.ReadElementContentAsString();  
            Console.WriteLine($"Employee ID: {id}, Name: {name}");  
        }  
    }  
}

XmlReader非常适合需要以增量方式处理大型文件的情况,从而避免一次加载整个文件的内存开销。

2. 异步 XML 处理

在现代 .NET 应用程序中,尤其是在 Web API 中,异步编程对于确保可扩展性和响应能力至关重要。您可以使用 或 异步读取和写入 XML。XDocumentXmlReader

异步 XML 读取示例

using System.Xml.Linq;  
  
async Task ProcessXmlAsync()  
{  
    XDocument xdoc = await XDocument.LoadAsync("employees.xml", LoadOptions.None, CancellationToken.None);  
  
    var employees = from e in xdoc.Descendants("Employee")  
                    select new  
                    {  
                        Id = e.Attribute("id").Value,  
                        Name = e.Element("Name").Value  
                    };  
  
    foreach (var employee in employees)  
    {  
        Console.WriteLine($"Employee ID: {employee.Id}, Name: {employee.Name}");  
    }  
}

这可确保您的应用程序在读取大型 XML 文件时不会阻塞,从而提高其效率和可扩展性。

3. 安全注意事项:防止 XXE 攻击

XML 文件可能容易受到 XXE (XML 外部实体) 攻击,尤其是当它们包含外部实体时。为了降低此风险,请在使用不受信任的 XML 源时始终禁用 DTD 处理。

XmlReaderSettings settings = new XmlReaderSettings  
{  
    DtdProcessing = DtdProcessing.Prohibit  
};  
  
using (XmlReader reader = XmlReader.Create("input.xml", settings))  
{  
    // Safely process the XML  
}

通过禁用 DTD 处理,可以防止攻击者利用外部实体,从而确保 XML 处理的安全性。

4. 在 XML 中使用命名空间

XML 命名空间通常用于消除元素和属性的歧义,尤其是在大型复杂文档中。LINQ to XML 使处理命名空间变得容易。

使用 LINQ to XML 处理命名空间的示例

XNamespace ns = "https://www.example.com/employees";  
XDocument xdoc = XDocument.Load("employees_with_namespace.xml");  
  
var employees = from e in xdoc.Descendants(ns + "Employee")  
                select new  
                {  
                    Id = e.Attribute("id").Value,  
                    Name = e.Element(ns + "Name").Value  
                };  
  
foreach (var employee in employees)  
{  
    Console.WriteLine($"Employee ID: {employee.Id}, Name: {employee.Name}");  
}

使用该类可确保正确定位相应命名空间中的元素和属性。XNamespace

将 .NET 对象序列化和反序列化为 XML

.NET 开发中最常见的任务之一是将对象序列化为 XML,然后将它们反序列化回对象。该类使此操作变得简单明了。XmlSerializer

将对象序列化为 XML

using System.Xml.Serialization;  
  
public class Employee  
{  
    public int Id { get; set; }  
    public string Name { get; set; }  
}  
  
Employee emp = new Employee { Id = 103, Name = "Charlie" };  
XmlSerializer serializer = new XmlSerializer(typeof(Employee));  
  
using (StreamWriter writer = new StreamWriter("employee.xml"))  
{  
    serializer.Serialize(writer, emp);  
}

这会将对象序列化为 XML。您可以轻松地将其反序列化回对象:Employee

从 XML 反序列化对象

using (StreamReader reader = new StreamReader("employee.xml"))  
{  
    Employee emp = (Employee)serializer.Deserialize(reader);  
    Console.WriteLine($"Employee ID: {emp.Id}, Name: {emp.Name}");  
}

XML 序列化通常用于存储对象状态、在本地缓存数据或跨应用程序传输数据。

  1. 选择正确的工具:在处理需要详细操作的大型复杂 XML 文件时使用,但更喜欢 LINQ to XML () 以获得更简洁、可读的代码。XmlDocumentXDocument
  2. 性能注意事项:对于大文件,应考虑异步 XML 处理,以避免高内存使用率。XmlReader
  3. 安全性:在处理不受信任的 XML 时,请始终通过禁用 DTD 处理来小心 XXE 漏洞。
  4. 现代实践:在 .NET 6/7/8 中,应优先考虑异步和流式处理技术以用于可伸缩应用程序。
  5. 命名空间:使用 LINQ to XML 中的类有效地处理 XML 命名空间,以处理更复杂的文档。XNamespace

在 .NET 中使用 XML 是任何处理数据交换、配置或存储的开发人员的基本技能。.NET 提供了强大的工具来简化这些任务。关键是根据项目的大小、复杂性和性能需求选择正确的方法。

相关留言评论
昵称:
邮箱:
阅读排行