当前位置: 首页 > article >正文

Unity/C# 常用XML读写方式详解(LINQ to XML、XmlReader/Writer)

此文章将会介绍C#中进行XML读写的方式:LINQ to XML随机读写、XmlReader/Writer流式读写
用于初学者参考或作为工具书查阅。


  • LINQ to XML
    • 基本概念和类
      • XElement常用方法
    • 创建XML
    • 查询:LINQ 查询语法(Query Syntax)
      • 排序、中间值
    • 编辑XML
  • XMLReader/XMLWriter
    • XML结构
      • 常见的节点类型与示例:
      • 使用场景和注意事项:
    • MoveTo...()方法
      • 详细说明:
    • ReadTo...()方法
      • 详细说明:
      • 总结对比:
  • 结束


LINQ to XML

首先介绍LINQ to XML,这是更现代、更直观的XML操作方式。它使得你可以使用 LINQ 查询语法对 XML 文档进行操作,同时也能执行插入、删除、修改等操作。

XMLDocument相比,LINQ to XML效率更高、内存占用更低。

基本概念和类

如果你对XML结构略有疑问,在流式处理XML章节有详细的XML结构介绍以及解析。

XDocument、XElement、XAttribute是最常用的元素,我使用🌟标记。

描述
XDocument 🌟表示整个 XML 文档的类。它可以存储根元素及其所有子元素
XElement 🌟表示 XML 中的一个元素节点。它代表了 XML 元素,包括名称属性子元素
XAttribute 🌟代表 XML 中的一个属性。每个 XElement 对象可以包含多个 XAttribute 对象
XNamespace表示 XML 中的命名空间。用于在查询和操作带有命名空间的 XML 文档时,指定正确的命名空间
XText表示 XML 中的文本节点。每个 XElement 可以有一个文本节点,包含该元素的文本值
XComment代表 XML 中的注释节点
XProcessingInstruction代表 XML 中的处理指令节点(例如 <?xml version="1.0"?>
XDocumentType表示 XML 文档类型声明节点(<!DOCTYPE>)。通常用于定义文档的类型、结构和规则

获取某个元素节点的内容,可读取其Value属性,或者将其本身强制转换为预期的基础类型。
设置某个元素节点的内容,可设置其Value属性,或者使用SetValue(Object o)方法

ℹ️注意
这些元素都实现了向基础类型强制转换运算符,即转换是安全且有意义的,例如:

XElement root = XElement.Parse("<Root>abc <b>def </b>ghi</Root>");
//将 XElement 强制转换为 string,其值将自动为:root.value
Console.WriteLine("root={0}", (string)root);

这将输出root的内容:

abc def ghi

XElement常用方法

XElementXDocument 的基础构建块,是整个 XML 操作体系的核心,它包含常用的方法:

XElement方法描述
Add向元素添加子元素、文本、注释等。
重载:可以添加多个元素、文本、注释或其他节点。常用的重载包括:
1. Add(params object[] content):接受多个对象,支持添加 XElementXTextXComment 等。
2. Add(XElement element):添加单个元素。
Remove移除当前元素的子元素、属性或其他节点。
重载:可以移除单个节点或一组节点。
Descendants返回当前元素及其所有后代元素的集合。
重载:可以指定过滤条件来获取符合条件的后代元素。例如:
1. Descendants(XName name):返回符合特定名称的后代元素。
2. Descendants(XName name, XNamespace ns):返回符合特定名称和命名空间的后代元素。
Elements返回当前元素的所有直接子元素。
重载:可以指定过滤条件来获取符合条件的子元素。例如:
1. Elements(XName name):返回符合特定名称的子元素。
2. Elements(XName name, XNamespace ns):返回符合特定名称和命名空间的子元素。
Attribute获取或设置与当前元素关联的特定属性。
重载:可以通过属性的名称来访问或设置属性值。
1. Attribute(XName name):获取特定名称的属性。
2. Attribute(XName name, XNamespace ns):获取带命名空间的特定名称的属性。
HasElements判断当前元素是否包含子元素。返回 true 如果元素包含子元素,否则返回 false
Value获取或设置元素的文本值。如果元素有子元素,返回其所有子元素的文本拼接;否则返回元素的文本内容。
重载:可以设置元素的文本内容或从子元素中获取文本。
Name获取或设置元素的名称。包括元素的本地名称和命名空间。
FirstNode返回当前元素的第一个子节点。
LastNode返回当前元素的最后一个子节点。
Ancestors返回当前元素及其所有祖先元素的集合。
重载:可以指定过滤条件来获取符合条件的祖先元素。例如:
1. Ancestors(XName name):返回符合特定名称的祖先元素。
2. Ancestors(XName name, XNamespace ns):返回符合特定名称和命名空间的祖先元素。
Parent获取当前元素的父元素。如果当前元素没有父元素,则返回 null
DescendantsAndSelf返回当前元素及其所有后代元素(包括当前元素)。
NodeType获取当前节点的类型(例如元素、文本、属性等)。
GetPrefixOfNamespace获取与当前元素关联的命名空间的前缀。
RemoveAttributes移除当前元素的所有属性。
SetAttributeValue设置或修改与当前元素关联的属性的值。如果属性不存在,则会创建新属性。
重载:可以为不同类型的属性赋值。例如:
1. SetAttributeValue(XName name, object value):设置属性的值。
SetElementValue设置或修改指定子元素的值。如果子元素不存在,则会创建新子元素并设置其值。
重载:可以设置不同类型的值。例如:
1. SetElementValue(XName name, object value):为指定名称的子元素设置值。

这些方法是后续进行增删改查的基础,需对其有清楚的理解。


创建XML

通过链式调用,能够让代码更加紧凑和易读,例如:

var contact =
	new XElement("Contact",
	    new XElement("Name", "Patrick Hines"),
	    new XElement("Age","22")
	    new XElement("Phone", "206-555-0144",
	        new XAttribute("Type", "Home")),
	    new XElement("Phone", "425-555-0145",
	        new XAttribute("Type", "Work")),
	    new XElement("Address",
	        new XElement("City", "Mercer Island"),
	        new XElement("State", "WA"),
	    )
	);

生成的XML:

<Contact>
  <Name>Patrick Hines</Name>
  <Age>22</Age>
  <Phone Type="Home">206-555-0144</Phone>
  <Phone Type="Work">425-555-0145</phone>
  <Address>
    <City>Mercer Island</City>
    <State>WA</State>
  </Address>
</Contact>

查询:LINQ 查询语法(Query Syntax)

官方查询用例文档

LINQ 查询语法类似于 SQL 查询,它是更加直观、声明性的查询方式。如果你有SQL语句基础,那么应该很容易掌握复杂查询的方法。

以上文的XML为例,要查询TypeHome<Phone>

XElement root = XElement.Load("Contact.xml");
IEnumerable<XElement> phone =
    from el in root.Elements("Phone")
    where (string)el.Attribute("Type") == "Home"
    select el;
foreach (XElement el in address)
    Console.WriteLine(el);

其中用到了Elements(string n)方法来获取所有n标签。

⚠️再次强调:
el.Attribute("Type")返回值是XAttribute,将其强制转换为string是安全的,因为其实现了向基础类型的类型转换操作符。

排序、中间值

假设XML有多个<Contact>元素节点,内容均为随机值。

借助于LINQ 查询语法,很容易对其结果根据年龄进行排序

IEnumerable<XElement> sortedContacts = 
	from contact in root.Elements("Contact")
	orderby (int)contact.Element("Age")
	select contact;

计算中间值的例子,实现根据年龄的奇偶性进行排序:

IEnumerable<XElement> sortedContacts = 
	from contact in root.Elements("Contact")
	let isOdd = (int)contact.Element("Age") % 2
	orderby isOdd
	select contact;

let用于在查询中创建一个新的临时变量,保存计算结果以便后续使用。

可以在let中进行更复杂的运算,例如实现选择后面紧接 ul 元素的 p 元素

IEnumerable<XElement> items =
   from e in doc.Descendants("p")
   let z = e.ElementsAfterSelf().FirstOrDefault()
   where z != null && z.Name.LocalName == "ul"
   select e;

用到了更多的新方法,DescendantsElementsAfterSelfFirstOrDefault,但核心原理依旧是在where中进行数值判断。
其中LocalNameXName的一个属性,其获取的是没有命名空间限定符的元素节点的名称。例如: 对于下面的XML文件:

<Root xmlns="http://www.4399.com">  
    <Child>content</Child>
</Root> 

其Root的Name为:{http://www.4399.com}Root
其Root的Name.LocalName为:Root
其Root的Name.NameSpace为:http://www.4399.com

编辑XML

使用LINQ to XML编辑XML非常容易,只需要调用XElement的方法:

添加方法说明
Add在子内容的末尾添加内容。
AddFirst在子内容的开头添加内容。
AddAfterSelf同级后面添加内容。
AddBeforeSelf同级前面添加内容。

这些方法都支持多个重载,以调用XElement.Add(…)为例:

var srcTree = new XElement("Root",
    new XElement("Element1", 1),
    new XElement("Element2", 2),
);
var xmlTree = new XElement("Root",
    new XElement("Child1", 1),
    new XElement("Child2", 2),
);
//添加单个元素
xmlTree.Add(new XElement("NewChild", "new content"));
//添加集合
xmlTree.Add(
    from el in srcTree.Elements()
    where (int)el > 3
    select el
);
//什么也不会做
xmlTree.Add(srcTree.Element("这是一个不可能找到的元素"));


有些元素有特殊的删除方法:

方法说明
XAttribute.Remove从父节点中移除 XAttribute。
XContainer.RemoveNodes从 XContainer 中移除子节点。
XElement.RemoveAll从 XElement 中移除内容和属性。
XElement.RemoveAttributes移除 XElement 的属性。
XElement.SetAttributeValue如果传递值 null,则删除该属性。
XElement.SetElementValue如果传递值 null,则删除子元素。
XNode.Remove从父节点中移除 XNode。
Extensions.Remove从父元素中移除源集合中的每个属性或元素。

其中SetAttributeValueSetElementValue是其函数的特殊用法。

XNodeXContainer 均包括 XElementXDocument

下面是一个官方的案例:

XElement root = XElement.Parse(
@"<Root>
    <Child1>
        <GrandChild1/>
        <GrandChild2/>
        <GrandChild3/>
    </Child1>
    <Child2>
        <GrandChild4/>
        <GrandChild5/>
        <GrandChild6/>
    </Child2>
    <Child3>
        <GrandChild7/>
        <GrandChild8/>
        <GrandChild9/>
    </Child3>
</Root>");
root.Element("Child1").Element("GrandChild1").Remove();
root.Element("Child2").Elements().ToList().Remove();
root.Element("Child3").Elements().Remove();

它将从 Child1 中删除第一个子元素,从 Child2 和 Child3 中删除所有子元素。
注意其中使用了ToList(),依然能够删除root元素中的数据。



下面的方法修改 XElement

方法说明
XElement.Parse用已分析的 XML 替换元素。
XElement.RemoveAll移除元素的所有内容(子节点和属性)。
XElement.RemoveAttributes移除元素的属性。
XElement.ReplaceAll替换元素的所有内容(子节点和属性)。
XElement.ReplaceAttributes替换元素的属性。
XElement.SetAttributeValue设置属性的值。 如果该属性不存在,则创建该属性。 如果值设置为 null,则移除该属性。
XElement.SetElementValue设置子元素的值。 如果该元素不存在,则创建该元素。 如果值设置为 null,则移除该元素。
XElement.Value用指定的文本替换元素的内容(子节点)。
XElement.SetValue设置元素的值。

下面的方法修改 XAttribute

方法说明
XAttribute.Value设置属性的值。
XAttribute.SetValue设置属性的值。

下面的方法修改 XNodeXContainer(包括 XElementXDocument):

方法说明
XNode.ReplaceWith用新内容替换节点。
XContainer.ReplaceNodes用新内容替换子节点:

XMLReader/XMLWriter

特性XmlReader / XmlWriterLINQ to XML
操作方式基于流,逐行读取或写入基于内存的对象模型(DOM),加载整个文档
性能高效,适用于大文件,内存占用低性能较低,内存占用较高,适用于中小文件
适用场景读取大文件、按需处理、低内存占用简单查询、修改、创建和操作 XML 数据
查询能力不支持直接查询,需要手动处理节点支持 LINQ 查询,支持复杂查询、筛选、排序
易用性较复杂,手动处理 XML 解析和生成简单易用,支持 LINQ 查询语法
修改能力支持写入但不支持修改已读取的节点支持修改 XML 数据,添加、删除、更新节点
内存占用低,占用内存少高,需要将整个 XML 文档加载到内存中
性能优化适合大规模数据的流式处理,逐步操作适合小规模文档操作,适合内存中的数据

在理解XML流式序列化的逻辑之前你需要理解XML结构

XML结构

XmlNodeType 微软官方文档
XmlNodeType 是一个枚举类型,定义了 XmlReader 处理的 XML 文档中可能出现的节点类型。每个节点类型代表 XML 文档结构的一部分,例如元素、属性、文本等。以下是 XmlNodeType 的详细说明:

类型枚举值描述可作为其子节点的元素可作为其父节点的元素
None0当XmlReader的读取方法未被调用时返回此值EntityReference, Text
Element1元素(例如,<item>Element、Text、Comment、ProcessingInstruction、CDATA、EntityReferenceDocument、DocumentFragment、EntityReference、Element
Attribute2属性(例如,id='123'EntityReference, TextAttribute不被视为子节点)
Text3节点的文本内容Attribute、DocumentFragment、Element、EntityReference
CDATA4CDATA部分(例如,<![CDATA[我的转义文本]]>DocumentFragment、EntityReference 和 Element
EntityReference5对实体的引用(例如,&num;Element、ProcessingInstruction、Comment、Text、CDATA、EntityReferenceAttribute、DocumentFragment、Element、EntityReference
Entity6实体声明(例如,<!ENTITY...>例如 Text ,表示扩展实体的子节点 (EntityReference)DocumentType
ProcessingInstruction7处理指令(例如,<?pi test?>Document、DocumentFragment、Element、EntityReference
Comment8注释(例如,<!-- 我的注释 -->Document、DocumentFragment、EntityReference
Document9作为文档树的根,提供访问整个XML文档的文档对象XmlDeclaration、 Element (最多一个) 、ProcessingInstruction、、 Comment``DocumentType
DocumentType10文档类型声明由以下标签指示(例如,<!DOCTYPE...>Notation, Entity
DocumentFragment11文档片段Element、ProcessingInstruction、Comment、Text、CDATA、EntityReference
Notation12文档类型声明中的符号(例如,<!NOTATION...>DocumentType
Whitespace13标记之间的空白
SignificantWhitespace14混合内容模型中或xml:space="preserve"范围内标记之间的空白
EndElement15结束元素标签(例如,</item>
EndEntity16当XmlReader到达实体替换的结尾时返回,这是由于调用了ResolveEntity()
XmlDeclaration17XML声明(例如,<?xml version='1.0'?>)。
XmlDeclaration节点必须是文档中的第一个节点。它不能有子节点。它是文档节点的子节点。它可以有提供版本和编码信息的属性
Document

其中最常用的节点我使用✨将其标识。

常见的节点类型与示例:

假设我们有如下的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<!-- A comment -->
<book title="XML Guide">
    <author>John Doe</author>
    <![CDATA[This is CDATA content]]>
</book>

解析此 XML 时,XmlReader 会处理以下节点类型:

节点节点类型 (XmlNodeType)描述
<?xml version="1.0" encoding="UTF-8"?>XmlDeclarationXML 声明节点。
<!-- A comment -->Comment注释节点。
<book>Element起始元素节点。
title="XML Guide"Attribute属性节点。
John DoeText元素中的文本节点(<author> 的内容)。
<![CDATA[This is CDATA content]]>CDATACDATA 节点,表示未解析的字符数据。
</book>EndElement结束元素节点。

使用场景和注意事项:

  • 动态检查节点类型
    你可以通过 XmlReader.NodeType 属性动态检查当前节点的类型。例如:

    if (reader.NodeType == XmlNodeType.Element) {
        Console.WriteLine($"Start element: {reader.Name}");
    } else if (reader.NodeType == XmlNodeType.Text) {
        Console.WriteLine($"Text content: {reader.Value}");
    }
    
  • 跳过非内容节点
    你可以使用 MoveToContent() 跳过注释、空白等非内容节点,直接移动到元素或文本节点。

  • 特殊节点处理
    某些类型的节点(如 EntityDocumentFragment 等)通常不会直接被 XmlReader 返回。这些节点更多地用于 DOM 模型,而非流式读取。

MoveTo…()方法

XmlReader 中与节点移动相关的成员函数:

函数名介绍
MoveToAttribute()移动到指定的属性节点。如果当前节点是元素节点且存在指定的属性,返回 true;否则返回 false
MoveToContent()移动到下一个元素节点或文本节点。如果当前节点是元素、文本、注释等类型节点,返回 true;否则返回 false
MoveToContentAsync()异步版本 MoveToContent() 。该方法返回一个 Task<bool>,表示操作是否成功。
MoveToElement()将游标从当前的属性节点移动到包含该属性的元素节点。返回 true 如果移动成功,false 如果当前节点不是属性节点。
MoveToFirstAttribute()移动到当前元素节点的第一个属性节点。如果当前节点没有属性,返回 false
MoveToNextAttribute()移动到当前元素节点的下一个属性节点。如果没有下一个属性,返回 false

详细说明:

  1. MoveToAttribute()

    • 将游标从当前的元素节点移动到指定名称的属性节点。例如,如果当前在 <book> 元素节点上,可以使用此方法移动到 titleauthor 等属性。
    • 如果指定的属性存在,返回 true,否则返回 false
  2. MoveToContent()

    • 用于跳过当前的非内容节点(例如,空格、注释等),直接跳转到下一个内容节点(例如元素或文本节点)。它会跳过任何不包含实际数据的节点。
    • 如果成功跳转到内容节点,返回 true;如果没有更多的内容节点,返回 false
  3. MoveToContentAsync()

    • MoveToContent() 功能相同,但该方法是异步的。它返回一个 Task<bool>,表示移动是否成功,允许在不阻塞主线程的情况下进行操作。
  4. MoveToElement()

    • 当游标当前位于属性节点时,调用此方法可以将游标移动回包含该属性的元素节点。返回 true 表示成功,否则返回 false
  5. MoveToFirstAttribute()

    • 如果当前元素节点包含属性,调用此方法会将游标移动到第一个属性节点。如果元素没有任何属性,返回 false
  6. MoveToNextAttribute()

    • 在当前元素节点的属性列表中,调用此方法会将游标移动到下一个属性节点。如果没有更多的属性,返回 false

这些方法在 XML 文档的解析中非常有用,可以帮助我们在元素和属性之间导航,灵活地获取不同类型的数据。

ReadTo…()方法

XmlReader 中的 ReadToDescendantReadToFollowingReadToNextSibling 是用于导航和移动游标到 XML 文档中不同节点的方法。它们允许我们跳过当前节点,直接跳到文档中的其他节点。:

函数名介绍
ReadToDescendant()将游标移动到当前节点的第一个子元素节点。如果当前节点没有子元素,返回 false,否则返回 true
ReadToFollowing()将游标移动到当前节点之后的下一个元素节点。如果找不到符合条件的节点,返回 false
ReadToNextSibling()将游标移动到当前节点的下一个兄弟节点。如果没有兄弟节点,返回 false

详细说明:

  1. ReadToDescendant()

    • 用途:用于将游标直接移动到当前节点的第一个子孙元素节点。如果当前节点有子孙元素,这个方法会跳过所有非元素节点(如文本节点、注释节点等),并停留在第一个子孙元素节点上。
    • 返回值:如果成功找到子孙元素节点,返回 true;如果当前节点没有子孙元素,返回 false
    • 适用场景:这个方法特别适用于你想要快速跳到某个元素的嵌套子元素时。例如,在遍历复杂的 XML 文档时,你可以使用 ReadToDescendant 跳过当前节点,直接进入它的第一个子元素。

    示例

    // 假设当前在 <book> 节点上,下面的 XML 结构中有子孙元素 <title> 和 <author>。
    if (reader.ReadToDescendant("title")) {
        // 现在游标已经移动到 <title> 节点。
        string title = reader.ReadElementContentAsString();
        Console.WriteLine("Title: " + title);
    }
    
  2. ReadToFollowing()

    • 用途:将游标移动到当前节点之后的下一个符合条件的元素节点。它跳过所有的非元素节点,直到找到下一个元素节点。可以选择指定元素名称,跳到特定类型的节点。
    • 返回值:如果成功找到下一个元素节点,返回 true;如果找不到符合条件的节点,返回 false
    • 适用场景:当你想跳到文档中某个特定位置并继续解析后续元素时,可以使用此方法。你可以指定一个特定的节点名称,跳到下一个匹配的元素。

    示例

    // 假设我们当前在 <book> 节点中,下面有 <title> 和 <author> 节点。
    // 使用 ReadToFollowing 来跳到下一个符合条件的元素
    if (reader.ReadToFollowing("author")) {
        // 游标已经移动到 <author> 节点
        string author = reader.ReadElementContentAsString();
        Console.WriteLine("Author: " + author);
    }
    
  3. ReadToNextSibling()

    • 用途:将游标移动到当前节点的下一个兄弟节点。兄弟节点是指当前节点同一级别上的其他节点。例如,在父节点 <book> 下的兄弟节点可以是 <author><title> 等。
    • 返回值:如果当前节点有下一个兄弟节点,返回 true;如果没有兄弟节点,返回 false
    • 适用场景:当你需要遍历同一级别的多个兄弟节点时,可以使用 ReadToNextSibling()。这在解析具有平行结构的 XML 时特别有用。

    示例

    // 假设我们当前在 <title> 节点
    // 移动到下一个兄弟节点 <author>
    if (reader.ReadToNextSibling("author")) {
        string author = reader.ReadElementContentAsString();
        Console.WriteLine("Author: " + author);
    }
    

总结对比:

方法功能返回值适用场景
ReadToDescendant()移动到当前节点的第一个子孙元素节点truefalse当你需要进入嵌套的元素节点时,跳过当前节点并寻找子元素。
ReadToFollowing()移动到当前节点后的下一个元素节点truefalse当你需要继续遍历后续元素节点时,跳过非元素节点并找到下一个符合条件的元素。
ReadToNextSibling()移动到当前节点的下一个兄弟节点truefalse当你需要遍历同一层级的元素节点时,跳到下一个兄弟节点。

这些方法帮助我们在遍历 XML 文档时,灵活地从当前节点跳转到其他相关节点,避免手动处理节点的复杂层次。

以下是 XmlReader 类成员函数的表格,包括函数名和介绍:

函数名介绍
Read()读取下一个节点并移动游标。如果成功,返回 true,否则返回 false,直到文档结束。
ReadStartElement()读取下一个开始元素节点,并移动游标。如果当前节点不是开始元素,会抛出异常。
ReadEndElement()读取下一个结束元素节点,并移动游标。如果当前节点不是结束元素,会抛出异常。
ReadElementContentAsString()读取当前元素节点的内容并作为字符串返回。
ReadInnerXml()获取当前节点的内部 XML,返回从当前节点开始的所有内容(不包括当前节点本身)。
ReadOuterXml()获取当前节点的外部 XML,包括当前节点本身及其所有子节点。
GetAttribute()获取当前节点的指定属性值,如果属性不存在则返回 null
MoveToAttribute()移动到指定的属性节点。返回 true 如果该属性存在,false 如果该属性不存在。
MoveToElement()将游标移动回元素节点。
MoveToFirstAttribute()移动到第一个属性节点,如果当前节点没有属性,则返回 false
MoveToNextAttribute()移动到下一个属性节点,返回 true 如果存在下一个属性节点,false 如果没有。
IsStartElement()检查当前节点是否为开始元素节点,返回 true 如果是,false 如果不是。
IsEndElement()检查当前节点是否为结束元素节点,返回 true 如果是,false 如果不是。
NodeType获取当前节点的类型,例如 ElementTextAttribute 等。
Name获取当前节点的名称(如果是元素节点,则是元素的名称;如果是属性节点,则是属性的名称)。
LocalName获取当前节点的本地名称,不包含任何命名空间前缀。
NamespaceURI获取当前节点的命名空间 URI。如果当前节点没有命名空间,则返回空字符串。
Depth获取当前节点的深度,即当前节点在 XML 树中的层级。
IsEmptyElement检查当前节点是否是一个空元素(例如 <element />),返回 truefalse
BaseURI获取当前节点的基本 URI。如果无法确定 URI,则返回一个空字符串。
HasValue检查当前节点是否有值。如果是元素节点且有子节点,或是文本节点,返回 true;否则返回 false
Close()关闭 XmlReader 实例,释放相关资源。
ReadStartElementAsync()异步读取下一个开始元素节点。
ReadEndElementAsync()异步读取下一个结束元素节点。

假设我们有一个简单的 XML 片段

<book>
  <title lang="en">Introduction to XML</title>
  <author>John Doe</author>
</book>

一个伪代码用例为:

// 创建 XmlReader 实例
xmlReader = CreateXmlReader("books.xml")
// 开始读取文档
while (xmlReader.Read())  // 循环直到文件结束
    if (xmlReader.IsStartElement())  // 如果当前节点是一个开始元素
        if (xmlReader.Name == "title")  // 检查节点名称是否为 "title"
            title = xmlReader.ReadElementContentAsString()  // 获取该元素的内容作为字符串
            language = xmlReader.GetAttribute("lang")  // 获取 "lang" 属性的值
            print("Title: " + title + ", Language: " + language)
        else if (xmlReader.Name == "author")  // 检查是否为 "author" 元素
            author = xmlReader.ReadElementContentAsString()  // 获取该元素的内容
            print("Author: " + author)

// 关闭 XmlReader 实例
xmlReader.Close()

结束

以上,即为本章的所有内容。
下一篇文章将详细介绍XMLReader/XMLWriter的使用技巧,以及常见但十分隐蔽的误区。


http://www.kler.cn/a/596589.html

相关文章:

  • ES集群的部署
  • Pytest的夹具
  • 论文阅读笔记——EWA Volume Splatting
  • CityEngine:3D城市建模专家
  • C++进阶——封装红黑树实现map和set
  • Selenium Web UI自动化测试:从入门到实战
  • C#与西门子PLC的六大通信库
  • 使用LangChain开发智能问答系统
  • 最优编码树的双子性
  • TopK问题
  • 常考计算机操作系统面试习题(二)(上)
  • AI生成移动端贪吃蛇游戏页面,手机浏览器打开即可玩
  • Linux进程控制(四)之进程程序替换
  • 新能源汽车高压液体加热器总成技术解析及未来发展趋势
  • HashMap学习总结——JDK17
  • 介绍一个测试boostrap表格插件的好网站!
  • LVGL学习1
  • 【云上CPU玩转AIGC】——腾讯云高性能应用服务HAI已支持DeepSeek-R1模型预装环境和CPU算力
  • 基于linux平台的C语言入门教程(4)输入输出
  • SQL中的索引是什么