Problem validation a XML file with a local DTD file in C#

10,132

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

Share:
10,132
Jonathan
Author by

Jonathan

neverending student ;) https://es.linkedin.com/pub/jonathan-fernández-román/102/944/908

Updated on June 18, 2022

Comments

  • Jonathan
    Jonathan almost 2 years

    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.

  • Jonathan
    Jonathan over 14 years
    but I want the user to select from the HD both files, the XML and the dtd, and tell him if the XML is valid or not. I'm pretty sure that it can be done, but I don't know how :(
  • Jonathan
    Jonathan over 14 years
    I also tried ir before (and now again) with no luck. I obtain the same error. It's a little frustrating xD
  • Geoff
    Geoff over 14 years
    Updated my aswer with a possible solution to load the DTD from a local file.
  • Zach Bonham
    Zach Bonham over 14 years
    @Johnathan Maybe, after creating your XmlReader (in your original sample above), check the value of XmlReader.Settings.ProhibitDtd and see if it truly is false? From your question, I'm not sure if that was the value you were checking, or the value on the initial settings.ProhibitDtd. Just make sure they are showing the same value. If the reader does't, try setting it to false before loading your schemas? You've probably already tried it but there is nothing else that looks like it might even be an issue?
  • Jonathan
    Jonathan over 14 years
    I will try it as soon as posible. Thanks.
  • fretje
    fretje almost 14 years
    @Jonathan: Did you actually manage to get this to work with a .dtd file? I don't think XmlSchemaSet can be used with a .dtd file... Only .xsd files. I keep getting that error message, no matter what I try.
  • Jonathan
    Jonathan almost 14 years
    I didn't try it again until now. We did a workarround. I tried it yesterday because you left a comment. No answers for months, so I accepted de more detailed question.
  • Concrete Gannet
    Concrete Gannet over 10 years
    -1. fretje is correct, XmlSchemaSet is intended for XMl schemas (XSD) only.