🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏
文章目录
🚀一、XML
🔎1.XML的概述
XML是一种可扩展标记语言,用于描述和交换数据。它是一种文本格式,可以在不同的计算机系统和应用程序之间进行数据交换。XML由标记组成,每个标记都有一个开始标记和一个结束标记。标记中包含数据,也可以包含属性。
XML的设计目的是为了使文档具有结构性,并便于在不同的应用程序之间共享数据。XML支持的标记可以自定义,并且可以扩展,从而使XML更加灵活和适合于特定的应用领域。在Web开发中,XML常用于描述数据,例如RSS、SOAP、SVG等。
与HTML相比,XML的表现力更强,更适合用于数据交换和文档描述。但与HTML不同的是,XML本身不定义任何标记,所有标记都需要根据应用领域的需求进行定义。
🔎2.XML的创建、语法规则
XML的创建:可以使用文本编辑器手动创建XML文件,也可以通过各种编程语言的API,在程序中动态地创建和操作XML文档。
XML的语法规则:
-
XML文档是由一个或多个元素构成的树形结构。
-
每个元素都由开始标签、结束标签和标签内容组成。
-
开始标签和结束标签是一对,结束标签与开始标签相同,但在标签前面加上“/”。
-
元素可以有属性,属性由属性名和属性值组成,用等号连接。
-
标签和属性名都必须是大小写敏感的。
-
元素可以包含其他元素和文本节点。文本节点是元素的内容,不能包含标签或实体引用。
-
注释以“ ”结尾。
-
实体引用用来表示特殊字符,如“<”表示小于号“<”。
-
XML文档必须有根元素,所有其他元素必须是其子元素。
-
XML文档必须包含声明行,形式为“<?xml version="1.0" encoding="UTF-8"?>”,其中version指定XML版本,encoding指定字符集编码。
XML有五个特殊字符,需要用特殊的方式来表示它们,否则会与XML的语法规则产生冲突。这五个特殊字符是:
-
“&”(ampersand):用来表示XML中的实体引用开始。例如,< 表示 <。
-
“<”(less-than):用来表示标签的开始。
-
“>”(greater-than):用来表示标签的结束。
-
“'”(apostrophe):用来表示XML中的字符串值开始和结束。
-
“”"(quotation mark):同样用来表示XML中的字符串值开始和结束。
当文本中包含以上特殊字符时,需要使用CDATA(Character Data)标记将其包裹起来,以告诉解析器这些字符不应被解析,而是作为纯文本处理。CDATA标记的语法格式如下:
<![CDATA[ 文本内容]]>
例如,下面的XML代码段中,CDATA将 和 包裹起来,表示它们是纯文本而非标签。
<example>
<message>
<![CDATA[<hello> This is a message. </hello>]]>
</message>
</example>
在浏览器中显示时,CDATA中的文本将会被正常显示,而不被解析为XML元素。
🔎3.XML文档约束
🦋3.1 DTD约束
DTD(Document Type Definition,文档类型定义)是一种XML文档约束,用于定义XML文档的结构、元素和属性的规范。使用DTD可以确保XML文档的格式和结构符合预期,可以帮助开发者在开发过程中遵循一致的标准。
在XML文档中定义DTD,可以通过以下两种方式之一:
-
内部DTD:将DTD定义直接嵌入XML文档中,使用<!DOCTYPE>声明定义,放在XML文档的开头。
-
外部DTD:将DTD定义保存到一个单独的文件中,使用<!DOCTYPE>声明引用,放在XML文档的开头。
例如,以下是一个简单的XML文档和内部DTD的示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article [
<!ELEMENT article (title, author, content)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT content (#PCDATA)>
]>
<article>
<title>XML 文档约束-DTD 的使用</title>
<author>张三</author>
<content>本文介绍了使用DTD定义XML文档的结构和规范</content>
</article>
在上述示例中,我们使用了内部DTD来定义article元素必须包含title、author和content三个子元素,并且这三个子元素只能包含文本内容。如果XML文档不符合此结构,将无法通过DTD的约束检查。
使用DTD可以帮助我们编写出更加规范、有序的XML文档,提高开发的效率和质量。但是,在DTD的定义过程中要注意规范性和灵活性的平衡,以及与应用程序的兼容性问题。
🦋3.2 schema约束
XML文档约束是指为XML文档定义的一组规则,它规定了文档中的元素、属性、数据类型和结构等方面的限制。XML Schema是一种用于定义XML文档约束的语言,它可以用于验证XML文档的内容和格式是否符合规定。
使用XML Schema可以帮助开发人员更好地管理和验证XML文档,以确保其符合特定的格式和数据要求。以下是使用XML Schema的步骤:
-
创建一个XML Schema文件,通常以.XSD作为后缀名。
-
在XML Schema文件中定义XML文档中可能出现的元素和属性,以及它们的数据类型和结构。
-
在XML文档中引用该XML Schema文件,并设置文档的根元素为该文件中定义的一个元素。
-
解析XML文档以验证其内容和格式是否符合XML Schema定义的规则。
例如,下面是一个XML Schema文件的示例:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:integer"/>
</xs:sequence>
<xs:attribute name="gender" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>
该XML Schema定义了一个名为person的元素,它包含名为name和age的元素,以及一个名为gender的属性。name元素是一个字符串类型,age元素是一个整数类型,gender属性也是一个字符串类型。使用该XML Schema可以确保XML文档中的person元素包含这三个元素和属性,并且它们的数据类型符合定义。
🚀二、XML解析技术
🔎1.XML解析技术概述
XML是一种被广泛使用的数据交换格式,常见于Web应用程序中。Java语言提供了多种XML解析技术,可以将XML数据转换成Java对象或处理XML数据。以下是常见的Java XML解析技术:
-
DOM解析:将整个XML文档读入内存形成一个树形结构的文档对象模型(DOM),可以方便地遍历和修改XML文档。但是,由于整个文档需要完全读入内存,因此对于大型XML文档不太适用。
-
SAX解析:按照XML文档的结构逐行读取XML文档,只保存当前处理的元素和属性,因此不需要完整读取XML文档。SAX解析器将XML文档解析为一系列事件,应用程序可以注册一个或多个事件处理程序来处理这些事件。
-
JAXB解析:Java XML绑定(Java Architecture for XML Binding,JAXB)是一种将Java类与XML文档互相转换的技术。通过在Java类和XML文档之间建立映射关系,可以自动地将Java对象序列化为XML文档或将XML文档反序列化为Java对象。
-
StAX解析:基于流处理的XML解析技术,既可以像SAX解析器一样基于事件模型,也可以像DOM解析器一样使用树形结构。Stax API提供了两种操作模式:游标模式和事件模式,前者是推模式类似于XMLStreamReader,而后者是拉模式类似于XMLStreamWriter。
DOM解析相关的解析工具:
解析工具 | 功能 | 优点 | 缺点 |
---|---|---|---|
JAXP | 解析、转换和验证XML文档 | JAXP是Java官方的XML处理API,易于使用,文档丰富 | 性能较低 |
Xerces-J | DOM解析、SAX解析和DTD验证 | Apache官方XML处理器,稳定性较高,易于使用 | 不支持XPath查询 |
DOM4J | DOM解析、XPath查询和修改XML文档 | 支持XPath查询、API简洁易用 | 性能较低 |
JDOM | DOM解析、XPath查询和修改XML文档 | 支持XPath查询、API简洁易用 | 性能较低 |
SAX | 解析XML文档 | 解析速度快,适合解析大型XML文档 | 不支持修改操作,使用较复杂 |
🔎2.Dom4J解析XML文件
Dom4J是一个Java的XML解析器,用于读取和操作XML文件。以下是使用Dom4J解析XML文件的步骤:
-
在项目中导入Dom4J的jar包。
-
创建SAXReader对象,该对象用于读取XML文件。
-
使用SAXReader对象的read()方法读取XML文件,返回一个Document对象。
-
通过Document对象获取XML文件中的元素和属性,可以使用XPath表达式或者Element对象的方法。
-
根据业务需求,使用Java代码操作XML文件。
下面是一个简单的Dom4J解析XML文件的示例:
import java.io.File;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class Dom4JXMLParser {
public static void main(String[] args) {
try {
// 创建SAXReader对象
SAXReader reader = new SAXReader();
// 读取XML文件
Document document = reader.read(new File("students.xml"));
// 获取根元素
Element root = document.getRootElement();
System.out.println("根元素:" + root.getName());
// 获取所有子元素
List<Element> list = root.elements();
System.out.println("共有" + list.size() + "个学生:");
// 遍历子元素
for (Element e : list) {
System.out.println("姓名:" + e.attributeValue("name") + ",性别:" + e.attributeValue("gender") + ",年龄:" + e.attributeValue("age"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们读取一个名为“students.xml”的XML文件,并获取根元素和子元素。对于每个子元素,我们打印出姓名、性别和年龄属性。
🔎3.Dom4J解析XML文件中的各种节点
方法 | 描述 | 示例 |
---|---|---|
Document.getRootElement() | 获取根元素 | Element root = document.getRootElement(); |
Element.getName() | 获取元素名称 | String name = element.getName(); |
Element.attributeValue(String name) | 获取指定属性的值 | String value = element.attributeValue(“id”); |
Element.element(String name) | 获取指定子元素 | Element childElement = element.element(“title”); |
Element.elements() | 获取所有子元素 | List childElements = element.elements(); |
Element.elements(String name) | 获取指定名称的子元素 | List childElements = element.elements(“book”); |
Element.elementText(String name) | 获取指定子元素的文本内容 | String text = element.elementText(“title”); |
Element.addAttribute(String name, String value) | 添加属性 | element.addAttribute(“id”, “001”); |
Element.addElement(String name) | 添加子元素 | Element childElement = element.addElement(“title”); |
Element.addCDATA(String cdata) | 添加CDATA节点 | element.addCDATA(“<![CDATA[ This is a CDATA section. ]]>”); |
以下是一个完整的Dom4J解析XML文件的示例:
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class Dom4JXMLParser {
public static void main(String[] args) {
try {
// 创建SAXReader对象
SAXReader reader = new SAXReader();
// 读取XML文件
Document document = reader.read(new File("books.xml"));
// 获取根元素
Element root = document.getRootElement();
System.out.println("根元素:" + root.getName());
// 获取所有子元素
List<Element> bookElementList = root.elements("book");
// 遍历子元素
for (Element bookElement : bookElementList) {
// 获取book元素的属性值
String bookId = bookElement.attributeValue("id");
System.out.println("Book ID: " + bookId);
// 获取title元素的文本内容
Element titleElement = bookElement.element("title");
String bookTitle = titleElement.getText();
System.out.println("Book Title: " + bookTitle);
// 获取author元素的文本内容
String bookAuthor = bookElement.elementText("author");
System.out.println("Book Author: " + bookAuthor);
// 获取price元素的文本内容
String bookPrice = bookElement.elementText("price");
System.out.println("Book Price: " + bookPrice);
// 添加新的元素
Element descElement = bookElement.addElement("description");
descElement.setText("This is a good book.");
// 添加新的属性
bookElement.addAttribute("publisher", "Pearson");
// 输出包含新元素和属性的XML
System.out.println("\nModified XML:");
System.out.println(bookElement.asXML());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们首先读取“books.xml”文件,并获取根元素。然后,我们遍历从根元素获取的所有书本元素,并使用各种方法来获取和修改它们的属性和文本内容。最后,我们使用Dom4J添加了一个新的元素和一个新的属性,并输出包含这些新元素和属性的XML。
🔎4.Dom4J解析XML文件-案例实战
假设我们有一个名为“books.xml”的XML文件,其中包含了多本书的信息,每本书有一个唯一的ID、书名、作者和价格。
我们的目标是使用Dom4J解析该XML文件,并将每个书本的信息存储到一个Book对象中,最后将所有的Book对象存储到一个List中。
首先,我们需要定义一个Book类,用于存储每个书本的信息:
public class Book {
private int id;
private String title;
private String author;
private double price;
public Book(int id, String title, String author, double price) {
super();
this.id = id;
this.title = title;
this.author = author;
this.price = price;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book [id=" + id + ", title=" + title + ", author=" + author + ", price=" + price + "]";
}
}
接下来,我们可以编写一个XML解析器,将每个书本的信息解析为一个Book对象:
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class Dom4JXMLParser {
public static void main(String[] args) {
List<Book> bookList = new ArrayList<Book>();
try {
// 创建SAXReader对象
SAXReader reader = new SAXReader();
// 读取XML文件
Document document = reader.read(new File("books.xml"));
// 获取根元素
Element root = document.getRootElement();
System.out.println("根元素:" + root.getName());
// 获取所有子元素
List<Element> bookElementList = root.elements("book");
// 遍历子元素
for (Element bookElement : bookElementList) {
int id = Integer.parseInt(bookElement.attributeValue("id"));
String title = bookElement.elementText("title");
String author = bookElement.elementText("author");
double price = Double.parseDouble(bookElement.elementText("price"));
Book book = new Book(id, title, author, price);
bookList.add(book);
}
// 打印出所有的Book对象
for (Book book : bookList) {
System.out.println(book);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们首先读取“books.xml”文件,并获取根元素。然后,我们通过遍历从根元素获取的所有子元素来提取每个书本的信息,并创建一个新的Book对象将其存储到bookList中。最后,我们遍历bookList并打印出每个Book对象。
🚀三、XML检索技术:Xpath
🔎1.Xpath的概念
XPath 是一种用于在 XML 文档中定位元素和节点的语言。XPath 可以描述文档的结构,包括文档中的元素和属性,以及它们之间的关系,从而使开发者能够在文档中进行精确的选择和查询。XPath 是一个与 XML 规范无关的语言,因此可以在任何基于 XML 的文档中使用,如 HTML、RSS、Atom 等。XPath 由 W3C 定义,并且被广泛应用于 XML 的各种技术中,如 XSLT、XQuery、DOM、SAX 等。
🔎2.Xpath检索出XML文件
🦋2.1 XPath使用步骤
在Dom4J中,我们可以使用XPath来检索XML文件中的数据,XPath是一种用于在XML文档中导航的语言。可以使用Dom4J内置的XPath引擎轻松地使用XPath表达式检索XML文件中的数据。以下是解析XML文件并使用XPath进行检索的示例:
- 导入Dom4J和Jaxen库
需要导入Dom4J和Jaxen库,以便可以使用它的API来解析XML文件和XPath表达式。
- 创建XML文档对象
使用Dom4J的SAXReader类来创建XML文档对象,如下所示:
SAXReader reader = new SAXReader();
Document document = reader.read(new File("file.xml"));
- 使用XPath检索数据
使用Dom4J提供的XPath API来编写XPath表达式并检索XML文件中的数据,如下所示:
List<Node> nodeList = document.selectNodes("//root/childNode");
for (Node node : nodeList) {
String text = node.getText();
// 处理节点数据
}
在此示例中,XPath表达式//root/childNode
用于检索XML文件中<root>
标记下面的所有<childNode>
标记。
完整代码示例:
SAXReader reader = new SAXReader();
Document document = reader.read(new File("file.xml"));
List<Node> nodeList = document.selectNodes("//root/childNode");
for (Node node : nodeList) {
String text = node.getText();
// 处理节点数据
}
🦋2.2 XPath使用方法
以下是使用Dom4J解析XML文件并使用XPath检索的常见方法和示例:
方法 | 描述 | 示例 |
---|---|---|
SAXReader.read(File file) | 使用SAX解析器读取指定的XML文件并返回Document对象 | SAXReader reader = new SAXReader(); Document document = reader.read(new File(“file.xml”)); |
Document.getRootElement() | 返回XML文档的根元素 | Element root = document.getRootElement(); |
Element.element(String name) | 检索指定名称的直接子元素 | Element child = root.element(“child”); |
Element.elements() | 返回所有直接子元素的列表 | List children = root.elements(); |
Element.getName() | 返回元素的名称 | String name = element.getName(); |
Element.getText() | 返回元素的文本内容 | String text = element.getText(); |
Document.selectNodes(String xpathExpression) | 使用XPath表达式检索节点列表 | List nodes = document.selectNodes(“//root/child”); |
Element.selectSingleNode(String xpathExpression) | 使用XPath表达式检索单个节点 | Node node = element.selectSingleNode(“child”); |
示例:
在下面的示例中,我们将解析下面的XML文件。
<?xml version="1.0" encoding="UTF-8"?>
<root>
<child id="1">element one</child>
<child id="2">element two</child>
<child id="3">element three</child>
</root>
- 使用SAXReader解析XML文件并返回Document对象
SAXReader reader = new SAXReader();
Document document = reader.read(new File("file.xml"));
- 获取XML根元素
Element root = document.getRootElement();
- 检索指定名称的直接子元素
Element child = root.element("child");
- 返回所有直接子元素的列表
List<Element> children = root.elements();
- 返回元素的名称
String name = element.getName();
- 返回元素的文本内容
String text = element.getText();
- 使用XPath表达式检索节点列表
List<Node> nodes = document.selectNodes("//root/child");
- 使用XPath表达式检索单个节点
Node node = element.selectSingleNode("child");
这是一个简单的使用Dom4J解析XML文件和使用XPath检索数据的示例。使用Dom4J和XPath轻松地解析和处理XML文件非常简单和方便。
🦋2.3 Xpath的四大检索方案
方案 | 描述 | 示例 |
---|---|---|
绝对路径 | 从根节点开始的完整路径,查找节点 | /bookstore/book[1]/title |
相对路径 | 相对当前节点的路径,查找节点 | ./title 表示当前节点下的title元素; ../author 表示当前节点的父节点下的author元素 |
全文检索 | 通过搜索文本内容来查找节点 | //*[contains(text(),'Java')] 表示查找包含文本“Java”的所有元素 |
属性查找 | 通过元素属性来查找节点 | //*[@id='book1'] 表示查找id属性为“book1”的所有元素 |
示例:
- 绝对路径示例:
假设我们有一个XML文档如下:
<bookstore>
<book category="科幻" id="book1">
<title>Java编程思想</title>
<author>Bruce Eckel</author>
</book>
<book category="文艺" id="book2">
<title>JavaScript高级程序设计</title>
<author>Nicholas C. Zakas</author>
</book>
</bookstore>
如果要查找第一个book元素的title元素,可以使用绝对路径如下:
/bookstore/book[1]/title
- 相对路径示例:
继续使用上面的XML文档,如果当前节点是book元素,我们可以使用相对路径来查找title元素,如下:
./title
这里的“.”表示当前节点,跟Linux中的“.”表示当前目录类似。
- 全文检索示例:
假设我们有一个XML文档如下:
<bookstore>
<book category="科幻" id="book1">
<title>Java编程思想</title>
<author>Bruce Eckel</author>
</book>
<book category="文艺" id="book2">
<title>JavaScript高级程序设计</title>
<author>Nicholas C. Zakas</author>
</book>
</bookstore>
如果要查找包含文本“Java”的所有元素,可以使用全文检索如下:
//*[contains(text(),'Java')]
这里的“*”表示所有元素,包括book、title、author等。
- 属性查找示例:
假设我们有一个XML文档如下:
<bookstore>
<book category="科幻" id="book1">
<title>Java编程思想</title>
<author>Bruce Eckel</author>
</book>
<book category="文艺" id="book2">
<title>JavaScript高级程序设计</title>
<author>Nicholas C. Zakas</author>
</book>
</bookstore>
如果要查找id属性为“book1”的所有元素,可以使用属性查找如下:
//*[@id='book1']
这里的“*”表示所有元素,跟全文检索类似。
🔎3.Xpath检索出HTML文件
下面是一个完整的Java使用Dom4J把一个HTML文件的数据进行解析和使用Xpath检索的案例:
- 添加Dom4J依赖
我们可以在pom.xml文件中添加如下依赖:
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
- 创建HTML文件
我们需要创建一个HTML文件,保存在项目的resources目录下,作为我们的测试文件,例如:
<!DOCTYPE html>
<html>
<head>
<title>Example Page</title>
</head>
<body>
<h1>Title</h1>
<div class="content">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<p>Paragraph 3</p>
</div>
</body>
</html>
- 读取HTML文件并创建Document对象
我们可以使用如下代码读取该HTML文件并使用Dom4J的DocumentHelper类的parseText()方法,创建一个Document对象:
import java.io.File;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
public class HtmlParser {
public static void main(String[] args) throws DocumentException {
String html = FileUtils.readFileToString(new File("src/main/resources/example.html"), StandardCharsets.UTF_8);
Document document = DocumentHelper.parseText(html);
}
}
- 使用Xpath检索数据
我们可以使用如下代码使用Dom4J的XPath类的selectNodes()或者selectSingleNode()方法,使用Xpath表达式从Document对象中检索数据:
import java.util.List;
import org.dom4j.Node;
import org.dom4j.XPath;
public class HtmlParser {
public static void main(String[] args) throws Exception {
String html = FileUtils.readFileToString(new File("src/main/resources/example.html"), StandardCharsets.UTF_8);
Document document = DocumentHelper.parseText(html);
// 使用相对路径检索p元素
XPath xpath = document.createXPath("//div[@class='content']/p");
List<Node> nodes = xpath.selectNodes(document);
// 使用绝对路径检索h1元素
Node node = document.selectSingleNode("/html/body/h1");
// 处理检索到的数据
for (Node n : nodes) {
System.out.println(n.asXML());
}
System.out.println(node.getText());
}
}
在这个例子中,我们使用了相对路径和绝对路径两种方式检索数据。相对路径是从当前节点(例如:document)开始的,而绝对路径通常以根节点开始(例如:/html/body/h1)。我们还将检索到的数据输出到控制台。
输出结果如下:
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<p>Paragraph 3</p>
Title
🚀感谢:给读者的一封信
亲爱的读者,
我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。
如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。
我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。
如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。
再次感谢您的阅读和支持!
最诚挚的问候, “愚公搬代码”