• (转)用C#读xml文档(流模型)


    System.Xml命名空间下,XmlReader和XmlWriter类是用于读写xml文档的抽象类,它们使用流模型
    使用XmlReader类读XML文档,它提供对XML数据的快速、非缓存、只向前、只读的访问。

    1.XmlReader有3个子类:
    1)XmlTextReader:最快的 XmlReader 实现。它检查 XML 格式是否正确,但不支持验证。该读取器不能展开常规实体(dtd中的概念),不支持默认属性。
    XmlReader 在发生 XML 分析错误时引发 XmlException 异常。

    2)XmlValidatingReader:  可以使用 DTD 或 Schema 验证数据的 XmlReader 的实现。该读取器还可以展开常规实体并支持默认属性。

    3)XmlNodeReader:  从 XmlNode 读取 XML 数据的 XmlReader 的实现

    注:读xml文档,一般使用XmlTextReader类


    ===================================================

    2.XmlTextReader 类
    1)XmlTextReader把xml文档看作是一个序列化的节点集合,即一个节点流

    2)xml文档中的 元素的开始标记(节点类型为Element)、元素的属性(Attribute)、元素的文本内容(Text)、标记之间的空白/换行(SignificantWhitespace或Whitespace)、元素的结束标记(EndElement)等 都被视为节点。

    3)Read()方法是XmlTextReader类的主要实例方法,它执行一次就读节点流中的一个节点
    但Read()方法不会自动读取属性节点(Attribute类型的节点),如果当前节点是Element节点后,下一次被读的节点就是Text(如果当前元素有文本内容)或Whitespace节点(如果当前节点标记预下一个标记之间有空白/换行的话,如果没有空白换行,就没有Whitespace节点)
    即Read()方法只会读Element、Text、Whitespace、EndElement等类型的节点

    3)如果当前当前节点是Element节点,如果想读元素的属性节点的话,可以使用以下方法:
    MoveToAttribute 、MoveToFirstAttribute 、MoveToNextAttribute 等
    如果当前节点是Attribute节点,要回到属性所属元素的节点上的话,可使用MoveToElement 方法

    4)随着当前节点的节点类型的不同,XmlReader类对象的某些属性也会无效
    例如XmlTextReader对象的AttributeCount属性,对于不是Element、DocumentType 和 XmlDeclaration 类型的节点来说,该属性无意义

    5)关于SignificantWhitespace/Whitespace节点的处理:
    XmlTextReader对象的WhitespaceHandling属性可以指定如何处理空白


    3.节点的类型
    =====================================================================
    节点类型 说明   示例 XML
    =====================================================================
    Attribute  属性    id='123'
    ---------------------------------------------------------------------
    CDATA  CDATA节   <![CDATA[my escaped text]]>
    ---------------------------------------------------------------------
    Comment  注释   <!-- my comment -->
    ---------------------------------------------------------------------
    Document  作为文档树的根的文档对象提供对整个 XML 文档的访问
    ---------------------------------------------------------------------
    DocumentFragment  文档片段  
    ---------------------------------------------------------------------
    DocumentType  文档类型声明  <!DOCTYPE ...>
    ---------------------------------------------------------------------
    Element  元素   <item>
    ---------------------------------------------------------------------
    EndElement  结束元素标记  </item>
    ---------------------------------------------------------------------
    EndEntity  由于调用 ResolveEntity 而使 XmlReader 到达实体替换的末尾时返回
    ---------------------------------------------------------------------
    Entity   实体声明  <!ENTITY ...>
    ---------------------------------------------------------------------
    EntityReference 对实体的引用  &num;
    ---------------------------------------------------------------------
    None   如果未调用 Read 方法,则由 XmlReader 返回
    ---------------------------------------------------------------------
    Notation  文档类型声明中的表示法 <!NOTATION ...>
    ---------------------------------------------------------------------
    ProcessingInstruction  处理指令 <?pi test?>
    ---------------------------------------------------------------------
    SignificantWhitespace  混合内容模型中标记间的空白或 xml:space="preserve"范围内的空白
    ---------------------------------------------------------------------
    Text   节点的文本内容。可以以Attribute、DocumentFragment、Element、  EntityReference 节点的子节点的形式出现
    ---------------------------------------------------------------------
    Whitespace  标记间的空白
    ---------------------------------------------------------------------
    XmlDeclaration  XML 声明  <?xml version='1.0'?>
    =====================================================================


    4.XmlTextReader应用示例:读一个xml文档-tmp.xml

    文档tmp.xml的内容:
    -----------------------------------------------------------------------
    <?xml version="1.0" encoding="GB2312"?>
    <bookstore>
     <book name="文化苦旅">
      <author nation="中国" 年代="当代">余秋雨&amp;</author>
      <price>32</price>
      <press>华夏出版社</press>
     </book> 
    </bookstore>
      //文档有一个空白尾行
    ------------------------------------------------------------------------

    C#代码:
    ------------------------------------------------------------------------
    XmlTextReader xr4 = new XmlTextReader("temp.xml");  //装载整个文档到内存
    xr4.WhitespaceHandling = WhitespaceHandling.All;    //设置如何处理空白节点
      while(xr4.Read())
      {   
     Console.Write((" Type: " + xr4.NodeType).PadRight(20));   //打印节点类型
     Console.Write((" Name: " +  xr4.Name).PadRight(18));   //打印节点名称
     Console.WriteLine(" Value: " + xr4.Value);    //打印节点的值

     if (xr4.HasAttributes)   //如果当前节点有属性的话(非元素节点的此属性为null)
     {
         int tmp = xr4.AttributeCount;
       for (int i = 0; i < tmp; i++ ) //循环打印元素节点的属性
       {
             xr4.MoveToAttribute(i);  //移动到第n个属性上
      Console.WriteLine((" Type: " + xr4.NodeType).PadRight(20)
        + (" Name: " + xr4.Name).PadRight(16)
        + (" value: " + xr4.Value.PadRight(10))
        + (" AttributeCount: " + xr4.AttributeCount) );
      xr4.MoveToElement();  //回到元素节点
       }
     }
      }
    xr4.Close();  //关闭流对象
    Console.ReadLine();
    ------------------------------------------------------------------------

    输出:
    ----------------------------------------------------------------------------------
    Type: XmlDeclaration Name: xml         Value: version="1.0" encoding="GB2312"
    Type: Attribute     Name: version   value: 1.0        AttributeCount: 2
    Type: Attribute     Name: encoding  value: GB2312     AttributeCount: 2
    Type: Whitespace    Name:             Value:

    Type: Element       Name: bookstore   Value: //该节点没有属性,AttributeCount为null
    Type: Whitespace    Name:             Value: //该节点没有属性,AttributeCount为null

    Type: Element       Name: book        Value:
    Type: Attribute     Name: name      value: 文化苦旅       AttributeCount: 1
    Type: Whitespace    Name:             Value:

    Type: Element       Name: author      Value:
    Type: Attribute     Name: nation    value: 中国         AttributeCount: 2
    Type: Attribute     Name: 年代        value: 当代         AttributeCount: 2
    Type: Text          Name:             Value: 余秋雨&
    Type: EndElement    Name: author      Value: 
    Type: Whitespace    Name:             Value:

    Type: Element       Name: price       Value:
    Type: Text          Name:             Value: 32
    Type: EndElement    Name: price       Value:
    Type: Whitespace    Name:             Value:

    Type: Element       Name: press       Value:
    Type: Text          Name:             Value: 华夏出版社
    Type: EndElement    Name: press       Value:
    Type: Whitespace    Name:             Value:

    Type: EndElement    Name: book        Value:  //即book元素的结束标记</book> 
    Type: Whitespace    Name:             Value:

    Type: EndElement    Name: bookstore   Value:  //即结束标记</bookstore>
    Type: Whitespace    Name:             Value:  //文档的空白尾行
    ----------------------------------------------------------------------------------


    5.XmlTextReader类的常用方法
    1)在元素节点和属性节点之间移动
    如果当前节点是元素节点,并且该元素拥有属性的话:
    ·使用MoveToAttribute()方法可以移动到属性节点,该方法要求指定属性名或属性的位置
    ·使用MoveToFirstAttribute()方法可以移动到第一个属性上,并返回true
    ·如果当前节点是元素节点,使用MoveToNextAttribute()方法等效于MoveToFirstAttribute方法。
      如果已经移动到了属性节点上,并且存在下一个属性,调用该方法就会移动到下一个属性节点上
      否则,读取器位置不变并返回false

    如果读取器定位在属性上,使用MoveToElement()方法,则当前节点移动到属性所属的元素节点上。

    2)跳过内容-两种方法
    ·一种方法是调用使用 MoveToContent 方法直接移动到内容节点
    MoveToContent()方法检查当前节点以查看它是否是内容节点。
    内容节点被定义为任意 Text、CDATA、Element、EndElement、EntityReference 或 EndEntity 节点。如果当前节点不是前述内容节点的类型之一,则将跳过该节点并跳到下一个内容节点或文件结尾。
    它一直跳,直到找到下一个内容节点或到文件的结尾才停止。
    如果当前节点是一个属性节点,则此方法将读取器移回拥有该属性的元素。

    示例:
    -----------------------------------------------------------------------------
    if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "price")
     {
        _price = reader.ReadString();
     }
    -----------------------------------------------------------------------------

    ·另一种方法是直接调用 Skip 方法,该方法从当前节点跳过所有子节点到下一个同级节点
    如果当前节点类型为XmlNodeType.Element,则调用skip方法将跳到同级的下一个节点上。
    如果当前节点是属性节点,则调用skip方法将跳到属性所属元素节点的下一个同级节点上。


    3)读方法
    ·Read()方法:如果成功读取了下一个节点,则为true;如果没有其他节点可读取,则为false
      第一次创建和初始化读取器时,没有可用的信息。必须调用 Read() 读取第一个节点。

    ·ReadStartElement()方法:
      检查当前节点是否为元素(类型为Element的节点)并将读取器推进到下一个节点

    ·ReadEndElement()方法:
      检查当前节点是否为结束标记(类型为EndElement的节点)并将读取器推进到下一个节点

    ·ReadAttributeValue()方法:
      将当前属性节点的属性值分解为一个或多个 Text、EntityReference 或 EndEntity 节点。
      如果有可返回的节点,则返回true。如果进行初始调用时读取器不是定位在属性节点上,或者如果已读取了所有属性值,则返回false
      如果是空属性(如 misc=""),则返回true,同时将属性值分解为 String.Empty 的单个节点
      一般,当读取器移动到一个属性节点上后,通过循环调用ReadAttributeValue方法来分解属性的值

    示例:读xml文档 <book genre='novel' misc='sale-item &h; 1987'></book>
    ---------------------------------------------------------------------
    .......
    reader.MoveToAttribute("misc");  //移动到属性misc上
    while (reader.ReadAttributeValue()) //misc属性值包含实体应用,属性值被分解
    {     //分解完属性值后,循环结束
       if (reader.NodeType==XmlNodeType.EntityReference) //遇到实体引用节点
         Console.WriteLine("{0} {1}", reader.NodeType, reader.Name);
       else
         Console.WriteLine("{0} {1}", reader.NodeType, reader.Value);
    }
    --------------------------------------------------------------------


    4)使用字符流进行完整的内容读取
    方法ReadChars、ReadBinHex、ReadBase64用于读取大型的流。ReadChars方法原样读取文本 (US-ASCII),ReadBase64方法解码Base64编码的文本,而ReadBinHex方法则解码binhex编码的数据。
    ReadChars、ReadBinHex和ReadBase64方法只能用在元素上。在其他节点类型上使用这些方法不起作用
    这三个方法都返回元素的开始标记和结束标记之间的所有内容,包括所有标记,就像在读出流一样。

    ·ReadChars方法: public int ReadChars(char[] buffer,int index,int count);
      将元素的内容读入字符缓冲区。通过连续调用此方法,可以读取当前元素的非常大的嵌入文本流
      此方法设计只用于元素节点。其他节点类型导致ReadChars返回0
      此方法返回元素的实际字符内容,返回元素开始标记和结束标记之间的所有内容,包括标记
      ReadChars方法忽略格式不正确的XML标记
      当ReadChars方法已到达字符流的结尾时,它返回值0并且将读取器定位在结束标记之后

    ·ReadBase64方法: public int ReadBase64(byte[] array,int offset,int len);
      和ReadChars方法一样,可以连续调用此方法以读取大的嵌入文本流。
      它对Base64内容进行解码,并将解码的二进制字节(例如内联Base64编码的GIF图像)返回到缓冲区中

    ·ReadBinHex方法: public int ReadBinHex(byte[] array,int offset,int len);
      与 ReadChars 一样,可以连续调用此方法以读取大的嵌入文本流。
      它对BinHex内容进行解码并将解码的二进制字节(例如内联BinHex编码的GIF图像)返回到缓冲区中
     

    5)读取字符内容
    ·ReadElementString方法:读取简单文本元素的方法
      调用ReadElementString方法时,读取器将移动到下一个节点并读取其简单文本内容,如果该节点不是简单文本元素,则会报错。读取完之后,读取器将再向下移动一个节点

    ·ReadString方法:元素或文本节点的内容当做字符串读取
      如果读取器定位在元素或文本节点以外的位置,或者当前上下文中没有其他文本内容,则返回空字符串

    ·ReadInnerXml方法:将节点的所有内容(包括子元素、文本内容等)当做字符串读取
      如果当前读取器位于开始标记,则该方法返回开始标记与对应的结束标记之间所有的内容
      如果当前读取器位于属性节点,则该方法返回属性的值
      如果当前节点既非元素,也非属性,则返回空字符串

    ·ReadOuterXml方法:此方法类似于 ReadInnerXml,但它还返回开始标记和结束标记
      如果当前读取器位于开始标记,则该方法返回  <开始标记>..内容..<结束标记/>  字符串
      如果当前读取器位于属性节点,则该方法返回   属性名="属性值"  字符串
      如果当前节点既非元素,也非属性,则返回空字符串


    ===================================================

    2.XmlValidatingReader类
    1)XmlValidatingReader类是一个能够提供 DTD、XDR 和 XSD 验证的读取器,能够提供数据验证、解析常规实体的能力和对默认属性的支持,该类也是继承自 XmlReader 类。

    2)XmlValidatingReader类基本上类似于XmlTextReader类,但它增加了ValidationType、Schema和 SchemaType、XmlResolver 等新的属性
    ·ValidationType属性指示验证的类型,其值域为:Auto,DTD,Schema,XDR,None
    ·Schema属性用于需要多个xdr或xsd参与验证的情况,Schema属性实质上是一个XmlSchemaCollection
    ·SchemaType属性返回当前节点的类型:XSD内置类型、用户自定义类型(simpleType/complexType)
    ·XmlResolver属性用于解析外部实体(比如DTD中定义的外部实体)

    3)使用XmlValidatingReader类进行验证的最佳操作:
    ·创建一个XmlTextReader对象tr,将tr对象传给XmlValidatingReader构造函数生成一个对象trv
    ·设置XmlValidatingReader类型对象trv的ValidationType属性(默认值为Auto)
    ·为事件ValidationEventHandler定义和分配事件处理方法ValidationEvent
      trv.ValidationEventHandler += new ValidationEventHandler(this.ValidationEvent)
      因为如果验证出错误时,就会引发trv对象的ValidationEventHandler事件,需要对该事件进行处理
    ·像使用XmlTextReader类对象那样使用XmlValidatingReader对象trv

    4)仅当在调用Read、ReadInnerXml、ReadOuterXml或Skip方法的过程中,且XmlValidatingReader对象trv的ValidationType属性不是ValidationType.None时,才可能发生ValidationEventHandler验证事件
      如果不提供ValidationEventHandler事件的处理程序,当遇到级别为Warning的验证错误时,仍会继续读取数据不引发异常。当遇到第一个级别为Error的验证错误时,XmlValidatingReader对象trv将会引发异常XmlException,之后trv对象也将无法重新启动。
      当根据架构或DTD进行验证时,如果发生验证错误,也将引发XmlSchemaException异常
      如果某个元素报告验证错误,则不验证该元素其余的内容模型,但是将验证其子级。读取器只报告给定元素的第一个错误
      ValidationEventHandler事件处理程序可以使用ValidationEventArgs类对象e的Severity属性来保证根据架构验证了XML实例文档。Severity属性可以区分验证错误和验证警告,验证错误(Severity 等于 XmlSeverityType.Error)表示致命错误,而验证警告(Severity 等于 XmlSeverityType.Warning)指示没有可用的架构信息。

  • 相关阅读:
    解决全局变量共享---C语言的extern关键字用法
    VIM学习笔记
    测试博客
    docker容器中安装vi
    docker中安装Jenkins
    Jenkins Pipeline+Maven+Gitlab持续集成构建问题集锦
    jenkinsapi操作Jenkins,提示:No valid crumb was included in the request
    python语言的jenkinapi
    Jenkins Pipeline+Maven+Gitlab持续集成构建
    windows中卸载Jenkins
  • 原文地址:https://www.cnblogs.com/lancidie/p/1895323.html
Copyright © 2020-2023  润新知