• 访问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有个很经典的:

    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)
    }
    XDocument的(网上有更详细的,这个是我为了解决自己的问题写的,主要是遍历某个节点下的全部子节点):
     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);
                    }
    OK,先到这里,以后碰到问题再补上增删的。

    继续:

    关于linq to xml的,关于Descentdants函数。具体可以参看:http://www.programbbs.com/doc/4564.htm

    Desentdants英文意思是后代,晚辈。也就是这个函数是用于获得某个Element下的指定子Element。

    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)
    );
    } 
    
    <?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> 
    
    特别的,当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对象处理。

    string invalidChars =@"<>\&";
    XElement element = new XElement("Root",
                            new XElement("InvalidChars1",
                                new XCData(invalidChars)),
                            new XElement("InvalidChars2", invalidChars));
    

    InvalidChars1将保存为<![CDATA[<>\&"]>,InvalidChars2将转义存储。

    附上转义表:

      <   &lt;

      <   &gt;

      "    &quot;

      '    &apos;

      &   &amp;

      XmlWriter处理可以使用WriteCData方法将非法字符封装在CDATA片段中,另一种使用WriteElementString方法。   

    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属性中。

    string invalidChars =@"<>\&";
    XmlElement invalidElement1 = xmlDoc.CreateElement("InvalidChars1");
    invalidElement1.AppendChild(xmlDoc.CreateCDataSection(invalidChars);
    

    通过赋值给InnerText属性令XmlElement类为封装数据。

    string invalidChars =@"<>\&";
    XmlElement invalidElement2 = xmlDoc.CreateElement("InvalidChars2");
    invalidElement2.InnerText = invalidChars;
    
  • 相关阅读:
    ES6之6种遍历对象属性的方法
    css自定义滚动条样式,自定义文字选择样式,设置文字不被选择
    js img转换base64
    移动端rem造成的很多问题
    移动端边框1像素的问题
    【小练习1】如何制作“表单”
    2015-09-24 第六节课 (CSS补充和html 标签讲解、浏览器兼容性)
    2015-09-22 第四节课 CSS块级元素 行内元素 浮动 盒子模型 绝对定位、相当定位和固定定位
    2015-09-21 第三节课 css属性 border(边框)、background(背景)
    html你可能还不知道的一些知识点
  • 原文地址:https://www.cnblogs.com/kulong995/p/1634834.html
Copyright © 2020-2023  润新知