根据.net中的模式进行多线程xml验证
本文关键字:多线程 xml 验证 模式 net 根据 | 更新日期: 2023-09-27 18:01:01
我试图在多线程应用程序中验证xml文件,但遇到了问题(验证错误:未声明"元素。
我认为这与XmlSchemaSet的架构验证错误/线程安全中的问题相同?这个问题,但我不知道如何让它发挥作用。
我最初使用的是内联模式,这很好,但解决外部文件的速度太慢了。我决定将模式缓存在ConcurrentDictionary中以加快速度。
这是代码:
此方法属于每个线程的本地对象。
public void validate()
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler +=
new ValidationEventHandler(ValidationCallBack);
using (var tr = new XmlTextReader(xmlFile))
{
tr.MoveToContent();
var url = tr.GetAttribute("xsi:noNamespaceSchemaLocation");
var schema = SchemaFactory.GetSchema(url);
settings.Schemas.Add(schema);
}
using (XmlReader reader = XmlReader.Create(xmlFile, settings))
{
while (reader.Read());
}
SchemaFactory定义:
public static class SchemaFactory
{
static ConcurrentDictionary<string, XmlSchema> schemaStore =
new ConcurrentDictionary<string, XmlSchema>();
public static XmlSchema GetSchema(string url)
{
XmlSchema schema = null;
if (!schemaStore.TryGetValue(url, out schema))
{
var schemadata = new System.Net.WebClient().DownloadString(url);
schema = XmlSchema.Read(new StringReader(schemadata), (sender, args) => { });
schemaStore.TryAdd(url, schema);
}
return schema;
}
}
在多个线程中处理时,如何在xml文件中第一次遇到架构时实时将其添加到缓存中
XMLSchema不是线程安全的。将模式缓存为字符串,然后它就可以工作了:
class Program
{
private ConcurrentDictionary<string, string> schemaStore =
new ConcurrentDictionary<string, string>();
static void Main(string[] args)
{
Program p = new Program();
for (int i = 0; i < 40;i++ )
new Thread(new ThreadStart(p.validate)).Start();
Console.ReadKey();
}
public void validate()
{
string xmlFile = "XMLFile1.xml";
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler +=
new ValidationEventHandler(ValidationCallBack);
using (var tr = new XmlTextReader(xmlFile))
{
tr.MoveToContent();
var url = tr.GetAttribute("xsi:noNamespaceSchemaLocation");
string schemaXml =null;
if (!schemaStore.TryGetValue(url, out schemaXml))
{
//Console.WriteLine("Need download");
using (System.Net.WebClient wc = new System.Net.WebClient())
{
string schemadata = wc.DownloadString(url);
schemaStore.TryAdd(url, schemadata);
schemaXml = schemadata;
}
}else
{
//Console.WriteLine("Cache hit");
}
XmlSchema schema = XmlSchema.Read(new StringReader(schemaXml), (sender, args) => { });
settings.Schemas.Add(schema);
}
using (XmlReader reader = XmlReader.Create(xmlFile, settings))
{
while (reader.Read()) ;
}
Console.WriteLine("Thread "+Thread.CurrentThread.ManagedThreadId+" completes");
}
private void ValidationCallBack(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Error)
Console.WriteLine("Thread " + Thread.CurrentThread.ManagedThreadId + " -> Error: " + args.Message);
else
Console.WriteLine("Thread " + Thread.CurrentThread.ManagedThreadId + " -> Warning: " + args.Message);
}
}
如果它仍然是真的,如XmlSchemaSet的架构验证错误/线程安全中所述?如果您不能针对同一个编译的模式运行多个并行模式验证,那么解决方法可能是使用没有此限制的Saxon模式验证器[无耻插件]。
http://www.saxonica.com/