问题
I'm triying to validate a XML file. I'm using this code
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();
But in the line "reader.Settings.Schemas.Add(null, lblDTDPath.Text);" Visual Studio show me that error "For security reasons DTD is prohibited in this XML document. To enable DTD processing set the ProhibitDtd property on XmlReaderSettings to false and pass the settings into XmlReader.Create method"
As you can see in the code, ProhibitDtd is setted to false (I verified during debug too). I also tried to add the Schema before call to XmlReader.Create() with no success.
回答1:
I did this some time before for validating RSS feeds. The method to do validation by locally stored DTD was to insert a custom XmlResolver
to the XmlReader
XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.ValidationType = ValidationType.DTD;
readerSettings.ProhibitDtd = false;
readerSettings.XmlResolver = new XmlFakeDtdResolver();
which would give the reader the local DTD (for known formats) instead of downloading it from the URL given in DOCTYPE.
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);
}
}
As an end note, I decided to not use DTD validation in the end and go for validation by XML schema, one reason being that many feeds didn't include the DOCTYPE
回答2:
Try adding to your DTD schema to schemas collection before the call to XmlReader.Create.
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:
From my poking around the only way i could get it to work is not to add the schema to the XmlReader
. The DTD specified in the xml document must be a valid url and the XmlReader
will download it each time.
If you need the shema to be local, you can change the url of the DTD to point to a local file using a regular expression so it would look somthing like
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.3//EN" "file:C:\wml.dtd">
Note the file: in the url. Do this in memory before passing it to the XmlReader and that way you do not have to modify the xml file just to varify that it is correct.
回答4:
I had a similar problem. The answer, for me, was that the DTD doesn't need to be hooked up via the Schemas as the XML file points to out, adding via schemas caused me the issue.
来源:https://stackoverflow.com/questions/1508799/problem-validation-a-xml-file-with-a-local-dtd-file-in-c-sharp