访问XML的方法
昨天用wpf的时候要访问xml,弄了很久,所以记录一下。
C#3.0提供了轻型的XmlReader、XmlWriter类和完全文档对象模式(DOM)的XmlDocument类。这也是我昨天郁闷半天的原因。以前用过XmlTextReader,也没搞太懂,就是找到了方法,贴上代码。看懂下了事。
在这个博客可以找到原理:http://www.cnblogs.com/xdesigner/archive/2008/05/15/1198398.html
整个博客可以看到xml操作方法:http://www.cnblogs.com/surfsky/archive/2007/03/13/673625.html
先上原理:
XmlReader是流式处理模型,所谓流式处理是指将XML文档当做一个数据流来进行处理,逐个处理XML文档中的数据。这种模型下,读取快,内存占用少,性能也就好。它的缺点也明显(昨天我就是在这上面闷了很久):1.只能读取不能修改;2.不能使用XPath技术;3.接口简单,处理方法比较少。
System.Xml空间
以下类适合快速流式读写XML文件(注:DOM适合随机读写)
XmlReader, XmlWriter,
XmlTextReader, XmlTextWriter
XmlValidatingReader, XmlValidatingWriter 添加了DTD和模式验证,因此提供了数据的有效性验证
XmlNodeReader, XmlNodeWriter 把XmlNode作为其源
XmlDocument是DOM处理模型,使用文档对象模型的思想解析整个XML文档,在内存中生成一个对象树来表述XML文档。可以使用XmlElement对象来影射XML文档中的一个元素,使用XmlAttribute对象来影射到XML文档中的一个属性。这样通过编程可以方便的操作XML,比如递归遍历XML文档的一部分或全部,可以像树状结构插入,修改或删除XML元素,可以设置XML元素的属性。
在DOM模式下,我们可以使用XPath技术在XML文档树状结构中进行快速检索和定位,这为处理XML文档带来比较大的方便。
经常用到的几个DOM的类型;
XmlNode 是DOM结构中的所有类型的基础类型,它定义了所有XML节点的通用属性和方法,是XMLDOM的基础。它具有一个ChildNodes属性,表示它所包含的子XML节点。
XmlAttribute 表示XML属性,它只保存在XmlElement的Attributes 列表中。
XmlDocument表示XML文档本身,是XMLDOM模型中的顶级对象,它用于对XML文档进行整体的控制,并且是其它程序访问XML文档对象树的唯一入口。
XmlLinkedNode在XmlNode的基础上实现了访问前后同级节点的方法。
XmlElement元素表示XML元素。是XMLDOM中使用最多的对象类型。它具有Attributes属性可以处理它所拥有的属性,可以使用ChildNodes属性获得它所有的子节点。并提供了一些添加和删除子节点的方法。
下面看一张XDocument的(有个问题想问,XDocument和XElement的关系是?):
再上建议:
使用XmlDocument:1.传统的DOM方法适用。2.所需的整个文档皆在内存中。3.必须在内存中向前或向后遍历以及更新。
使用XmlReader/XmlWriter:1.必须适用流方法。2.必须要求进行最快的处理。3.要处理较大的文档并且无法一次性加载全部文档。
使用XElement/XDocument:1.用代码构建xml声明。2.LINQ的查询能力有助于流方法。3.需要一种针对大多数开发人员的更易读的XML编程语法。
4.要求使用查语义在内存中遍历。
博文后面的代码比较多,我只说我用到的。
XmlReader有个很经典的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | XmlReader reader = xDoc.CreateRedaer(); reader.Settings.CheckCharacters = true ; int level = 0; while (reader.Reader()) { switch (reader.NodeType) { case XmlNodeType: Display(level, "CDATA:{0}" ,reader.Value); break ; case XmlNodeType.Comment: Display(level, "Comment:{0}" ,reader.Value); break ; case XmlNodeType.DocumentType: Display(level, "DOCTYPE:{0}= {1}" ,reader.Name,reader.Value); break ; case XmlNodeType.Element: Display(level, "Element:{0}" ,reader.Name); level++; while (reader.MoveToNextAttribute()) { Display(level, "ATTRIBUTE: {0}='{1}'" ,reader.Name,reader.Value); } break ; case XmlNodeType.EndElement; level--; break ; case XmlNodeType.EntityReference: Display(level, "ENTITY:{0}" ,reader.Name); break ; case XmlNodeType.ProcessingInstruction: Display(level, "INSTRUCTION: {0}={1}" ,reader.Value); break ; case XmlNodeType.Text; Display(level, "TEXT:{0}" ,reader.Value); break ; case XmlNodeType.XmlDeclaration: Display(level, "DECLARATION: {0}={1}" ,reader.Value); break ; } } static void Display( int indentLevel, string format, params object [] args) { for ( int i=0;i<indentLevel;i++) Console.Write( " " ); Console.WriteLine(format,args) } |
1 | XDocument的(网上有更详细的,这个是我为了解决自己的问题写的,主要是遍历某个节点下的全部子节点): |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <pre class = "brush:csharp" > XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(filePath); XmlNodeList topM = xmldoc.DocumentElement.ChildNodes; foreach (XmlElement element in topM) { if (element.Name== "Vocabulary" ) { XmlNodeList nodelist = element.ChildNodes; Model.Vocabulary vocabulary = new Model.Vocabulary(); foreach (XmlElement el in nodelist) { if (el.Name == "Word" ) vocabulary.Word = el.InnerText; else if (el.Name == "Explain" ) vocabulary.Explain = el.InnerText; else if (el.Name == "IsLastSelected" ) vocabulary.IsLastSelected = el.InnerText== "0" ? false : true ; } vocabularies.Add(vocabulary); }</pre> OK,先到这里,以后碰到问题再补上增删的。 |
继续:
关于linq to xml的,关于Descentdants函数。具体可以参看:http://www.programbbs.com/doc/4564.htm
Desentdants英文意思是后代,晚辈。也就是这个函数是用于获得某个Element下的指定子Element。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | foreach (XElement elem in doc.Elements(\"Customers\").Descendants(\"Customer\")) { Console.WriteLine( string .Format( \"Customer ID : {0}, Name : {1}, Address : {2}\", elem.Attribute(\"ID\").Value, elem.Attribute(\"Name\").Value, elem.Attribute(\"Address\").Value) ); } <pre class = "brush:csharp" ><?xml version=\"1.0\" encoding=\"utf-8\"?> <Customers> <Customer ID=\"A0001\" Name=\"Tom\" Address=\"Taipen\" /> <Customer ID=\"A0002\" Name=\"Mary\" Address=\"LD\" /> <Customer ID=\"A0003\" Name=\"Jeff\" Address=\"YW\" /> </Customers> </pre> |
1 | 特别的,当xml中包含了Namespace时,传入的Descendants的指定Element名称必包含Namespace, |
Descendants函数接收的是一个XName的元素,它隐含了\算子,显然刚只得到了Element的LocalName。可以这样做:
var cstr = (from s1 in doc.Descendants() where s1.Name.LocalName==\"Connection\" select s1).First();
var cstr = (from s1 in doc.Descendants(doc.Root.Name.Namespace+\"Connection\" select s1).First();
继续:Linq to xml 的Elements()函数
(发现很多方法都可以轻松搞定我那个问题)
参考网站:http://www.cnblogs.com/ucetgg/archive/2009/04/23/1441739.html
var name = from nm in xelement.Elements("Employee") where (string)nm.Element("Sex")=="Female" select nm;
继续:处理非法字符
XElement和XmlWriter方法:
XElement可以直接处理转义也可以用XCData对象处理。
1 2 3 4 5 | string invalidChars = @"<>\&" ; XElement element = new XElement( "Root" , new XElement( "InvalidChars1" , new XCData(invalidChars)), new XElement( "InvalidChars2" , invalidChars)); |
InvalidChars1将保存为<![CDATA[<>\&"]>,InvalidChars2将转义存储。
附上转义表:
< <
< >
" "
' '
& &
XmlWriter处理可以使用WriteCData方法将非法字符封装在CDATA片段中,另一种使用WriteElementString方法。
1 2 3 4 5 6 7 8 9 10 11 12 | string invalidChars = @"<>\&" ; XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true ; using (XmlWriter writer = XmlWriter.Create(Console.Out,settings)) { writer.WriteStartElement( "root" ); writer.WriteStartElement( "InvalidChars1" ); writer.WriteCDate(invalidChars); writer.WriteEndElement(); writer.WriteElementString( "InvalidChars2" ,invalidChars); writer.WriteEndElement(); } |
XmlDocumenthe和XmlElement处理方法:
放置于CDATA片段中,并添加至XmlElement的InnerXML属性中。
1 2 3 | string invalidChars = @"<>\&" ; XmlElement invalidElement1 = xmlDoc.CreateElement( "InvalidChars1" ); invalidElement1.AppendChild(xmlDoc.CreateCDataSection(invalidChars); |
通过赋值给InnerText属性令XmlElement类为封装数据。
1 2 3 | string invalidChars = @"<>\&" ; XmlElement invalidElement2 = xmlDoc.CreateElement( "InvalidChars2" ); invalidElement2.InnerText = invalidChars; |
作 者:doku
出 处:http://www.cnblogs.com/kulong995/
关于作者:喜欢编程,喜欢美食,专注于.NET项目开发。
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?