使用.NET根据模式验证XML

时间:2010-08-10 13:03:27

标签: .net xml xsd xml-validation

我想测试(true或false)任意XML文件是否与给定模式匹配。

对于它的价值,架构是Word 2003 WordML架构,Microsoft使用大约7个*.xsd文件列表定义。

其中一个文件还包括W3C xml.xsd文件,包括以下声明:

<xsd:import id="xml" namespace="http://www.w3.org/XML/1998/namespace"
    schemaLocation="http://www.w3.org/2001/xml.xsd"></xsd:import>

我正在使用以下.NET代码进行验证:

   public static void validate(string filename)
    {
       XmlReaderSettings settings = new XmlReaderSettings();
       settings.Schemas.Add(
           "http://schemas.microsoft.com/office/word/2003/wordml",
           //to get this file I downloaded "Office 2003: XML Reference Schemas", i.e. "Office2003XMLSchema.exe" 
           @"C:\Program Files\Microsoft Office 2003 Developer Resources\Microsoft Office 2003 XML Reference Schemas\WordprocessingML Schemas\wordnet.xsd"
           );
        settings.ValidationType = ValidationType.Schema;
        settings.ValidationEventHandler += new ValidationEventHandler(validationEventHandler);
        XmlReader xmlReader = XmlReader.Create(filename, settings);
        while (xmlReader.Read()) { }
   }

我的问题是,如果我在未连接到互联网的计算机上运行此代码,则会收到XmlSchemaValidationException错误,导致找不到xml.xsd

为了解决这个问题,我下载了xml.xsd的副本,并使用settings.Schemas.Add方法显式添加:当机器未连接到互联网时,验证现在可以正常工作。

但是,当机器连接到互联网时,我现在收到错误消息The global attribute 'http://www.w3.org/XML/1998/namespace:lang' has already been declared.

所以显然我需要明确地添加它,或者我不需要,这取决于机器是否能够从互联网上静默下载(或者甚至可能以前能够下载它,并将其缓存在某个地方) )。

所以,如果我这样做是“该死的,如果我不这样做,该死的”。我是否需要以一种方式尝试,捕获异常,然后以其他方式尝试?还是有更优雅的解决方案?

1 个答案:

答案 0 :(得分:4)

我们看不到您的代码,但是在许多实现中,这是通过使用目录解析器将.xsd的请求重定向到本地副本来处理的。有一个属性XmlReaderSettings.XmlResolver可用于此目的。有关您可以使用的Apache许可实现,请参阅XMLCatalog.net

这样做的副作用是您可以保留所有本地缓存​​的模式。这一点尤其重要,因为W3C会阻止对其网站的过度读取,并且随机地将您的代码(或者更糟糕的是,您的客户代码)开始失败。