Problème de validation d’un fichier XML avec un fichier DTD local en C #

Je tente de valider un fichier XML. J’utilise ce 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(); 

Mais dans la ligne “reader.Settings.Schemas.Add (null, lblDTDPath.Text);” Visual Studio m’a montré cette erreur “Pour des raisons de sécurité, la DTD est interdite dans ce document XML. Pour activer le traitement de la DTD, définissez la propriété ProhibitDtd sur XmlReaderSettings sur false et transmettez les parameters à la méthode XmlReader.Create”

Comme vous pouvez le constater dans le code, ProhibitDtd est défini sur false (j’ai également vérifié lors du débogage). J’ai également essayé d’append le schéma avant d’appeler XmlReader.Create () sans succès.

Je l’avais déjà fait avant pour valider les stream RSS. La méthode de validation par la DTD stockée localement consistait à insérer un XmlResolver personnalisé dans XmlReader

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

qui donnerait au lecteur la DTD locale (pour les formats connus) au lieu de la télécharger à partir de l’URL indiquée dans DOCTYPE.

 class XmlFakeDtdResolver : XmlUrlResolver { public static Dictionary dtdMap = new Dictionary(); public static Dictionary uriMap = new Dictionary(); 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, ssortingng 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, ssortingng relativeUri) { if (uriMap.ContainsKey(relativeUri)) return uriMap[relativeUri]; return base.ResolveUri(baseUri, relativeUri); } } 

En guise de remarque finale, j’ai décidé de ne pas utiliser la validation DTD à la fin et d’accepter une validation par schéma XML, notamment parce que de nombreux stream n’incluaient pas DOCTYPE.

Essayez d’append à votre schéma DTD une collection de schémas avant l’appel à 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(); 

D’après moi, le seul moyen de le faire fonctionner est de ne pas append le schéma à XmlReader . La DTD spécifiée dans le document XML doit être une URL valide et XmlReader téléchargera à chaque fois.

Si vous avez besoin que le shema soit local, vous pouvez modifier l’URL de la DTD pour qu’elle pointe vers un fichier local à l’aide d’une expression régulière, de sorte que

  

Notez le fichier: dans l’URL. Faites cela en mémoire avant de le transmettre au XmlReader. Ainsi, vous n’aurez pas à modifier le fichier XML simplement pour faire en sorte qu’il soit correct.

J’avais un problème similaire. La réponse, pour moi, était que la DTD n’avait pas besoin d’être connectée via les schémas car le fichier XML pointait vers l’extérieur, l’ajout via des schémas m’ayant causé le problème.