繁体   English   中英

在C#中使用本地DTD文件验证XML文件的问题

[英]Problem validation a XML file with a local DTD file in C#

我正在试图验证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()之前添加Schema,但没有成功。

我之前做了一段时间来验证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

从我的探索可以让它工作的唯一方法是不将模式添加到XmlReader xml文档中指定的DTD必须是有效的URL,并且XmlReader每次都会下载它。

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

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

请注意文件:在网址中。 在将它传递给XmlReader之前在内存中执行此操作,这样您就不必修改xml文件只是为了修改它是正确的。

在调用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();

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM