1

我已经在互联网上搜索了 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 设置组合,并且这些设置已通过搜索得到建议。

我现在真的很困惑。

4

3 回答 3

3

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

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

出于安全原因,此 XML 文档中禁止使用 DTD。要启用 DTD 处理,请将 XmlReaderSettings 上的 DtdProcessing 属性设置为 Parse 并将设置传递给 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);

我认为可能有一种更雄辩和简洁的方式来编写该代码,但我已经花了很长时间在它上面,我很高兴它可以工作。如果有人想编辑它,请随意。

于 2013-07-04T14:20:10.063 回答
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 和架构确实存在那里,以及在其中 {http://www.w3.org/2000/09/xmldsig#}Signature声明的元素(全局)。

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

关于这个:

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

我不确定您使用哪种编程系统(Java、.NET 等),但这取决于它的设置,这些设置可以通过您的代码或某些配置文件或环境变量传递给它。

该架构确实包含对必须加载的某些 DTD (XMLSchema.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 ''>
]>

我建议您也从该 URL 加载该 DTD:http://www.w3.org/2001/XMLSchema.dtd 并将其放在与架构相同的目录中。然后,编辑架构文件并将 DTD 位置更改为相同(与架构相同):

<!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "XMLSchema.dtd" [
....

...并且http://www.w3.org/2001/datatypes.dtd在本地也需要,因为它是从XMLSchema.dtd.

于 2013-07-04T12:38:31.007 回答
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 ''>
  ]>-->
于 2014-05-13T19:26:37.193 回答