我正在试图验证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,但没有成功。
答案 0 :(得分:3)
我之前做了一段时间来验证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
答案 1 :(得分:0)
从我的探索中,我可以让它工作的唯一方法是不将架构添加到XmlReader
。 xml文档中指定的DTD必须是有效的URL,XmlReader
每次都会下载它。
如果你需要shema是本地的,你可以使用正则表达式将DTD的url更改为指向本地文件,这样看起来像
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.3//EN" "file:C:\wml.dtd">
请注意网址中的文件:。在将它传递给XmlReader之前在内存中执行此操作,这样您就不必修改xml文件只是为了修改它是正确的。
答案 2 :(得分:0)
在调用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();
答案 3 :(得分:0)
我有类似的问题。对我来说,答案是DTD不需要像XML文件指出的那样通过Schema连接,通过模式添加导致我的问题。