前言
命名空间
.Net中有System.Xml命名空间为处理XML提供基于标准的支持。
常用类
XmlDocument:可使用此类在文档中加载、验证、编辑、添加和放置 XML。
XmlElement:表示一个元素。
XmlNode:表示 XML 文档中的单个节点。
XmlReader:表示提供对 XML 数据进行快速、非缓存、只进访问的读取器。
XmlWriter:表示一个写入器,该写入器提供一种快速、非缓存和只进方式以生成包含 XML 数据的流或文件。
本文说明
以下的范例代码,无特殊说明,均为我自定义的一个XmlUtil类的方法。
这个类有两个重要的属性:
#region 对象、属性
///
<summary>
///
XmlUtil类加载的XML文件
///
</summary>
private
string _filePath =
null;
///
<summary>
///
XmlUtil类持有的XmlDocument对象
///
</summary>
private XmlDocument _xmlDoc =
null;
///
<summary>
///
XmlUtil类加载的XML文件
///
</summary>
public
string FilePath {
get {
return
this._filePath; }
set {
this._filePath = value; }
}
///
<summary>
///
XmlUtil类持有的XmlDocument对象
///
</summary>
public XmlDocument XmlDoc {
get {
return
this._xmlDoc; }
set {
this._xmlDoc = value; }
}
#endregion
创建XML文件
步骤:
- 创建一个XmlDocument对象
- 写入内容
- 使用 XmlDocument 类的 Save 方法保存内容
有两种方法
例1:加载xml文件内容字符串,创建xml文档
XmlDocument doc = new XmlDocument();
doc.LoadXml("
<
book
ISBN
='1-861001-57-5'
>" +
"
<
title
>Pride And Prejudice
</
title
>" +
"
<
price
>19.95
</
price
>" +
"
</
book
>");
doc.Save("d:\\result.xml");
这种方法的缺点在于,你必须保证LoadXml方法加载的xml内容格式必须正确。
例2:创建一个xml文档
功能代码
///
<summary>
///
如果文件不存在则创建一个带有根节点的Xml 文件,如果文件存在,则打开XML文件
///
</summary>
///
<param name="filePath">
文件路径
</param>
///
<param name="rootName">
根节点名
</param>
///
<returns>
0表示成功,其他为失败
</returns>
public
int CreateXmlDocument(
string filePath,
string rootName) {
if (
string.IsNullOrEmpty(filePath)) {
return -
1;
}
//
如果文件存在,则直接打开
if (File.Exists(filePath)) {
return
this.OpenXmlDocument(filePath);
}
try {
this._xmlDoc =
new XmlDocument();
//
创建声明节点
XmlDeclaration xmldecl =
this._xmlDoc.CreateXmlDeclaration(
"
1.0
",
"
utf-8
",
null);
this._xmlDoc.AppendChild(xmldecl);
//
创建根节点
XmlElement xmlRoot =
this._xmlDoc.CreateElement(
"", rootName,
"");
this._xmlDoc.AppendChild(xmlRoot);
//
保存
this._xmlDoc.Save(filePath);
this.FilePath = filePath;
return
0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
return -
1;
}
}
测试代码
XmlUtil util =
new XmlUtil();
int code = util.CreateXmlDocument(
"
D:\\temp\\class.xml
",
"
Configuration
");
测试结果
创建class.xml文件成功,内容如下:
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
/>
打开XML文件
步骤:
- 创建一个 XmlDocument 对象
- 用XmlDocument 类的Load方法加载指定xml文件的路径
功能代码
///
<summary>
///
打开XML文档
///
</summary>
///
<param name="filePath">
文件路径
</param>
///
<returns>
0表示成功,其他为失败
</returns>
public
int OpenXmlDocument(
string filePath) {
if (
string.IsNullOrEmpty(filePath)) {
return -
1;
}
if (!File.Exists(filePath)) {
return -
1;
}
try {
this._xmlDoc =
new XmlDocument();
this._xmlDoc.Load(filePath);
this.FilePath = filePath;
return
0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
return -
1;
}
}
测试代码
XmlUtil util =
new XmlUtil();
int code = util.OpenXmlDocument(
"
D:\\temp\\class.xml
");
if (
0 == code &&
null != util.XmlDoc) {
Console.WriteLine(
"
打开XML文件成功
");
}
测试结果
输出
保存XML文件
使用XmlDocument类的Save方法
功能代码:
使用本方法的前提是先调用 CreateXmlDocument 或 OpenXmlDocument,以初始化xml文件路径和XmlDoc属性。
///
<summary>
///
保存XML文档
///
</summary>
///
<returns>
0表示成功,其他为失败
</returns>
public
int SaveXmlDocument() {
if (
null ==
this._xmlDoc ||
string.IsNullOrEmpty(
this.FilePath)) {
return -
1;
}
try {
this._xmlDoc.Save(
this.FilePath);
return
0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
return -
1;
}
}
测试代码:
XmlUtil util =
new XmlUtil();
int code = util.OpenXmlDocument(
"
D:\\temp\\class.xml
");
if (
0 == code &&
null != util.XmlDoc) {
Console.WriteLine(
"
打开XML文件成功
");
}
code = util.SaveXmlDocument();
if (
0 == code) {
Console.WriteLine(
"
保存XML文件成功
");
}
测试结果:
输出
增
步骤:
- 创建 XmlDocument 对象
- 调用 XmlDocument 类的 CreateElement 方法创建新节点
- 调用 XmlDocument 类的 AppendChild 方法将新节点加到一个已存在的节点下
功能代码
///
<summary>
///
在一个已存在的节点下新增XML节点。如果key节点在父节点下已存在,则返回失败
///
</summary>
///
<param name="parent">
要插入元素的父节点路径。类似"Class/Student",不要包含根节点。如果为空,则key节点会插入根节点下。
</param>
///
<param name="key">
要插入元素的key
</param>
///
<param name="value">
要插入元素的value,如果为空。则key节点会是一个空节点。
</param>
///
<param name="attributes">
要插入元素的属性。如果为null,key节点没有属性值
</param>
///
<returns>
0为成功,其他为失败
</returns>
public
int InsertNewNodeToXml(
string parent,
string key,
string value, Dictionary<
string,
string> attributes) {
if (
null ==
this._xmlDoc ||
string.IsNullOrEmpty(key)) {
return -
1;
}
try {
//
如果parent为空,则将节点key插入根节点下
XmlElement root =
this._xmlDoc.DocumentElement;
XmlNode parentNode =
null;
if (
string.IsNullOrEmpty(parent)) {
parentNode = root;
}
else {
//
获取父节点
parentNode = root.SelectSingleNode(parent);
if (
null == parentNode) {
Console.WriteLine(
"
未找到父节点
");
return -
1;
}
}
//
如果要插入的node已存在,结束方法
XmlNode newNode = parentNode.SelectSingleNode(key);
if (
null != newNode) {
return -
1;
}
//
创建key节点,并设置它的value
XmlElement elem =
this._xmlDoc.CreateElement(key);
if (!
string.IsNullOrEmpty(value)){
elem.InnerText = value;
}
//
遍历属性字典,设置key节点的属性
if (
null != attributes &&
0 != attributes.Count) {
foreach(KeyValuePair<
string,
string> kv
in attributes){
XmlAttribute newAttribute =
this._xmlDoc.CreateAttribute(kv.Key);
newAttribute.Value = kv.Value;
elem.SetAttributeNode(newAttribute);
}
}
//
将新节点添加到父节点
parentNode.AppendChild(elem);
return
0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
return -
1;
}
}
测试前提
以下两个测试例的xml初始内容一样,如下:
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
/>
测试一代码
XmlUtil util =
new XmlUtil();
int code = util.OpenXmlDocument(
"
D:\\temp\\class.xml
");
if (
0 == code &&
null != util.XmlDoc) {
Console.WriteLine(
"
打开XML文件成功
");
}
Dictionary<
string,
string> attributes =
new Dictionary<
string,
string>();
attributes.Add(
"
name
",
"
张三
");
attributes.Add(
"
sex
",
"
男
");
attributes.Add(
"
age
",
"
22
");
code = util.InsertNewNodeToXml(
"",
"
Class
",
"");
code = util.InsertNewNodeToXml(
"
Class
",
"
Student
",
"
张三
", attributes);
code = util.SaveXmlDocument();
if (
0 == code) {
Console.WriteLine(
"
保存XML文件成功
");
}
测试结果
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
name
="张三"
sex
="男"
age
="22"
>张三
</
Student
>
</
Class
>
</
Configuration
>
测试二代码
XmlUtil util =
new XmlUtil();
int code = util.OpenXmlDocument(
"
D:\\temp\\class.xml
");
if (
0 == code &&
null != util.XmlDoc) {
Console.WriteLine(
"
打开XML文件成功
");
}
code = util.InsertNewNodeToXml(
"",
"
Class
",
"");
code = util.InsertNewNodeToXml(
"
Class
",
"
Student
",
"
张三
",
null);
code = util.SaveXmlDocument();
if (
0 == code) {
Console.WriteLine(
"
保存XML文件成功
");
}
测试结果
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
>张三
</
Student
>
</
Class
>
</
Configuration
>
删
删除节点
XmlElement 和 XmlNode 两个类都提供了以下两个方法:
RemoveChild,删除一个指定的子节点。
RemoveAll,删除所有子节点。
功能代码
///
<summary>
///
删除prefix节点下所有的指定节点和它的所有子节点
///
</summary>
///
<param name="prefix">
前驱节点,如果不指定,默认为根节点。形式为类似Class/Student
</param>
///
<param name="key">
要删除的节点的键
</param>
///
<param name="value">
要删除的节点的值,如果value为空,则删除所有节点名为key的节点
</param>
///
<returns>
0为成功,其他为失败
</returns>
public
int RemoveNode(
string prefix,
string key,
string value) {
if (
null ==
this._xmlDoc ||
string.IsNullOrEmpty(key)) {
return -
1;
}
try {
//
获取前驱节点并校验
XmlNode prefixNode =
this._xmlDoc.DocumentElement;
if (!
string.IsNullOrEmpty(prefix)) {
prefixNode =
this._xmlDoc.DocumentElement.SelectSingleNode(prefix);
}
if (
null == prefixNode) {
return -
1;
}
XmlNode parentNode =
null;
XmlNodeList nodes = prefixNode.ChildNodes;
for (
int i =
0; i < nodes.Count; i++) {
XmlNode node = nodes[i];
if (node.Name.Equals(key)) {
if (
string.IsNullOrEmpty(value)) {
parentNode = node.ParentNode;
node.RemoveAll();
parentNode.RemoveChild(node);
i--;
//
删除节点后,其他元素下标会改变
}
else {
if (node.InnerText.Equals(value)) {
parentNode = node.ParentNode;
node.RemoveAll();
parentNode.RemoveChild(node);
i--;
//
删除节点后,其他元素下标会改变
}
}
}
}
return
0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
return -
1;
}
}
测试前提
原xml文件内容:
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
>张三
</
Student
>
<
Student
>李四
</
Student
>
<
Student
>王五
</
Student
>
<
Student
>张三
</
Student
>
<
Student
>李四
</
Student
>
<
Student
>王五
</
Student
>
</
Class
>
</
Configuration
>
测试代码
XmlUtil util =
new XmlUtil();
int code = util.OpenXmlDocument(
"
D:\\temp\\class.xml
");
if (
0 == code &&
null != util.XmlDoc) {
Console.WriteLine(
"
打开XML文件成功
");
}
code = util.RemoveNode(
"
Class
",
"
Student
",
"
张三
");
code = util.SaveXmlDocument();
if (
0 == code) {
Console.WriteLine(
"
保存XML文件成功
");
}
测试结果
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
>李四
</
Student
>
<
Student
>王五
</
Student
>
<
Student
>李四
</
Student
>
<
Student
>王五
</
Student
>
</
Class
>
</
Configuration
>
删除属性
XmlElement 提供了以下方法删除属性:
RemoveAttribute
RemoveAllAttributes
RemoveAttributeAt
RemoveAttributeNode
例:删除一个指定节点的属性
功能代码
///
<summary>
///
删除名为key的节点的attribute属性
///
</summary>
///
<param name="key">
节点key
</param>
///
<param name="attribute">
节点attribute
</param>
public
int RemoveAttribute(
string key,
string attribute) {
if (
null ==
this._xmlDoc ||
string.IsNullOrEmpty(key) ||
string.IsNullOrEmpty(attribute)) {
return -
1;
}
try {
//
获取前驱节点并校验
XmlElement keyElem = (XmlElement)
this._xmlDoc.DocumentElement.SelectSingleNode(key);
if (
null == keyElem) {
return -
1;
}
keyElem.RemoveAttribute(attribute);
return
0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
return -
1;
}
}
测试前提
原xml文件内容:
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
name
="李四"
age
="27"
sex
="男"
>李四
</
Student
>
</
Class
>
</
Configuration
>
测试代码
XmlUtil util =
new XmlUtil();
int code = util.OpenXmlDocument(
"
D:\\temp\\class.xml
");
if (
0 == code &&
null != util.XmlDoc) {
Console.WriteLine(
"
打开XML文件成功
");
}
code = util.RemoveAttribute(
"
Class/Student
",
"
age
");
code = util.SaveXmlDocument();
if (
0 == code) {
Console.WriteLine(
"
保存XML文件成功
");
}
测试结果
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
name
="李四"
sex
="男"
>李四
</
Student
>
</
Class
>
</
Configuration
>
改
改节点值
步骤:
- 创建一个 XmlDocument 对象
- 通过 SelectSingleNode 方法找到指定节点
- 给 InnerText 属性赋值
功能代码
///
<summary>
///
修改所有值为oldValue的key节点,新值为newValue
///
</summary>
///
<param name="prefix">
前驱路径
</param>
///
<param name="key">
节点key
</param>
///
<param name="oldValue">
旧值
</param>
///
<param name="newValue">
新值
</param>
///
<returns>
0表示成功,其他为失败
</returns>
public
int SetXmlNodeValue(
string prefix,
string key,
string oldValue,
string newValue) {
if (
null ==
this._xmlDoc ||
string.IsNullOrEmpty(key)
||
string.IsNullOrEmpty(oldValue) ||
string.IsNullOrEmpty(newValue)) {
return -
1;
}
try {
//
获取前驱节点并校验
XmlNode prefixNode =
this._xmlDoc.DocumentElement;
if (!
string.IsNullOrEmpty(prefix)) {
prefixNode =
this._xmlDoc.DocumentElement.SelectSingleNode(prefix);
}
if (
null == prefixNode) {
return -
1;
}
XmlNodeList nodes = prefixNode.ChildNodes;
for (
int i =
0; i < nodes.Count; i++) {
XmlNode node = nodes[i];
if (node.Name.Equals(key) && node.InnerText.Equals(oldValue)) {
node.InnerText = newValue;
}
}
return
0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
return -
1;
}
}
测试前提
原xml文件内容为:
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
>张三
</
Student
>
<
Student
>李四
</
Student
>
<
Student
>王五
</
Student
>
<
Student
>张三
</
Student
>
<
Student
>李四
</
Student
>
<
Student
>王五
</
Student
>
</
Class
>
</
Configuration
>
测试代码
XmlUtil util =
new XmlUtil();
int code = util.OpenXmlDocument(
"
D:\\temp\\class.xml
");
if (
0 == code &&
null != util.XmlDoc) {
Console.WriteLine(
"
打开XML文件成功
");
}
code = util.SetXmlNodeValue(
"
Class
",
"
Student
",
"
张三
",
"
zhangsan
");
code = util.SaveXmlDocument();
if (
0 == code) {
Console.WriteLine(
"
保存XML文件成功
");
}
测试结果
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
>zhangsan
</
Student
>
<
Student
>李四
</
Student
>
<
Student
>王五
</
Student
>
<
Student
>zhangsan
</
Student
>
<
Student
>李四
</
Student
>
<
Student
>王五
</
Student
>
</
Class
>
</
Configuration
>
改节点属性
步骤:
- 创建一个 XmlDocument 对象
- 通过 SelectSingleNode 方法找到指定节点
- 通过 SetAttribute 方法给指定的属性设置值
功能代码
///
<summary>
///
设置第一个满足key和attribute的XML节点的值
///
</summary>
///
<param name="key">
节点key
</param>
///
<param name="attribute">
属性名
</param>
///
<param name="value">
指定节点的特定属性的值
</param>
///
<returns>
0表示成功,其他为失败
</returns>
public
int SetXmlNodeAttributeValue(
string key,
string attribute,
string value) {
if (
null ==
this._xmlDoc ||
string.IsNullOrEmpty(key)) {
return -
1;
}
try {
//
如果parent为空,则将节点key插入根节点下
XmlElement elem = (XmlElement)
this._xmlDoc.DocumentElement.SelectSingleNode(key);
if (
null == elem) {
return -
1;
}
elem.SetAttribute(attribute, value);
return
0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
return -
1;
}
}
测试前提
原xml文件内容:
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
name
="张三"
, age
="18"
, sex
="男"
>张三
</
Student
>
</
Class
>
</
Configuration
>
测试代码
XmlUtil util =
new XmlUtil();
int code = util.OpenXmlDocument(
"
D:\\temp\\class.xml
");
if (
0 == code &&
null != util.XmlDoc) {
Console.WriteLine(
"
打开XML文件成功
");
}
code = util.SetXmlNodeAttributeValue(
"
Class/Student
",
"
age
",
"
28
");
code = util.SaveXmlDocument();
if (
0 == code) {
Console.WriteLine(
"
保存XML文件成功
");
}
测试结果
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
name
="张三"
age
="28"
sex
="男"
>张三
</
Student
>
</
Class
>
</
Configuration
>
查
查找节点的值
步骤:
- 通过 SelectSingleNode 方法找到节点
- 读取 InnerText 属性的值
功能代码
///
<summary>
///
获取第一个满足key的XML节点的值
///
</summary>
///
<param name="key">
节点key
</param>
///
<param name="value">
出参,指定节点的的值
</param>
///
<returns>
0表示成功,其他为失败
</returns>
public
int GetXmlNodeValue(
string key,
out
string value) {
value =
null;
if (
null ==
this._xmlDoc) {
return -
1;
}
try {
//
根据指定路径获取节点
XmlNode xmlNode =
this._xmlDoc.DocumentElement.SelectSingleNode(key);
if (
null == xmlNode) {
return -
1;
}
value = xmlNode.InnerText;
return
0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
return -
1;
}
}
测试前提
原xml内容
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
name
="张三"
age
="28"
sex
="男"
>张三
</
Student
>
</
Class
>
</
Configuration
>
测试代码
XmlUtil util =
new XmlUtil();
int code = util.OpenXmlDocument(
"
D:\\temp\\class.xml
");
if (
0 == code &&
null != util.XmlDoc) {
Console.WriteLine(
"
打开XML文件成功
");
}
string value;
code = util.GetXmlNodeValue(
"
Class/Student
",
out value);
Console.WriteLine(
"
value =
" + value);
测试结果
输出
查找节点属性的值
步骤:
- 通过 SelectSingleNode 方法找到节点
- 用节点的Attributes属性初始化XmlAttributeCollection类
- 查找指定的属性名,修改其value
功能代码
///
<summary>
///
获取第一个满足key和attribute的XML节点的值
///
</summary>
///
<param name="key">
节点key
</param>
///
<param name="attribute">
属性名
</param>
///
<param name="value">
出参,指定节点的特定属性的值
</param>
///
<returns>
0表示成功,其他为失败
</returns>
public
int GetXmlNodeAttributeValue(
string key,
string attribute,
out
string value) {
value =
null;
if (
null ==
this._xmlDoc) {
return -
1;
}
try {
//
根据指定路径获取节点
XmlNode xmlNode =
this._xmlDoc.DocumentElement.SelectSingleNode(key);
if (
null == xmlNode) {
return -
1;
}
//
获取节点的属性,并循环取出需要的属性值
XmlAttributeCollection xmlAttr = xmlNode.Attributes;
for (
int i =
0; i < xmlAttr.Count; i++) {
if (xmlAttr.Item(i).Name.Equals(attribute)) {
value = xmlAttr.Item(i).Value;
break;
}
}
return
0;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
return -
1;
}
}
测试前提
原xml内容
<?
xml version="1.0" encoding="utf-8"
?>
<
Configuration
>
<
Class
>
<
Student
name
="张三"
age
="28"
sex
="男"
>张三
</
Student
>
</
Class
>
</
Configuration
>
测试代码
XmlUtil util =
new XmlUtil();
int code = util.OpenXmlDocument(
"
D:\\temp\\class.xml
");
if (
0 == code &&
null != util.XmlDoc) {
Console.WriteLine(
"
打开XML文件成功
");
}
string attributeValue;
code = util.GetXmlNodeAttributeValue(
"
Class/Student
",
"
age
",
out attributeValue);
Console.WriteLine(
"
attributeValue =
" + attributeValue);
测试结果
打开XML文件成功
attributeValue =
28
参考资料
https://msdn.microsoft.com/zh-cn/library/system.xml.aspx