原文地址:https://zhuanlan.zhihu.com/p/337698648
XmlDocument 类的方法和属性
属性 | 描述 |
---|---|
XmlAttributeCollection Attributes { get; } | 获取当前节点的所有属性引用对象集合 |
XmlNodeList ChildNodes { get; } | 获取子级节点集合 |
XmlElement DocumentElement { get; } | 获取文档的根节点 |
XmlDocumentType DocumentType { get; } | 获取XML文档类型定义 |
XmlNodeType NodeType { get; } | 获取当前节点的类型 |
XmlDocument OwnerDocument { get; } | 获取当前节点所属的 XmlDocument 对象 |
XmlNode ParentNode { get; } | 获取父节点(针对可以拥有父级的节点) |
string BaseURI { get; } | 获取文档的地址 |
string InnerText { get; set;} | 获取或设置当前节点和子级的文本 |
string InnerXml { get; set; } | 获取或设置子级节点的标签和文本 |
string LocalName { get; } | 获取节点本地名称 |
string Name { get; } | 获取节点限定名称 |
bool IsReadOnly { get; } | 是否只读 |
bool PreserveWhitespace { get; set; } | 获取或设置元素内容是否保留空白区域 |
XmlNameTable NameTable { get; } | 获取关联的 XmlNameTable |
IXmlSchemaInfo SchemaInfo { get; } | 返回节点的后架构验证信息集 (PSVI) |
XmlSchemaSet Schemas { get; set; } | 获取或设置与此 XmlDocument 关联的XmlSchemaSet 对象 |
XmlNode NextSibling { get; } | 获取下一个节点(XmlNode) |
XmlNode PreviousSibling { get; } | 获取上一个节点(XmlNode) |
XmlNode PreviousText { get; } | 获取该节点之前的文本节点(XmlNode) |
XmlNode LastChild { get; } | 获取该节点的最后一个子节点(XmlNode) |
XmlNode FirstChild { get; } | 获取节点的第一个子级(XmlNode) |
XmlElement Item[string name] { get; } | 获取具有指定Name的第一个子元素 (XmlNode) |
string OuterXml { get; } | 获取当前节点和子级的标签和文本(XmlNode) |
string Prefix { get; set; } | 获取或设置该节点的命名空间前缀(XmlNode) |
string Value { get; set; } | 获取或设置节点的值(XmlNode) |
string NamespaceURI { get; } | 获取该节点的命名空间 URI(XmlNode) |
bool HasChildNodes { get; } | 判断该节点下是否有子节点(XmlNode) |
2. XmlDocument 类的一些常用的方法:
方法 | 描述 |
---|---|
XmlElement CreateElement (string name); | 创建一个新节点 |
XmlAttribute CreateAttribute (string name); | 创建指定名称的属性 |
void SetAttribute(string attribute ,string value); | 为指定节点的新建属性并赋值 |
mlNode AppendChild (XmlNode newChild); | 为指定节点末尾添加子节点(XmlNode) |
XmlAttribute SetAttributeNode(XmlAttribute newAttr); | 指定节点添加指定的属性 |
XmlElement GetElementById (string elementId); | 获取具有指定ID的XmlElement |
XmlNodeList GetElementsByTagName (string name); | 返回一个 XmlNodeList,它包含与指定Name匹配的所有节点的列表,特殊值“*”匹配所有标记 |
XmlNode ImportNode (XmlNode node, bool deep); | 将节点从另一个文档导入到当前文档 |
XmlNode CreateNode (string nodeType, string name, string namespace); | 创建一个节点 |
XmlNode InsertAfter (XmlNode newChild, XmlNode refChild); | 将指定的节点紧接着插入指定的引用节点之后(XmlNode) |
XmlNode InsertBefore (XmlNode newChild, XmlNode refChild); | 将指定的节点紧接着插入指定的引用节点之前(XmlNode) |
void Load (string filename); | 从指定的地址加载 XML 文档 |
void LoadXml (string xml); | 从指定的字符串加载 XML 文档 |
XmlNode PrependChild (XmlNode newChild); | 指定的节点添加到该节点的子节点列表的开头(XmlNode) |
XmlNode SelectSingleNode (string xpath); | 选择一个节点 |
XmlNodeList SelectNodes (string xpath); | 获取同名同级节点集合 |
void RemoveAll (); | 移除当前节点的所有子节点和/或属性(XmlNode) |
XmlNode RemoveChild (XmlNode oldChild); | 移除指定的子节点(XmlNode) |
XmlNode ReplaceChild (XmlNode newChild, XmlNode oldChild); | 用新子节点替换旧子节点(XmlNode) |
void Save (string filename); | 保存XML文件,如果存在指定文件,则此方法会覆盖它 |
关于查询,可以简单了解一下XPath表达式:
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
代码演示
示例XML文档内容如下:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE note SYSTEM "Note.dtd"[]> <note> <ID id1="111" id2="222"/> <name>张三</name> <jobs> <type>搬砖</type> <time>1h</time> </jobs> <jobs> <type>伐木</type> <time>1h</time> </jobs> <sex> <man>男</man> <woman>女</woman> </sex> </note>
using System; using System.Xml; namespace XML操作 { class Program { static void Main(string[] args) { XMLTest(); XMLTest2(); Console.ReadKey(); } //先封装一个简单的输出方法方便验证结果 /// <summary> /// 一个简单输出方法 /// </summary> static void C(string str,object obj) { Console.WriteLine(" {0}: {1}" ,str, obj); Console.WriteLine(" ------------------------------"); } //定义两个文档地址 static string filePath = @"C:\Users\Administrator\Desktop\Temp\test.xml"; static string filePath2 = @"C:\Users\Administrator\Desktop\Temp\test2.xml"; //定义两个 XML 对象 static XmlDocument xml; static XmlDocument xml2; //定义两个常用的节点 static XmlNode IDnote; static XmlNode jobsnote; /// <summary> /// XML属性测试 /// </summary> static void XMLTest() { //构造函数 xml = new XmlDocument(); //如果 XML 文档中存在注释,读取时会报错 //可以通过 XmlReaderSettings ,XmlReader 组合设置即可 //文档读取完毕后,要关闭 XmlReader XmlReaderSettings settings = new XmlReaderSettings(); //设置忽略注释 settings.IgnoreComments = true; //通过 XmlReader 设置规则 XmlReader reader = XmlReader.Create(filePath, settings); //读取 XmlReader 中缓存的 XML xml.Load(reader); //关闭 XmlReader reader.Close(); //选择第一个按标签匹配到的节点,节点需要从根节点开始一层一层到当前节点标签 IDnote = xml.SelectSingleNode("/note/ID"); jobsnote = xml.SelectSingleNode("/note/jobs"); Console.WriteLine("\n ------------------------------\n"); Console.WriteLine(" 1.获取 当前 节点的所有属性引用对象集合"); //不包含子级的属性 XmlAttributeCollection attributes = IDnote.Attributes; //遍历出来的item必须指定类型(拆箱),否则默认为boject类型 foreach (XmlNode i in attributes) C("Attributes", i.Value); Console.WriteLine(" 通过 item 的方式直接获取单个属性的引用对象"); //需要通过 item[] 的方式定位到具体属性名 C("Attributes[id1]", IDnote.Attributes["id1"].Value); Console.WriteLine(" 2.获取 文档的地址"); string URI = xml.BaseURI; C("BaseURI", URI); Console.WriteLine(" 3.获取 当前 节点本地名称"); string localName = jobsnote.LocalName; C("LocalName", localName); Console.WriteLine(" 4.获取 当前节点 限定名称"); string name = jobsnote.Name; C("Name", name); } } }View Code
运行结果:
Console.WriteLine(" 5.获取 当前和子级 的标签和文本(XmlNode)"); string outerXml = jobsnote.OuterXml; C("OuterXml", outerXml); Console.WriteLine(" 6.获取或设置 当前和子级 的文本"); string innerText = jobsnote.InnerText; C("InnerText", innerText); Console.WriteLine(" 7.获取或设置 子级 节点的标签和文本"); //只能获取子节点,不包含当前节点 string innerXml = jobsnote.InnerXml; C("InnerXml", innerXml); Console.WriteLine(" 8.获取 XML文档类型定义"); XmlNode documentType = xml.DocumentType; C("DocumentType", documentType.OuterXml); Console.WriteLine(" 9.获取 子级 节点集合"); //只能获取子节点,不包含当前节点 XmlNodeList childNodes = jobsnote.ChildNodes; //可以通过 XmlNodeList.Item(index) 方法索引获得单个节点 string childNodesItem = childNodes.Item(0).LocalName; //也可以遍历列表 foreach (XmlNode i in childNodes) C(" ChildNodes", i.LocalName); Console.WriteLine(" 10.获取 文档的 根 节点"); //根节点是唯一的 XmlNode documentElement = xml.DocumentElement; C("DocumentElement", documentElement.LocalName); Console.WriteLine(" 11.获取 当前文档的 XmlImplementation 对象"); XmlImplementation xmlImplementation = xml.Implementation; Console.WriteLine("\n ------------------------------\n");View Code
运行结果:
Console.WriteLine(" 12.判断 是否只读"); bool isRead = xml.IsReadOnly; C("IIsReadOnly" , isRead); Console.WriteLine(" 13.获取或设置 元素内容是否保留空白区域"); //经过试验,设置为 true 会将每一行开头和结尾的空白以及换行符给去掉 //相反,false 会保留开头和结尾的处的空白和换行符 //??为何呢?? bool preserveWhitespace = xml.PreserveWhitespace; C("PreserveWhitespace", preserveWhitespace); Console.WriteLine(" 14.获取 当前节点 的类型"); XmlNodeType nodeType = jobsnote.NodeType; XmlNodeType nodeType2 = xml.NodeType; C("1.NodeType", nodeType); C("2.NodeType", nodeType2); Console.WriteLine(" 15.获取 当前节点 所属的 XmlDocument 对象"); XmlDocument ownerDocument = jobsnote.OwnerDocument; C("OwnerDocument" , ownerDocument); Console.WriteLine(" 16.获取 父 节点"); //针对可以拥有父级的节点 XmlNode parentNode = jobsnote.ParentNode; C("ParentNode" , parentNode.LocalName); Console.WriteLine(" 17.获取 下一个节点(XmlNode)"); //注意: //1.下一个节点必须是当前节点的同级节点,否则会返回null //2.如果存在多个标志相同的节点,则默认为第一个 //下面代码会报错,因为不存在和根节点同级的节点,版本声明不属于节点 //XmlNode next = xml.DocumentElement.NextSibling; XmlNode nextSibling = jobsnote.NextSibling; C("NextSibling" , nextSibling.LocalName); Console.WriteLine(" 18.获取 上一个节点(XmlNode)"); //注意:内容同上 XmlNode previousSibling = jobsnote.PreviousSibling; C("PreviousSibling" , previousSibling.LocalName);
运行结果:
Console.WriteLine(" 19.获取 当前 节点之前的文本节点(XmlNode)"); //??不知为何返回null?? //请求高人指点 XmlNode previousText = jobsnote.PreviousText; //C("PreviousText" , previousText.InnerXml); Console.WriteLine("\n ------------------------------\n"); Console.WriteLine(" 20.获取 当前 节点的 最后子级(XmlNode)"); XmlNode lastChild = jobsnote.LastChild; C("LastChild" , lastChild.LocalName); Console.WriteLine(" 21.获取 当前 节点的 首位子级(XmlNode)"); XmlNode firstChild = jobsnote.FirstChild; C("FirstChild" , firstChild.LocalName); Console.WriteLine(" 22.获取 具有指定 Name 的第一个子元素 (XmlNode)"); XmlNode item = documentElement["jobs"]; C("item" , item.LocalName); Console.WriteLine(" 23.获取或设置节点的值(XmlNode)"); //注意: //这里想要获得Value的值,必须详细定位到哪个属性,需要调用Attributes["属性名"] string value = IDnote.Attributes["id2"].Value; C("Value", value); Console.WriteLine(" 24.获取该节点的命名空间 URI(XmlNode)"); string namespaceURI = xml.NamespaceURI; C("NamespaceURI", namespaceURI); Console.WriteLine(" 25.判断该节点下是否有子节点(XmlNode)"); bool hasChildNodes = xml.HasChildNodes; C("HasChildNodes", hasChildNodes);
运行结果:
static void XMLTest2() { //构造函数 xml = new XmlDocument(); //如果 XML 文档中存在注释,读取时会报错 //可以通过 XmlReaderSettings ,XmlReader 组合设置即可 //文档读取完毕后,要关闭 XmlReader XmlReaderSettings settings = new XmlReaderSettings(); //设置忽略注释 settings.IgnoreComments = true; //通过 XmlReader 设置规则 XmlReader reader = XmlReader.Create(filePath, settings); //读取 XmlReader 中缓存的 XML xml.Load(reader); //关闭 XmlReader reader.Close(); //获取根节点 XmlElement rootElement = xml.DocumentElement; Console.WriteLine(" \n查询类方法:\n"); Console.WriteLine(" 1.获取与指定节点标签名称匹配的所有节点的列表"); XmlNodeList getElementsByTagName = xml.GetElementsByTagName("jobs"); foreach (XmlNode i in getElementsByTagName) { Console.Write("\n getElementsByTagName(jobs): {0}\n", i.LocalName); } Console.WriteLine("\n ------------------------------\n"); Console.WriteLine(" 特殊值“*”匹配所有标签名称"); XmlNodeList getElementsByTagName2 = xml.GetElementsByTagName("*"); foreach (XmlNode i in getElementsByTagName2) { Console.Write("\n getElementsByTagName(*): {0}\n", i.LocalName); } Console.WriteLine("\n ------------------------------\n");
运行结果:
Console.WriteLine(" 2.获取第一个按标签匹配到的节点集合"); //节点标签需要从根节点开始一层一层到当前节点标签 XmlNodeList selectNodes = xml.SelectNodes("/note/jobs"); foreach (XmlNode item in selectNodes) { C("SelectNodes", item.LocalName); } Console.WriteLine(" 3.选择第一个按标签匹配到的节点"); //1.节点标签需要从根节点开始一层一层到当前节点标签 XmlNode selectSingleNode = xml.SelectSingleNode("/note/jobs"); C("SelectSingleNode", selectSingleNode.LocalName); Console.WriteLine(" 4.获取具有指定 ID 的 XmlElement 节点"); //1.这里的指定 ID,需要再 DTD 中定义属于 ID 类型的属性 //2.比较麻烦,一般用不上,这里不做演示 XmlElement getElementById = xml.GetElementById("");
运行结果:
//新增和添加类方法 //创建一个新节点 XmlElement createElement = xml.CreateElement("1.createElement"); //为指定节点新建属性并赋值 createElement.SetAttribute("2.setAttribute", "100"); //不推荐以下为节点添加属性的办法,性能内存不佳,而且麻烦 //1.创建指定名称的属性 XmlAttribute createAttribute = xml.CreateAttribute("3.createAttribute"); //2.设置属性值 createAttribute.Value = "200"; //3.为指定节点添加指定的属性 createElement.SetAttributeNode(createAttribute); //为指定节点添加子节点 //如果存在相同节点,不会覆盖原节点 rootElement.AppendChild(createElement); //创建一个节点 //1.需要申明 XmlNodeType 和 Name,URI 可以不用申明 //2.XmlNodeType.Element 类型的节点,就等于是创建一个 XmlElement //3.XmlNodeType 是一个枚举类,18种类型节点,所以这是创建节点和创建元素的最大区别 XmlNode createNode = xml.CreateNode(XmlNodeType.Element, "4.CreateNode", ""); rootElement.AppendChild(createNode); //在当前节点的指定子节点 *前* 插入新节点(XmlNode) //1.refChild必须为当前节点的子节点 //2.newChild可以是xmlNode或者xmlElement XmlElement insertBefore = xml.CreateElement("5.InsertBefore"); XmlNode refChild = xml.SelectSingleNode("/note/jobs"); rootElement.InsertBefore(insertBefore, refChild); //在当前节点的指定子节点 *后* 插入新节点(XmlNode) //1.refChild必须为当前节点的子节点 //2.newChild可以是xmlNode或者xmlElement XmlElement insertAfter = xml.CreateElement("6.InsertAfter"); rootElement.InsertAfter(insertAfter, refChild); //将节点从另一个文档导入到当前文档 //1.importNode节点需要添加进当前的XML节点中,否则不会被添加进去 //2.不同文档之间无法直接添加对方节点,会报错,需要通过导入节点来添加 xml2 = new XmlDocument(); xml2.Load(filePath2); XmlNode xml2node = xml2.SelectSingleNode("/xml2/ImportNode"); //rootElement.AppendChild(xml2node); //此处会报错,提示不同文档 XmlNode importNode = xml.ImportNode(xml2node, true); rootElement.AppendChild(importNode);
运行结果:
//删改类方法 //将指定的节点添加到该节点的子节点列表的开头(XmlNode) //1.newChild可以是xmlNode或者xmlElement refChild.PrependChild(createNode); //用新子节点替换旧子节点(XmlNode) //1.必须是当前节点的子节点 XmlElement replaceChild = xml.CreateElement("ReplaceChild"); rootElement.ReplaceChild(replaceChild, createElement); //移除当前节点的子节点(XmlNode) //1.被移除的节点必须为当前节点的直接子级,不能是子级的子级 XmlNode removeChild = xml.SelectSingleNode("/note/jobs"); rootElement.RemoveChild(removeChild); //移除当前节点的所有子节点和属性(XmlNode) removeChild.RemoveAll(); //保存XML文件,如果存在指定文件,则此方法会覆盖它 xml.Save(filePath); }
运行结果: