【问题标题】:Problem validation a XML file with a local DTD file in C#在 C# 中使用本地 DTD 文件验证 XML 文件的问题
【发布时间】:2010-12-03 06:54:43
【问题描述】:

我正在尝试验证 XML 文件。我正在使用此代码

XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.ValidationType = ValidationType.DTD;

settings.ValidationEventHandler += new ValidationEventHandler(validationError);        

XmlSchemaSet schemas = new XmlSchemaSet();
settings.Schemas = schemas;
XmlReader reader = XmlReader.Create(lblXmlPath.Text, settings);

reader.Settings.Schemas.Add(null, lblDTDPath.Text);
while (reader.Read())
{ 
          // empty by now
}
reader.Close();

但是在“reader.Settings.Schemas.Add(null, lblDTDPath.Text);”这一行中Visual Studio 向我显示错误“出于安全原因,此 XML 文档中禁止 DTD。要启用 DTD 处理,请将 XmlReaderSettings 上的 ProhibitDtd 属性设置为 false 并将设置传递给 XmlReader.Create 方法”

正如您在代码中看到的,ProhibitDtd 设置为 false(我也在调试期间进行了验证)。我还尝试在调用 XmlReader.Create() 之前添加架构,但没有成功。

【问题讨论】:

    标签: c# xml validation dtd


    【解决方案1】:

    我之前为验证 RSS 提要做过此操作。通过本地存储的DTD进行验证的方法是将自定义XmlResolver插入XmlReader

    XmlReaderSettings readerSettings = new XmlReaderSettings();
    readerSettings.ValidationType = ValidationType.DTD;
    readerSettings.ProhibitDtd = false;
    readerSettings.XmlResolver = new XmlFakeDtdResolver();
    

    这将为读者提供本地 DTD(对于已知格式),而不是从 DOCTYPE 中给出的 URL 下载它。

    class XmlFakeDtdResolver : XmlUrlResolver
    {
        public static Dictionary<Uri, byte[]> dtdMap = new Dictionary<Uri, byte[]>();
        public static Dictionary<string, Uri> uriMap = new Dictionary<string, Uri>();
        static XmlFakeDtdResolver()
        {
            Uri rss091uri = new Uri("http://fake.uri/rss091");
            uriMap["-//Netscape Communications//DTD RSS 0.91//EN"] = rss091uri;
            uriMap["http://my.netscape.com/publish/formats/rss-0.91.dtd"] = rss091uri;
            dtdMap[rss091uri] = Encoding.ASCII.GetBytes(Resources.rss_0_91dtd);
        }
    
        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
        {
            if (dtdMap.ContainsKey(absoluteUri) && ofObjectToReturn == typeof(Stream))
            {
                return new MemoryStream(dtdMap[absoluteUri]);
            }
            return base.GetEntity(absoluteUri, role, ofObjectToReturn);
        }
    
        public override Uri ResolveUri(Uri baseUri, string relativeUri)
        {
            if (uriMap.ContainsKey(relativeUri))
                return uriMap[relativeUri];
            return base.ResolveUri(baseUri, relativeUri);
        }
    }
    

    最后,我决定最终不使用 DTD 验证,而是通过 XML 模式进行验证,原因之一是许多提要不包含 DOCTYPE

    【讨论】:

      【解决方案2】:

      尝试在调用 XmlReader.Create 之前将您的 DTD 架构添加到架构集合。

      XmlReaderSettings settings = new XmlReaderSettings();
      settings.ProhibitDtd = false;
      settings.ValidationType = ValidationType.DTD;
      
      settings.ValidationEventHandler += new ValidationEventHandler(validationError);        
      
      XmlSchemaSet schemas = new XmlSchemaSet();
      
      schemas.Add(null, lblDTDPath.Text);
      settings.Schemas = schemas;
      
      XmlReader reader = XmlReader.Create(lblXmlPath.Text, settings);
      
      while (reader.Read())
      { 
                // empty by now
      }
      reader.Close();
      

      【讨论】:

      • 我之前(现在又一次)也尝试过 ir,但没有成功。我得到同样的错误。这有点令人沮丧xD
      • @Johnathan 也许,在创建您的 XmlReader(在上面的原始示例中)之后,检查 XmlReader.Settings.ProhibitDtd 的值,看看它是否真的是假的?根据您的问题,我不确定这是您正在检查的值,还是初始 settings.ProhibitDtd 上的值。只要确保它们显示相同的值即可。如果读者没有,请尝试在加载模式之前将其设置为 false?您可能已经尝试过,但似乎没有其他问题可能会成为问题?
      • @Jonathan:你真的设法让它与 .dtd 文件一起工作吗?我不认为 XmlSchemaSet 可以与 .dtd 文件一起使用......只有 .xsd 文件。无论我尝试什么,我都会不断收到该错误消息。
      • 直到现在我才再次尝试。我们做了一个解决方法。我昨天试过了,因为你留下了评论。几个月没有答案,所以我接受了更详细的问题。
      • -1。 fretje 是正确的,XmlSchemaSet 仅适用于 XML 模式 (XSD)。
      【解决方案3】:

      根据我的探索,我可以让它工作的唯一方法是不将架构添加到XmlReader。 xml文档中指定的DTD必须是有效的url,XmlReader每次都会下载。

      如果您需要 shema 是本地的,您可以使用正则表达式将 DTD 的 url 更改为指向本地文件,这样它看起来就像

      <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.3//EN" "file:C:\wml.dtd">
      

      注意 url 中的 file:。在将其传递给 XmlReader 之前在内存中执行此操作,这样您就不必修改 xml 文件来验证它是否正确。

      【讨论】:

      • 但我希望用户从 HD 中选择 XML 和 dtd 这两个文件,并告诉他 XML 是否有效。我很确定可以做到,但我不知道怎么做:(
      • 更新了我的 aswer,提供了一种从本地文件加载 DTD 的可能解决方案。
      【解决方案4】:

      我遇到了类似的问题。对我来说,答案是 DTD 不需要通过模式连接,正如 XML 文件指出的那样,通过模式添加导致了我的问题。

      【讨论】:

      • 我会尽快尝试。谢谢。
      猜你喜欢
      • 1970-01-01
      • 2010-11-08
      • 1970-01-01
      • 2015-05-18
      • 1970-01-01
      • 2011-12-26
      • 1970-01-01
      • 2010-12-25
      • 2010-12-28
      相关资源
      最近更新 更多