ZetCode

C# XmlDocument

最后修改于 2023 年 7 月 5 日

C# XmlDocument 教程展示了如何在 C# 中使用 XmlDocument 处理 XML。

可扩展标记语言 (XML) 是一种标记语言,它定义了一组规则,用于以人类可读和机器可读的格式编码文档。 XML 通常用于应用程序配置、数据存储和交换。

XML 类似于 HTML,但没有预定义的标签;我们可以设计自己的标签。

XmlDocument

XmlDocument 表示一个 XML 文档。它可用于加载、修改、验证和导航 XML 文档。

XmlDocument 类是 XML 文档的内存表示。 它实现了 W3C XML 文档对象模型 (DOM)。

文档对象模型 (DOM) 是用于 HTML 和 XML 文档的与语言无关的编程接口。 它表示一个页面。 通过 DOM 接口,程序可以更改文档结构、样式和内容。 DOM 将文档表示为节点和对象。

XmlElementXmlDocument 中的一个常见节点。

XPath (XML Path Language) 是一种查询语言,用于从 XML 文档中选择节点。 它还可以用于计算 XML 文档内容中的值。

在示例中,我们使用以下文件

words.xml
<?xml version="1.0" encoding="UTF-8"?>
<words>
    <word>falcon</word>
    <word>sky</word>
    <word>bottom</word>
    <word>cup</word>
    <word>book</word>
    <word>rock</word>
    <word>sand</word>
    <word>river</word>
</words>

这是 words.xml 文件。

users.xml
<?xml version="1.0" encoding="UTF-8"?>
<users>
  <user id="1">
    <name>John Doe</name>
    <occupation>gardener</occupation>
  </user>
  <user id="2">
    <name>Jane Doe</name>
    <occupation>teacher</occupation>
  </user>
  <user id="3">
    <name>Roger Roe</name>
    <occupation>driver</occupation>
  </user>
  <user id="4">
    <name>Lucia Smith</name>
    <occupation>shopkeeper</occupation>
  </user>
</users>

这是 users.xml 文件。

continents.xml
<?xml version="1.0" encoding="UTF-8"?>
<continents>
    <europe>
        <slovakia>
            <capital>Bratislava</capital>
            <population>421000</population>
        </slovakia>
        <hungary>
            <capital>Budapest</capital>
            <population>1759000</population>
        </hungary>
        <poland>
            <capital>Warsaw</capital>
            <population>1735000</population>
        </poland>
    </europe>
    <asia>
        <china>
            <capital>Beijing</capital>
            <population>21700000</population>
        </china>
        <vietnam>
            <capital>Hanoi</capital>
            <population>7500000</population>
        </vietnam>
    </asia>
</continents>

这是 continents.xml 文件。

C# XmlDocument DocumentElement

DocumentElement 返回文档的根 XmlElement

Program.cs
using System.Xml;

var xmlData = @"<?xml version=""1.0"" encoding=""UTF-8""?>
    <words>
    <word>falcon</word>
    <word>sky</word>
    <word>bottom</word>
    <word>cup</word>
    <word>book</word>
    <word>rock</word>
    <word>sand</word>
    <word>river</word>
    </words>
    ";

var doc = new XmlDocument();
doc.LoadXml(xmlData);

Console.WriteLine(doc.DocumentElement?.Name);
Console.WriteLine(doc.DocumentElement?.FirstChild?.InnerText);
Console.WriteLine(doc.DocumentElement?.LastChild?.InnerText);
Console.WriteLine(doc.DocumentElement?.OuterXml);
Console.WriteLine(doc.DocumentElement?.InnerXml);

我们将 XML 数据加载到 XmlDocument 中,并获取文档的根元素;我们调用根节点的属性。

var xmlData = @"<?xml version=""1.0"" encoding=""UTF-8""?>
  <words>
  <word>falcon</word>
  <word>sky</word>
  <word>bottom</word>
  <word>cup</word>
  <word>book</word>
  <word>rock</word>
  <word>sand</word>
  <word>river</word>
  </words>
  ";

我们有作为多行字符串的 XML 数据。

var doc = new XmlDocument();
doc.LoadXml(xmlData);

我们创建一个 XmlDocument 并使用 LoadXml 方法加载 XML 数据。

Console.WriteLine(doc.DocumentElement?.Name);

Name 属性返回节点的名称。

Console.WriteLine(doc.DocumentElement?.FirstChild?.InnerText);
Console.WriteLine(doc.DocumentElement?.LastChild?.InnerText);

我们使用 FirstChildLastChild 获取根节点的第一个和最后一个子节点。 InnerText 属性返回节点及其所有子节点的值。

Console.WriteLine(doc.DocumentElement?.OuterXml);

OuterXml 属性获取包含此节点及其所有子节点的标记。

Console.WriteLine(doc.DocumentElement?.InnerXml);

InnerXml 属性获取或设置仅表示此节点的子节点的标记。

$ dotnet run 
words
falcon
river
<words><word>falcon</word><word>sky</word><word>bottom</word><word>cup</word>...
<word>falcon</word><word>sky</word><word>bottom</word><word>cup</word>...

C# XmlNode.RemoveChild

XmlNode.RemoveChild 方法删除指定的子节点。

Program.cs
using System.Xml;

var xmlFile = "/home/janbodnar/Documents/users.xml";

var doc = new XmlDocument();
doc.Load(xmlFile);

XmlElement root = doc.DocumentElement;
XmlNode userNode = root?.LastChild;

if (userNode != null)
{
    root.RemoveChild(userNode);
}

var xmlFile2 = "/home/janbodnar/Documents/users2.xml";

doc.Save(xmlFile2);

在该示例中,我们删除文档中的最后一个子节点。 请注意,该方法不修改原始文件; 它修改文档的内存表示,并将修改后的文档保存到新文件中。

C# XmlDocument.CreateElement

XmlDocument.CreateElement 方法创建具有指定名称的元素。

Program.cs
using System.Xml;

var xmlFile = "/home/janbodnar/Documents/words.xml";

var doc = new XmlDocument();
doc.Load(xmlFile);

XmlElement root = doc.DocumentElement;

XmlElement e1 = doc.CreateElement("word");
e1.InnerText = "eagle";
root?.InsertAfter(e1, root.LastChild);

XmlElement e2 = doc.CreateElement("word");
e2.InnerText = "cheetah";
root?.InsertBefore(e2, root.FirstChild);

var xmlFile2 = "/home/janbodnar/Documents/words2.xml";
doc.Save(xmlFile2);

在示例中,我们创建两个新元素。

XmlElement e1 = doc.CreateElement("word");
e1.InnerText = "eagle";

使用 CreateElement 创建一个名为 word 的新元素。 它的文本使用 InnerText 属性设置。

root?.InsertAfter(e1, root.LastChild);

使用 InsertAfter 将新创建的元素插入到最后一个子节点之后。

XmlElement e2 = doc.CreateElement("word");
e2.InnerText = "cheetah";
root?.InsertBefore(e2, root.FirstChild);

使用 InsertBefore 将第二个元素插入到第一个元素之前。

C# XmlDocument 创建新文档

在以下示例中,我们创建一个新的 XML 文档。

Program.cs
using System.Xml;

var users = new Dictionary<long, User>();
users.Add(1, new User(1L, "John Doe", "gardener"));
users.Add(2, new User(2L, "Jane Doe", "teacher"));
users.Add(3, new User(3L, "Roger Roe", "driver"));
users.Add(4, new User(4L, "Lucia Smith", "shopkeeper"));

var doc = new XmlDocument();
XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0",
    "UTF-8", string.Empty);

doc.AppendChild(xmlDeclaration);

XmlElement usersNode = doc.CreateElement("users");
doc.AppendChild(usersNode);

foreach (var (_, value) in users)
{
    XmlElement userEl = doc.CreateElement("user");
    usersNode.AppendChild(userEl);

    XmlAttribute e = doc.CreateAttribute("id");
    e.Value = value.Id.ToString();
    userEl.Attributes.Append(e);

    XmlElement e2 = doc.CreateElement("name");
    e2.InnerText = value.Name;
    userEl.AppendChild(e2);
    
    XmlElement e3 = doc.CreateElement("occupation");
    e3.InnerText = value.Occupation;
    userEl.AppendChild(e3);
}

doc.Save(Console.Out);

internal record User(long Id, string Name, string Occupation);

从用户对象的字典创建一个新的 XML 文档。

var users = new Dictionary<long, User>();
users.Add(1, new User(1L, "John Doe", "gardener"));
users.Add(2, new User(2L, "Jane Doe", "teacher"));
users.Add(3, new User(3L, "Roger Roe", "driver"));
users.Add(4, new User(4L, "Lucia Smith", "shopkeeper"));

我们有一个用户字典。

var doc = new XmlDocument();
XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0",
    "UTF-8", string.Empty);

创建一个 XmlDocument 和一个 XmlDeclaration

doc.AppendChild(xmlDeclaration);

使用 AppendChildXmlDeclaration 附加到文档。 声明标签是文档中的第一个标签。

XmlElement usersNode = doc.CreateElement("users");
doc.AppendChild(usersNode);

我们创建文档的根节点。

foreach (var (_, value) in users)
{
    XmlElement userEl = doc.CreateElement("user");
    usersNode.AppendChild(userEl);

    XmlAttribute e = doc.CreateAttribute("id");
    e.Value = value.Id.ToString();
    userEl.Attributes.Append(e);

    XmlElement e2 = doc.CreateElement("name");
    e2.InnerText = value.Name;
    userEl.AppendChild(e2);
    
    XmlElement e3 = doc.CreateElement("occupation");
    e3.InnerText = value.Occupation;
    userEl.AppendChild(e3);
}

我们遍历字典,并为每个用户对象创建必要的元素和一个属性。

doc.Save(Console.Out);

这次我们将 XML 数据输出到控制台。

$ dotnet run
<?xml version="1.0" encoding="utf-8"?>
<users>
  <user id="1">
    <name>John Doe</name>
    <occupation>gardener</occupation>
  </user>
  <user id="2">
    <name>Jane Doe</name>
    <occupation>teacher</occupation>
  </user>
  <user id="3">
    <name>Roger Roe</name>
    <occupation>driver</occupation>
  </user>
  <user id="4">
    <name>Lucia Smith</name>
    <occupation>shopkeeper</occupation>
  </user>
</users>

C# XmlNode.ChildNodes

XmlNode.ChildNodes 返回给定节点的所有子节点。 该属性返回 XmlNodeList,它表示节点的有序集合。

Program.cs
using System.Xml;

var xmlFile = "/home/janbodnar/Documents/words.xml";

var doc = new XmlDocument();
doc.Load(xmlFile);
XmlElement root = doc.DocumentElement;
XmlNodeList childNodes = root?.ChildNodes;

if (childNodes == null)
{
    Console.WriteLine("no nodes found");
    Environment.Exit(1);
}

foreach (XmlNode node in childNodes)
{
    Console.WriteLine(node.InnerText);
}

在示例中,我们获取根节点的所有子节点并打印它们的内部文本内容。

$ dotnet run
falcon
sky
bottom
cup
book
rock
sand
river

C# XmlNodeList.Count

XmlNodeList.Count 属性获取 XmlNodeList 中的节点数。

Program.cs
using System.Xml;

var xmlFile = "/home/janbodnar/Documents/words.xml";
    
var doc = new XmlDocument();
doc.Load(xmlFile);

XmlElement root = doc.DocumentElement;
int? n = root?.ChildNodes.Count;

Console.WriteLine($"There are {n} elements");

我们获取根节点内部的元素数量。

$ dotnet run 
There are 8 elements

C# XmlNode.SelectSingleNode

XmlNode.SelectSingleNode 选择与 XPath 表达式匹配的第一个 XmlNode。

Program.cs
using System.Xml;

var xmlFile = "/home/janbodnar/Documents/users.xml";

var doc = new XmlDocument();
doc.Load(xmlFile);

int id = 2;

XmlNode node = doc.SelectSingleNode($"/users/user[@id='{id}']");

if (node == null)
{
    Console.WriteLine("node not found");
    Environment.Exit(1);
}

var name = node.ChildNodes[0]?.InnerText;
var occupation = node.ChildNodes[1]?.InnerText;
var uid = node.Attributes?["id"]?.Value;

Console.WriteLine($"Id: {uid}");
Console.WriteLine($"Name: {name}");
Console.WriteLine($"Occupation: {occupation}");

words.xml 文件中,我们选择 Id 属性为 6 的 word 节点。

XmlNode node = doc.SelectSingleNode($"/users/user[@id='{id}']");

使用 SelectSingleNode 选择单个节点; /users/user[@id='{id}'] 是获取所需节点的查询表达式。

var name = node.ChildNodes[0]?.InnerText;
var occupation = node.ChildNodes[1]?.InnerText;
var uid = node.Attributes?["id"]?.Value;

我们获取节点的文本和属性。

$ dotnet run
Id: 2
Name: Jane Doe
Occupation: teacher

C# XmlNode.SelectNodes

XmlNode.SelectNodes 选择与 XPath 表达式匹配的节点列表。

Program.cs
using System.Xml;

var xmlFile = "/home/janbodnar/Documents/users.xml";

var doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList nodes = doc.SelectNodes("/users/user");

var users = new List<User>();

if (nodes == null)
{
    Console.WriteLine("No users found");
    Environment.Exit(1);
}

foreach (XmlNode node in nodes)
{
    long id = long.Parse(node.Attributes?.GetNamedItem("id")?.Value!);
    string name = node.ChildNodes[0]?.InnerText;
    string occupation = node.ChildNodes[1]?.InnerText;

    var user = new User(id, name, occupation);
    users.Add(user);
}

users.ForEach(Console.WriteLine);

record User(long Id, string Name, string Occupation);

在示例中,我们从 users.xml 文件中选择所有用户。

XmlNodeList nodes = doc.SelectNodes("/users/user");

/users/user 是获取所有用户的路径。 SelectNodes 方法返回一个 XmlNodeList

foreach (XmlNode node in nodes)
{
    long id = long.Parse(node.Attributes?.GetNamedItem("id")?.Value!);
    string name = node.ChildNodes[0]?.InnerText;
    string occupation = node.ChildNodes[1]?.InnerText;

    var user = new User(id, name, occupation);
    users.Add(user);
}

我们遍历 XmlNodeList 并从检索到的数据创建一个 User 对象。

$ dotnet run
User { Id = 1, Name = John Doe, Occupation = gardener }
User { Id = 2, Name = Jane Doe, Occupation = teacher }
User { Id = 3, Name = Roger Roe, Occupation = driver }
User { Id = 4, Name = Lucia Smith, Occupation = shopkeeper }

C# XmlElement.GetElementsByTagName

XmlElement.GetElementsByTagName 返回一个 XmlNodeList,其中包含与指定标签名称匹配的所有后代元素的列表。

Program.cs
using System.Xml;

var xmlFile = "/home/janbodnar/Documents/continents.xml";

XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);

XmlNodeList nodes = doc.GetElementsByTagName("capital");
Console.WriteLine("All capitals:");

foreach (XmlNode node in nodes)
{
    var text = node.InnerText;
    Console.WriteLine(text);
}

我们遍历 continents.xml 文件中的 capital 标签。

$ dotnet run
All capitals:
Bratislava
Budapest
Warsaw
Beijing
Hanoi

C# XmlDocument.CreateNavigator

XmlDocument.CreateNavigator 创建一个 XPathNavigator 对象,用于导航文档。 XPathNodeIterator 提供了对选定节点集的迭代器。

Program.cs
using System.Xml;
using System.Xml.XPath;

var xmlFile = "/home/janbodnar/Documents/users.xml";

var doc = new XmlDocument();
doc.Load(xmlFile);

XPathNavigator rootNav = doc.CreateNavigator();
XPathNodeIterator it = rootNav?.Select("descendant::users/user");

if (it == null)
{
    Console.WriteLine("no users found");
    Environment.Exit(1);
}

while (it.MoveNext())
{
    
    XPathNavigator nav = it.Current;

    var uId = nav?.GetAttribute("id", string.Empty);
    Console.WriteLine(uId);
    
    XPathNodeIterator nodeIt = nav?.SelectChildren(XPathNodeType.Element);

    if (nodeIt != null)
    {
        foreach (var e in nodeIt)
        {
            Console.WriteLine(e);
        }
    }

    Console.WriteLine("--------------------");
}

我们使用 XPathNavigatorXPathNodeIterator 来遍历 users.xml 文件中的用户。

XPathNavigator rootNav = doc.CreateNavigator();
XPathNodeIterator it = rootNav?.Select("descendant::users/user");
...
while (it.MoveNext())

首先,我们遍历 user 标签。

XPathNavigator nav = it.Current;

var uId = nav?.GetAttribute("id", string.Empty);
Console.WriteLine(uId);

XPathNodeIterator nodeIt = nav?.SelectChildren(XPathNodeType.Element);

if (nodeIt != null)
{
    foreach (var e in nodeIt)
    {
        Console.WriteLine(e);
    }
}

然后我们遍历每个 user 标签的元素。

$ dotnet run
1
John Doe
gardener
--------------------
2
Jane Doe
teacher
--------------------
3
Roger Roe
driver
--------------------
4
Lucia Smith
shopkeeper
--------------------

C# XmlDocument 递归循环

在以下示例中,我们递归循环 users.xml 文件的标签。

Program.cs
using System.Xml;

var xmlFile = "/home/janbodnar/Documents/users.xml";

var doc = new XmlDocument();
doc.Load(xmlFile);

traverse(doc.DocumentElement);

void traverse(XmlNode node)
{
    if (node is XmlElement)
    {
        if (node.Name == "users")
        {
            Console.WriteLine(node.Name);
        }
        else if (node.Name == "user")
        {
            Console.WriteLine("--------------------");
            Console.WriteLine(node.Name);
        }
        else
        {
            Console.WriteLine($"  {node.Name}");
        }

        if (node.HasChildNodes)
        {
            traverse(node.FirstChild);
        }

        if (node.NextSibling != null)
        {
            traverse(node.NextSibling);
        }
    }
    else if (node is XmlText)
    {
        var text = ((XmlText) node).Value;
        Console.WriteLine($"    {text}");
    }
}

我们使用递归算法解析 users.xml

traverse(doc.DocumentElement);

我们首先将根元素传递给 traverse 方法。

if (node is XmlElement)
{
  ...
}
else if (node is XmlText)
{
    var text = ((XmlText) node).Value;
    Console.WriteLine($"    {text}");
}

我们检查节点是否为 XmlElementXmlText。 在后一种情况下,我们输出节点的文本内容。

if (node.HasChildNodes)
{
    traverse(node.FirstChild);
}

如果节点有子节点,我们递归调用 traverse 方法,并将其第一个子节点传递给它。

if (node.NextSibling != null)
{
    traverse(node.NextSibling);
}

如果存在,我们递归地转到下一个同级节点。

$ dotnet run
users
--------------------
user
  name
    John Doe
  occupation
    gardener
--------------------
user
  name
    Jane Doe
  occupation
    teacher
--------------------
user
  name
    Roger Roe
  occupation
    driver
--------------------
user
  name
    Lucia Smith
  occupation
    shopkeeper

在本文中,我们使用 XmlDocument 处理了 C# 中的 XML 数据。

C# XmlDocument 读取货币汇率

在以下示例中,我们从欧洲中央银行读取数据。

Program.cs
using System.Xml;

var xmlRes = "http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml";

var doc = new XmlDocument();
doc.Load(xmlRes);

XmlNodeList nodes = doc.DocumentElement?.ChildNodes[2]?.ChildNodes[0]?.ChildNodes;

foreach (XmlNode xmlNode in nodes!)
{
    if (xmlNode.Attributes == null) continue;

    var cur = xmlNode.Attributes["currency"]?.Value;
    var rate = xmlNode.Attributes["rate"]?.Value;

    Console.WriteLine($"{cur}: {rate}");
}

我们获取欧元的货币汇率。

$ dotnet run
USD: 1.1904
JPY: 130.20
BGN: 1.9558
CZK: 26.031
DKK: 7.4369
GBP: 0.86518
HUF: 356.43
PLN: 4.5246
RON: 4.9203
SEK: 10.1975
CHF: 1.0998
ISK: 151.90
NOK: 10.0940
HRK: 7.5673
RUB: 91.9588
...

C# XmlDocument 验证

具有正确语法的 XML 文档被称为格式良好。 验证是检查 XML 文档以确认其既格式良好又有效的过程。 有效文档遵守特定 DTD 或 XML 架构规定的规则。

XML 架构或 XML 架构定义 (XSD) 是对 XML 文档的结构和内容的正式描述。 它用于验证 XML 文档。

users.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="users" type="usersType"/>

    <xs:complexType name="userType">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="occupation" type="xs:string"/>
        </xs:sequence>
        <xs:attribute type="xs:string" name="id"/>
    </xs:complexType>

    <xs:complexType name="usersType">
        <xs:sequence>
            <xs:element name="user" type="userType" maxOccurs="unbounded" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
  
</xs:schema>

我们有 users.xml 文件的架构定义。

Program.cs
using System.Xml;
using System.Xml.Schema;

var xmlFile = "/home/janbodnar/Documents/users.xml";
var xmlSchema = "/home/janbodnar/Documents/users.xsd";

try
{
    var settings = new XmlReaderSettings();
    settings.Schemas.Add(null, xmlSchema);
    settings.ValidationType = ValidationType.Schema;
    settings.ValidationEventHandler += ValidationEventHandler;
    
    XmlReader reader = XmlReader.Create(xmlFile, settings);
    var doc = new XmlDocument();
    doc.Load(reader);

    Console.WriteLine("validation passed");
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

void ValidationEventHandler(object sender, ValidationEventArgs e)
{
    Console.WriteLine($"Document validation error: {e.Message}");
    Environment.Exit(1);
}

我们根据 users.xsd 架构验证 users.xml 文档。

C# XmlDocument 事件

有一些事件处理程序可以对节点被更改、插入或删除做出反应。

Program.cs
using System.Xml;

var xmlFile = "/home/janbodnar/Documents/words.xml";

var doc = new XmlDocument();
doc.Load(xmlFile);

XmlElement root = doc.DocumentElement;

doc.NodeChanged += MyNodeChangedEvent;
doc.NodeInserted += MyNodeInsertedEvent;
doc.NodeRemoved += MyNodeRemovedEvent;

XmlNode node = root?.LastChild;
root?.RemoveChild(node!);

XmlElement e1 = doc.CreateElement("word");
e1.InnerText = "eagle";
root?.AppendChild(e1);

XmlNode n1 = doc.SelectSingleNode("//words/word[text()='bottom']");
Console.WriteLine(n1?.InnerText);
if (n1 != null) n1.InnerText = "star";
doc.Save("/home/janbodnar/Documents/words3.xml");

void MyNodeChangedEvent(Object src, XmlNodeChangedEventArgs args)
{
    Console.WriteLine($"Node Changed Event Fired for node {args.Node?.Name}");
    Console.WriteLine(args.Node?.Value);
}

void MyNodeInsertedEvent(Object src, XmlNodeChangedEventArgs args)
{
    Console.WriteLine($"Node Inserted Event Fired for node {args.Node?.Name}");
    Console.WriteLine(args.Node?.Value);
}

void MyNodeRemovedEvent(Object src, XmlNodeChangedEventArgs args)
{
    Console.WriteLine($"Node Removed Event Fired for node {args.Node?.Name}");
    Console.WriteLine(args.Node?.Value);
}

在示例中,我们创建了三个事件处理程序。

doc.NodeChanged += MyNodeChangedEvent;
doc.NodeInserted += MyNodeInsertedEvent;
doc.NodeRemoved += MyNodeRemovedEvent;

我们为节点被更改、插入和删除插入事件处理程序。

XmlNode node = root?.LastChild;
root?.RemoveChild(node!);

我们删除最后一个子节点。 这会触发 MyNodeRemovedEvent

XmlElement e1 = doc.CreateElement("word");
e1.InnerText = "eagle";
root?.AppendChild(e1);

我们创建一个新节点。 这会触发两段 MyNodeInsertedEvent:一段用于插入文本,一段用于插入节点。

XmlNode n1 = doc.SelectSingleNode("//words/word[text()='bottom']");
Console.WriteLine(n1?.InnerText);
if (n1 != null) n1.InnerText = "star";

我们修改节点的内容。 这会触发 MyNodeChangedEvent

$ dotnet run 
Node Removed Event Fired for node word
Node Inserted Event Fired for node #text
eagle
Node Inserted Event Fired for node word
bottom
Node Changed Event Fired for node #text
star

来源

XmlDocument 类 - 语言参考

在本文中,我们使用 XmlDocument 处理了 C# 中的 XML 数据。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直在撰写编程文章。 迄今为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程