zoukankan      html  css  js  c++  java
  • XML 搜索和验证(XmlDocument、XPath to XmlDocument、LINQ to XDocument)

           对数情况下,并不需要处理整个 XML 文档,只是从中抓取部分信息,使用的方法依据使用的类。

    • XmlDocument
      • 简单情况:使用 GetElementsByTagName()
      • 复杂情况:使用 XPath 语言。
    • XDocument
      • 简单情况:内建的搜索方法(如 Elements())
      • 复杂情况:LINQ 表达式

    搜索 XmlDocument

           使用 XmlDocument 执行查询最简单的方法是使用 XmlDocument. GetElementsByTagName(),返回一个 XmlNodeList 。

    string xmlFile = Server.MapPath("DvdList.xml");
    XmlDocument doc = new XmlDocument();
    doc.Load(xmlFile);
     
    StringBuilder str = new StringBuilder();
    XmlNodeList nodes = doc.GetElementsByTagName("Title");
    foreach (XmlNode node in nodes)
    {
        str.Append("Found: <b>");
        str.Append(node.ChildNodes[0].Value);
        str.Append("</b><br />");
    }
    Response.Write(str);

           更复杂的 XML 文档几乎总是有命名空间甚至多个命名空间。遇到这样的情况,可以使用 GetElementsByTagName()方法的重载版本:

    XmlNodeList nodes = doc.GetElementsByTagName("Title","http://mycompany/OrderML");

           如果要匹配给定命名空间下的所有标签,也可以使用星号(*)作为元素名称:

    XmlNodeList nodes = doc.GetElementsByTagName("*",http://mycompany/OrderML);

    使用 XPath 搜索 XmlDocument

           GetElementsByTagName()方法功能非常有限。只允许你基于元素的名称搜索,你不能够基于其他条件过滤,比如某个元素的值或者特性的内容。

           XPath 是一个更为强大的标准,使用和路径相似的符号允许你获取感兴趣的文档部分。

    XPath 基本语法:

    /

    从根节点开始创建绝对路径。(/DvdList/DVD 选择根元素<DvdList>下所有子元素<DVD>)

    //

    搜索节点所有嵌套层,递归搜索子节点。(//DVD/Title 搜索DVD元素的所有子元素Title)

    @

    选择节点的某个特性

    *

    选择路径中的任意元素 (/DvdList/DVD/*)

    |

    组合多个路径。(/DvdList/DVD/Title | /DvdList/DVD/Director)

    .

    表示当前节点

    ..

    表示父节点

    []

    定义一个选择条件,它可以测试包含节点或特性的值。

    starts - with

    这个函数根据包含元素以什么样的文本开头获取元素 /…/DVD[starts-with(Title.'P')]

    position

    基于位置获取元素,从1开始计数 /…/DVD[position()=2] 等效于简写的 /…/DVD[2]

    count

    这个函数统计匹配名称的元素个数。count(DVD) 返回 <DVD> 元素的个数

    注解:

           要区分两个相关的术语:

    • 子节点:父节点下一层的节点,只是第一层。
    • 后代节点:父节点下所有的嵌套节点,即所有子节点的子节点的子节点的…
    string xmlFile = Server.MapPath("DvdList.xml");
    XmlDocument doc = new XmlDocument();
    doc.Load(xmlFile);
     
    StringBuilder str = new StringBuilder();
    // 选择 Title 标签,查询条件是 父节点(DVD) 的特性相匹配的
    XmlNodeList nodes = doc.SelectNodes("/DvdList/DVD/Title[../@Category='Science Fiction']");
    foreach (XmlNode node in nodes)
    {
        str.Append("Found: <b>");
        str.Append(node.ChildNodes[0].Value);
        str.Append("</b><br />");
    }
    Response.Write(str);

    使用 LINQ 搜索 XDocument

           你已经知道了 XElement 类的 XElement()和 XElements()方法过滤出特定名称的元素,不过,这些方法只向下深入了一层。

           最简单的解决办法是使用这些方法:

    • ElementAfterSelf()、ElementBeforeSelf():找到兄弟元素
    • Descendants():返回此文档或元素的子代元素集合
    • Ancestors():返回此节点的上级元素的集合。

           下面的示例找到文档里任意层级的所有电影标题:

    string xmlFile = Server.MapPath("DvdList.xml");
    XDocument doc = XDocument.Load(xmlFile);
    foreach (XElement element in doc.Descendants("Title"))
    {
        // do something ...
    }

           把元素集合放到 LINQ 表达式后,就可以使用各种已经熟悉的操作。也就是说,你可以使用排序、过滤、分组和投影区取得希望的数据:

    string xmlFile = Server.MapPath("DvdList.xml");
    XDocument doc = XDocument.Load(xmlFile);
    IEnumerable<XElement> matches = from DVD in doc.Descendants("DVD")
                                    where (int)DVD.Attribute("ID") < 3
                                    select DVD.Element("Title");

           把数据转换为其他格式通常更有用。下面的查询创建一个匿名类型,它组合标题和价格,并按价格降序排序,然后绑定到网格显示:

    string xmlFile = Server.MapPath("DvdList.xml");
    XDocument doc = XDocument.Load(xmlFile);
    var matches = from DVD in doc.Descendants("DVD")
                  orderby (decimal)DVD.Element("Price") descending
                  select new
                  {
                      Moive = (string)DVD.Element("Title"),
                      Price = (decimal)DVD.Element("Price")
                  };
    GridView1.DataSource = matches;
    GridView1.DataBind();
     
    // 一定不要忘记进行类型转换这个步骤
    // 这个步骤用于从完整的 XElement 对象取得值

    image

           LINQ to XML 还包含一组扩展方法,它们针对元素集合工作:

    IEnumerable<string> matches =
        from title in doc.Root.Elements("DVD").Elements("Title")
        select (string)title;

           这里要注意的是,第二次调用的 Elements("Title") 实质上是针对第一次的结果 IEnumerable<T> 调用的,它是一个扩展方法。由 System.Xml.Linq.Extensions 类进行了定义,专为处理 IEnumerable<XElement> ,在某些场合,比如你拥有以不同方式从 XML 文档不同部分构件的 IEnumerable<XElement> 集合时,这些扩展方法就比较有用。

           Extensions 类还定义了另外几个应用到 XElement 集合的扩展方法:Ancestors()、AncestorsAndSelf()、Attributes()、Descendants()、DescendantsAndSelf()。

    验证 XML 内容

           我们已经知道了一系列用于读取和解析 XML 数据的策略。但如果用其中任何一种方法尝试读取一个无效的 XML 内容时,就会得到一个错误。换句话说,所有这些类都要求一个格式良好的 XML 。

    基本架构

           XML 格式通常用一个展示其必需结构和数据类型的 XML 架构来规范它的内容。对于 DVD 列表文档,可以创建这样一个相似的 XML 架构:

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema id="DvdList" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="DvdList">
        <xs:complexType>
          <xs:sequence maxOccurs="unbounded">
            <xs:element name="DVD" type="DVDType" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
     
      <xs:complexType name="DVDType">
        <xs:sequence>
          <xs:element name="Title" type="xs:string" />
          <xs:element name="Director" type="xs:string" />
          <xs:element name="Price" type="xs:decimal" />
          <xs:element name="Starring" type="StarringType" />
        </xs:sequence>
        <xs:attribute name="ID" type="xs:integer" />
        <xs:attribute name="Category" type="xs:string" />
      </xs:complexType>
     
      <xs:complexType name="StarringType">
        <xs:sequence maxOccurs="unbounded">
          <xs:element name="Star" type="xs:string" />
        </xs:sequence>
      </xs:complexType>  
    </xs:schema>

    验证 XmlDocument

           要用一个架构验证 XML 文档,可以借助 XmlValidatingReader 类。

           执行验证的第一步是引入命名空间 System.Xml.Schema,它包含的类型有 XmlSchema 和 XmlSchemaCollection 等:

    using System.Xml.Schema;

           下面的示例演示如何创建一个使用 DvdList.xsd 文件的带验证的阅读器,以及如何使用它验证 DvdList.xml 中的 XML 是有效的:

    // 创建 XmlReaderSettings,它指定你想使用的架构
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ValidationType = ValidationType.Schema;
    string xsdFile = Server.MapPath("DvdList.xsd");
    settings.Schemas.Add("", xsdFile);
     
    // 创建验证读取器并验证文档
    string xmlFile = Server.MapPath("DvdList.xml");
    FileStream fs = new FileStream(xmlFile, FileMode.Open);
    XmlReader vr = XmlReader.Create(fs, settings);
    while (vr.Read())
    {
        // Process document here.
        // if an error is found,an exception will be thrown.
    }
    vr.Close();

           做一个小小的改动:

    <DVD ID="A" Category="Drama">

           现在再次验证时,XmlSchemaValidationException (来自 System.Xml.Schema 命名空间)异常被抛出,它提示你有无效的数据类型。

           不是捕获错误,而是可以响应 ValidationEventHandler 事件。如果你响应了这个事件,它会提供错误信息但不会抛出异常:

    settings.ValidationEventHandler += ValidationEventHandler;

           对应的事件处理程序:

    void ValidationEventHandler(object sender, ValidationEventArgs e)
    {
        lblInfo.Text = "Erroe: " + e.Message;
    }

    使用 XDocument 进行验证

           虽然 XDocument 没有嵌入验证功能,但 .NET 包含扩展方法。需要引入 System.Xml.Schema ;这个命名空间里也有一个 Extensions 类,它有一个可以在 XElement 和 XDocument 中使用的 Validate()方法:

    {
        string xmlFile = Server.MapPath("DvdList.xml");
        string xsdFile = Server.MapPath("DvdList.xsd");
        
        XDocument doc = XDocument.Load(xmlFile);
        
        XmlSchemaSet schemas = new XmlSchemaSet();
        schemas.Add("", xsdFile);
        
        doc.Validate(schemas,ValidationEventHandler);
    }
     
     
    void ValidationEventHandler(object sender, ValidationEventArgs e)
    {
       // do something ...
    }
  • 相关阅读:
    图书管理系统---基于form组件和modelform改造添加和编辑
    Keepalived和Heartbeat
    SCAN IP 解释
    Configure Active DataGuard and DG BROKER
    Oracle 11gR2
    我在管理工作中積累的九種最重要的領導力 (李開復)
    公募基金公司超融合基础架构与同城灾备建设实践
    Oracle 11g RAC for LINUX rhel 6.X silent install(静默安装)
    11gR2 静默安装RAC 集群和数据库软件
    Setting Up Oracle GoldenGate 12
  • 原文地址:https://www.cnblogs.com/SkySoot/p/2658421.html
Copyright © 2011-2022 走看看