使用具有导入的xsd验证XML文档

时间:2013-07-04 11:34:55

标签: c# xml xsd xsd-validation

我一直在网上搜索24小时,但却找不到有效的解决方案。

我有一个包含导入行的模式文件:

<xsd:import namespace="http://www.w3.org/2000/09/xmldsig#" 
            schemaLocation=
              "http://www.w3.org/TR/2001/PR-xmldsig-core-20010820/xmldsig-core-schema.xsd"/>

以下是验证Xml的代码:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(null, @"C:\TEMP\myschema.xsd");

XmlReader xmlReader = XmlReader.Create(new StringReader(document.InnerXml), settings);
while (xmlReader.Read()) { }

当我运行它时,我得到:The 'http://www.w3.org/2000/09/xmldsig#:Signature' element is not declared.

如果我将代码(如搜索建议)更改为:

settings.ValidationType = ValidationType.DTD;
settings.DtdProcessing = DtdProcessing.Parse;

然后我没有收到错误,但验证不起作用,因为我故意插入一个无效值来测试验证是否正常。

我已尝试添加直接导入的架构:

settings.Schemas.Add(null, @"C:\TEMP\xmldsig-core-schema.xsd");

但收到错误:For security reasons DTD is prohibited in this XML document. To enable DTD processing...

我已经尝试了我能想到的XmlReaderSettings设置的每个组合,并且已经通过搜索建议了。

我现在真的很难受。

3 个答案:

答案 0 :(得分:1)

您写道:

  

当我运行它时,我得到:http://www.w3.org/2000/09/xmldsig#:Signature元素未被声明。

看起来它无法通过该URL加载导入的架构: http://www.w3.org/TR/2001/PR-xmldsig-core-20010820/xmldsig-core-schema.xsd

我已经检查过该URL,并且该架构确实存在,以及该元素 {(1}}在其中声明(全局)。

但是加载该模式需要相当长的时间,显然是因为W3C阻止(并且实际上阻碍)来自众多软件的XML资源的巨大流量 全球各地。

关于这个:

  

但接收错误:出于安全原因,此XML文档中禁止使用DTD。   启用DTD处理...

我不确定您使用的是哪种编程系统(Java,.NET等),但它归结为其设置,可以通过您的代码或某些配置文件或环境变量传递给它。 / p>

该架构确实包含对必须加载的某些DTD(XMLSchema.dtd)的引用:

{http://www.w3.org/2000/09/xmldsig#}Signature

我建议您也从该网址加载该DTD:<!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd" [ <!ATTLIST schema xmlns:ds CDATA #FIXED 'http://www.w3.org/2000/09/xmldsig#'> <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'> <!ENTITY % p ''> <!ENTITY % s ''> ]> 并将其放在与架构相同的目录中。 然后,编辑模式文件并将DTD位置更改为相同(作为模式):

http://www.w3.org/2001/XMLSchema.dtd

...还需要<!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "XMLSchema.dtd" [ .... 本地,因为它是从http://www.w3.org/2001/datatypes.dtd引用的。

答案 1 :(得分:1)

跳过此验证的一种简单方法是在xmldsig-core-schema.xsd

上评论第一行(DTD部分)
<!--<!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd" [
   <!ATTLIST schema 
     xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#">
   <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
   <!ENTITY % p ''>
   <!ENTITY % s ''>
  ]>-->

答案 2 :(得分:0)

好的,设法搞清楚了。一直盯着我的脸。

当我尝试将xmldsig-core-schema.xsd架构添加到XmlReaderSettings时,我收到以下消息:

  

出于安全原因,此XML文档中禁止使用DTD。启用   DTD处理将XmlReaderSettings上的DtdProcessing属性设置为   解析并将设置传递给XmlReader.Create方法。

以下代码是我们需要的:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;

settings.Schemas.Add(null, @"C:\TEMP\myschema.xsd");

// Create new XmlReaderSettings with DtdProcessing set to Parse.
XmlReaderSettings settings2 = new XmlReaderSettings();
settings2.DtdProcessing = DtdProcessing.Parse;

// Create an XmlReader passing it the location of the problematic xsd and the new XmlReaderSettings.
XmlReader reader = XmlReader.Create(@"C:\TEMP\xmldsig-core-schema.xsd", settings2);

// Add the reader to the first XmlReaderSettings
settings.Schemas.Add(null, reader);

我认为编写该代码可能有更为雄辩和简洁的方法,但我花了很长时间才开始使用它,我很高兴它的工作原理。如果有人想编辑它,请随意。