使用spring.net注入后让parse有 使用xsd文件验证XML格式

  临时接到这个任务,按我的习惯查到不少这种实现,感谢网上的大牛,每次都能够给我灵感


http://blog.csdn.net/gdjlc/article/details/11374787

  由于我这边没有 scchema uri所以用了他这里一段精简版

/// <summary>  
       /// 通过xsd验证xml格式是否正确,正确返回空字符串,错误返回提示  
       /// </summary>  
       /// <param name="xmlText">xml文本内容</param>  
       /// <param name="schemaFile">xsd文件</param>  
       /// <returns></returns>  
       public static string XmlValidateByXsd(string xmlText, string schemaFile)  
       {  
           StringBuilder sb = new StringBuilder();  
           XmlReaderSettings settings = new XmlReaderSettings();  
           settings.ValidationType = ValidationType.Schema;  
           settings.Schemas.Add(null, schemaFile);  
           settings.ValidationEventHandler += (x, y) =>  
           {  
               sb.AppendFormat("{0}\n", y.Message);  
           };  
           using (XmlReader reader = XmlReader.Create(new StringReader(xmlText), settings))  
           {  
               try  
               {  
                   while (reader.Read()) ;  
               }  
               catch (XmlException ex)  
               {  
                   sb.AppendFormat("{0}\n", ex.Message);  
               }  
           }  
           return sb.ToString();  
       }  
同时为了实现动态植入,当然需要做接口代理类,但是我们的parse抽象类有两个文件的解析,dataquery和quickquery,那我照葫芦画瓢也需要对不同的泛型占位符有不同的约束 ,首先上接口和抽象类,我把具体的实现已经实现在抽象类里了。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Com.Centaline.Framework.QuickQuery.Config.Entity;
using System.IO;
using System.Xml;

namespace Com.Centaline.Framework.QuickQuery.Config.Interface
{
    public interface ISchemaValidator<TResult,TResource> 
    {
        string XmlValidateByXsd(Stream xmlStream, XmlReader xmlReader);



        string XmlValidateByXsd(ref TResource resource);
    }
}


抽象类去实现这个接口:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Com.Centaline.Framework.Kernel.ObjectExtensions;
using Com.Centaline.Framework.QuickQuery.Config.Entity;
using Com.Centaline.Framework.QuickQuery.Config.Interface;

namespace Com.Centaline.Framework.QuickQuery.Config
{
    public abstract class SchemaValidator<TResult,TResource> : ISchemaValidator<TResult, TResource> 
        where TResource:Resource<TResult>
        where TResult : class, new()
    {
        public virtual string XmlValidateByXsd(Stream xmlStream, XmlReader xmlReader)
        {
            StringBuilder sb = new StringBuilder();
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas.Add(null, xmlReader);
            settings.ValidationEventHandler += (x, y) =>
            {
                sb.AppendFormat("{0}\n", y.Message);
            };
            using (XmlReader reader = XmlReader.Create(xmlStream, settings))
            {
                try
                {
                    while (reader.Read());
                }
                catch (XmlException ex)
                {
                    sb.AppendFormat("{0}\n", ex.Message);
                }
            }
            return sb.ToString();
        }

        public virtual string XmlValidateByXsd(ref TResource resource)
        {
            throw new NotImplementedException();

            //return XmlValidateByXsd(resource.Stream, "d:\\Users\\wanglin36\\centaline-infrastructure\\Com.Centaline.Framework.QuickQuery\\Config\\Schema\\DataQuery.xsd");
        }
    }
}

这里的神奇之处我方法都用了virtual,而且对一些外部的调用类并没有实现,而且将操作的入参和出参都做了约束,这个约束要在后来具体继承给定。然后两个实现类:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Com.Centaline.Framework.QuickQuery.Config;
using Com.Centaline.Framework.QuickQuery.Config.Interface;
using Com.Centaline.Framework.QuickQuery.Config.Entity;

namespace Com.Centaline.Framework.QuickQuery.Config
{
    public class QuickQuerySchemaValidator:SchemaValidator<Entity.QuickQuery, QuickQueryResource>
    {
        public override string XmlValidateByXsd(Stream xmlStream, XmlReader xmlReader)
        {
           return base.XmlValidateByXsd(xmlStream, xmlReader);

        }

        public override string XmlValidateByXsd(ref QuickQueryResource resource)
        {
            using (var sm = Assembly.GetExecutingAssembly().GetManifestResourceStream("Com.Centaline.Framework.QuickQuery.Config.Schema.QuickQuery.xsd"))
            {
                //byte[] bs = new byte[sm.Length];
                //sm.Read(bs, 0, (int)sm.Length);

                
               return XmlValidateByXsd(resource.Stream,  XmlReader.Create(sm));
            }
            //return XmlValidateByXsd(resource.Stream, "d:\\Users\\wanglin36\\centaline-infrastructure\\Com.Centaline.Framework.QuickQuery\\Config\\Schema\\QuickQuery.xsd");
        }

    }
}

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Com.Centaline.Framework.QuickQuery.Config.Entity;

namespace Com.Centaline.Framework.QuickQuery.Config
{
    public class QuerySchemaValidator : SchemaValidator<Entity.Query, QueryResource>
    {
        public override string XmlValidateByXsd(Stream xmlStream, XmlReader xmlReader)
        {
            return base.XmlValidateByXsd(xmlStream, xmlReader);
        }

        public override string XmlValidateByXsd(ref QueryResource resource)
        {
            using (var sm = Assembly.GetExecutingAssembly().GetManifestResourceStream("Com.Centaline.Framework.QuickQuery.Config.Schema.DataQuery.xsd"))
            {  byte[] bs = new byte[sm.Length];
                //sm.Read(bs, 0, (int)sm.Length);
                //sm.Close();
               return XmlValidateByXsd(resource.Stream, XmlReader.Create(sm));
              }
               // return XmlValidateByXsd(resource.Stream, "d:\\Users\\wanglin36\\centaline-infrastructure\\Com.Centaline.Framework.QuickQuery\\Config\\Schema\\DataQuery.xsd");
        }

    }
}
这里最有意思的是我知道xsd架构文件是嵌入在dll的中间插件里,然后用GetExecutingAssembly来读到assemble的stream用xmlreader 来创建,这都归功于网络上的高手:

http://blog.csdn.net/u011190993/article/details/39960865


看了上面的博客,我在结合msdn发觉XmlSchemaSet.add有Xmlreader作为schema文件的输入:

https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ZH-CN&k=k(System.Xml.Schema.XmlSchemaSet.Add);k(SolutionItemsProject);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5);k(DevLang-csharp)&rd=true


最后用spring.net的属性植入来植入这两个实现类,根据接口,竟然都能够找到对应的实现,真是发觉java spring的强大


 <object id="IQueryParser" type="Com.Centaline.Framework.QuickQuery.Config.QueryParser">
    <property name="ConfigReader">
      <object type="Com.Centaline.Framework.QuickQuery.Config.FileQueryConfigReader">
        <property name="PatchBuilder" ref="IFileQueryResourceRelativePatchBuilder"></property>
      </object>
    </property>
    <property name="ConfigParser">
      <!--<object type="Com.Centaline.Framework.QuickQuery.Config.XmlQueryConfigParser"/>-->
      <object type="Com.Centaline.Framework.QuickQuery.Config.XmlReadQueryConfigParser"/>
      
    </property>
    <property name="ConfigParseCacheProvider" ref="IQueryConfigParseCacheProvider">
    </property>
    <property name="ConfigResourceReader">
      <object type="Com.Centaline.Framework.QuickQuery.Config.FileQueryConfigResourceReader">
        <property name="PatchBuilder" ref="IFileQueryResourceRelativePatchBuilder"></property>
      </object>
    </property>
     <property name="SchemaValidator">
      <object type="Com.Centaline.Framework.QuickQuery.Config.QuerySchemaValidator"></object>
    </property>
   
  </object>

  <object id="IQuickQueryConfigParseCacheProvider" type="Com.Centaline.Framework.Kernel.Caching.MemeryCacheProvider"/>

  <object id="IQuickQueryParser" type="Com.Centaline.Framework.QuickQuery.Config.QuickQueryParser">
    <property name="QueryParser" ref="IQueryParser"></property>
    <property name="ConfigReader">
      <object type="Com.Centaline.Framework.QuickQuery.Config.FileQuickQueryConfigReader">
        <property name="PatchBuilder" ref="IFileQueryResourceRelativePatchBuilder"></property>
      </object>
    </property>
    <property name="ConfigParser">
      <!--<object type="Com.Centaline.Framework.QuickQuery.Config.XmlQuickQueryConfigParser"/>-->
      <object type="Com.Centaline.Framework.QuickQuery.Config.XmlReadQuickQueryConfigParser"/>
    </property>
    <property name="ConfigParseCacheProvider" ref="IQuickQueryConfigParseCacheProvider">
    </property>
    <property name="ConfigResourceReader">
      <object type="Com.Centaline.Framework.QuickQuery.Config.FileQuickQueryConfigResourceReader">
        <property name="PatchBuilder" ref="IFileQueryResourceRelativePatchBuilder"></property>
      </object>
    </property>
   <property name="SchemaValidator">
      <object type="Com.Centaline.Framework.QuickQuery.Config.QuickQuerySchemaValidator"></object>
    </property>
  </object>

  红色就是属性注入的地方,最后只要Parse抽象类中做定义就可以了,通过接口隐藏具体的实现实在太强大了

下面这段就是quickquery实现中加入了验证:

 protected virtual TResult ParseDirect(ref TResource resource)
        {
            Monitor.Watch(string.Format("read and parse file {0} .", resource.Path));
            TResult result = null;
            resource = ConfigReader.Read(ref resource);
            resource.PreLastWriteTime = resource.LastWriteTime;
            string ValidateResult = SchemaValidator.XmlValidateByXsd(ref resource);
            resource.Stream.Close();
            resource.Stream.Dispose();
            resource.Stream = null;
            if (!ValidateResult.IsNullOrEmpty())
            {
                string errorMessage = string.Format("file : {0} does not Conform to the schema file!", resource.Path);
                Monitor.Watch(errorMessage);
                throw new Exception.QuickQueryException(errorMessage);
            }
            resource = ConfigReader.Read(ref resource);
            resource.PreLastWriteTime = resource.LastWriteTime;
            result = resource.Entity = ConfigParser.Parse(ref resource);
            return result;
        }

下面就是DataQuery实现中加入的验证:

 public virtual TResult ParseSchema(ref TResource resource)
        {
            lock (_LockObject)
            {
                TResult result = new TResult();
                switch (resource.ParseLevel)
                {
                    case ParseLevel.NULL:
                        resource = ConfigResourceReader.Read(ref resource);
                    
                        resource = ConfigReader.Read(ref resource);
                        string ValidateResult = SchemaValidator.XmlValidateByXsd(ref resource);
                        resource.Stream.Close();
                        resource.Stream.Dispose();
                        resource.Stream = null;
                        if (!ValidateResult.IsNullOrEmpty())
                        {
                            string errorMessage = string.Format("file : {0} does not Conform to the schema file!", resource.Path);
                            Monitor.Watch(errorMessage);
                            throw new Exception.QuickQueryException(errorMessage);
                        }
                        resource = ConfigResourceReader.Read(ref resource);
                        resource = ConfigReader.Read(ref resource);
                        result = ConfigParser.ParseSchema(ref resource);
                        break;
                    case ParseLevel.Detail:
                        result = resource.Entity;
                        break;
                    default:
                        break;
                }
                return result;
            }
        }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值