将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/
本文版权归作者所有,可以转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
更多博客文章,以及作者对于博客引用方面的完整声明以及合作方面的政策,请参考以下站点: 陈希章的博客中心
本文是使用 博客同步和管理系统自动于2009/6/20 9:25:52 从 陈希章@博客园 同步过来的。原文地址: http://www.cnblogs.com/chenxizhang/archive/2009/06/20/1507215.html ,发表于2009/6/20 1:26:00.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值