zoukankan      html  css  js  c++  java
  • 将XSD架构文件嵌入资源使用

    上一篇,我讲解到如何使用XSD架构对XML数据文档进行验证。这一篇深入一点来看:那个XSD架构能不能直接嵌入到程序,作为资源存在呢?这样一来,就可以更好的保护这个文件

    准备工作:为了测试,请创建一个ConsoleApplication

    1. 首先,我们的范例数据比较简单。请保存为Order.xml

    <?xml version="1.0" encoding="utf-8" ?>
    <Order>
      <OrderID>10248</OrderID>
      <OrderDate>2009-01-01</OrderDate>
      <Items>
        <OrderItem>
          <ItemNumber>1</ItemNumber>
          <ProductID>2</ProductID>
          <Quantity>12.00</Quantity>
          <UnitPrice>25.6</UnitPrice>
        </OrderItem>
        <OrderItem>
          <ItemNumber>1</ItemNumber>
          <ProductID>2</ProductID>
          <Quantity>12.00</Quantity>
          <UnitPrice>25.6</UnitPrice>
        </OrderItem>
        <OrderItem>
          <ItemNumber>1</ItemNumber>
          <ProductID>2</ProductID>
          <Quantity>12.00</Quantity>
          <UnitPrice>25.6</UnitPrice>
        </OrderItem>
      </Items>
    </Order>

    2. 我们直接通过Visual Studio的菜单:“XML”=》“创建架构”来生成一个XSD文件,默认的名字就是Order.xsd

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="Order">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="OrderID" type="xs:unsignedShort" />
            <xs:element name="OrderDate" type="xs:date" />
            <xs:element name="Items">
              <xs:complexType>
                <xs:sequence>
                  <xs:element maxOccurs="unbounded" name="OrderItem">
                    <xs:complexType>
                      <xs:sequence>
                        <xs:element name="ItemNumber" type="xs:unsignedByte" />
                        <xs:element name="ProductID" type="xs:unsignedByte" />
                        <xs:element name="Quantity" type="xs:decimal" />
                        <xs:element name="UnitPrice" type="xs:decimal" />
                      </xs:sequence>
                    </xs:complexType>
                  </xs:element>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>

    我们对其做一点修改

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="Order">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="OrderID" type="xs:unsignedShort" />
            <xs:element name="OrderDate" type="xs:date" />
            <xs:element name="Items">
              <xs:complexType>
                <xs:sequence>
                  <xs:element maxOccurs="unbounded" name="OrderItem" minOccurs="1">
                    <xs:complexType>
                      <xs:sequence>
                        <xs:element name="ItemNumber" type="xs:unsignedByte" />
                        <xs:element name="ProductID" type="xs:unsignedByte" />
                        <xs:element name="Quantity" type="xs:decimal" />
                        <xs:element name="UnitPrice" type="xs:decimal" />
                      </xs:sequence>
                    </xs:complexType>
                  </xs:element>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    保存该文件到项目目录,因为它默认是在临时目录创建的
    3.将该文件的生成操作设置为“嵌入的资源”

    image 

    4. 生成该项目,我们查看一下该文件在程序集里面是怎么一个表现形式

    我们通过Reflector打开这个exe

    image

    请记住这个名字:ConsoleApplication1.Order.xsd

    如果你实在不想要前面这一段前缀:ConsoleApplication1,则可以手工修改一下ConsoleApplication1.csproj文件,把里面的RootNameSpace清空

    image

    然后,再来看就很简洁了:Order.xsd

    image

    5. 编写代码,使用该嵌入资源文件作为架构,进行验证

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    using System.Reflection;
    using System.Xml;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                string dataFile = "Order.xml";
                string namespaceUrl = string.Empty;
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.ValidationType = ValidationType.Schema;
                settings.Schemas.Add(namespaceUrl,
                    XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("Order.xsd")));
                settings.ValidationEventHandler += new System.Xml.Schema.ValidationEventHandler(settings_ValidationEventHandler);
    
                string errorMessage = "这不是一个合乎规范的数据文件";
                sb = new StringBuilder();
    
                XmlReader reader = XmlReader.Create(dataFile, settings);
                try
                {
                    reader.MoveToContent();
                    while (reader.Read())
                    {
                        if (reader.NodeType == XmlNodeType.Document && reader.NamespaceURI != namespaceUrl)
                        {
                            Console.WriteLine("文档不是合法的");
                            break;
                        }
                    }
                }
                catch (XmlException ex)
                {
                    sb.AppendFormat("{0}\n", ex.Message);
                }
                finally
                {
                    reader.Close();
                }
    
                if (sb.Length == 0)
                    Console.WriteLine("该文档是合法的");
                else
                    Console.WriteLine(sb.ToString());
    
                Console.Read();
    
                
            }
    
            static StringBuilder sb = null;
            static void settings_ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs e)
            {
                sb.AppendFormat("{0}\n", e.Message);
            }
        }
    }
    

    6. 按下F5键进行调试

    image

    同样道理,如果故意将XML文件修改一下,则可能导致验证无法通过

    image

    最后,仍然要提一下,如果验证的时候,需要考虑命名空间的问题,则上述代码会有问题。因为之前我们介绍过,那种情况下需要两个或者更多个架构文件,而且这些文件之间还需要有所联系。解决方案就是:那些架构文件可以嵌入,但验证之前,仍然需要在磁盘的同一个目录下临时创建起来,然后用磁盘文件的方式去验证。就是不能使用内存流的方式来做,因为它不知道怎么关联。

    由此可见,命名空间这个东西实在是麻烦,不是吗?

    本文由作者:陈希章 于 2009/6/20 9:25:46 发布在:http://www.cnblogs.com/chenxizhang/
    本文版权归作者所有,可以转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    更多博客文章,以及作者对于博客引用方面的完整声明以及合作方面的政策,请参考以下站点:陈希章的博客中心
  • 相关阅读:
    深入理解计算机系统 第六章 存储器层次结构 第二遍
    深入理解计算机系统 第六章 存储器层次结构
    深入理解计算机系统 第八章 异常控制流 Part2 第二遍
    深入理解计算机系统 第八章 异常控制流 part2
    深入理解计算机系统 第八章 异常控制流 Part1 第二遍
    深入理解计算机系统 第八章 异常控制流 part1
    深入理解计算机系统 第三章 程序的机器级表示 Part2 第二遍
    深入理解计算机系统 第三章 程序的机器级表示 part2
    深入理解计算机系统 第三章 程序的机器级表示 Part1 第二遍
    深入理解计算机系统 第三章 程序的机器级表示 part1
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1507215.html
Copyright © 2011-2022 走看看