简体   繁体   中英

XmlSchemaSet DTD Processing

I am trying to validate an xml against xsd.

 XmlSchemaSet schema = new XmlSchemaSet();
 schema.Add("", "http://abc.cba/OrderRequest"); <-- error

And getting the following error

  For security reasons DTD is prohibited in this XML document. 
  To enable DTD processing set the DtdProcessing property on XmlReaderSettings to 
  Parse and pass the settings into XmlReader.Create method

First, there isnt any XmlReader.Create method so wondering why is this kind of error on that line.

Secondly, I googled and found the following code by dont know where to add the readersettings to the schema.

 XmlReaderSettings readerSettings = new XmlReaderSettings();
 readerSettings.ValidationType = ValidationType.DTD;
 readerSettings.DtdProcessing = DtdProcessing.Parse;

I initially thought that this error can be thrown while reading the Xml . But, looking at your question, I did some tests and can see that trying to add a DTD file throws this exception.

Since an XSD is also an Xml file, internally it is "reading of the Xml" that is throwing this exception.

Looking more closer, I get the following StackTrace

Unhandled Exception: System.Xml.XmlException: For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.ParseDoctypeDecl()
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.Schema.Parser.StartParsing(XmlReader reader, String targetNamespace)
   at System.Xml.Schema.Parser.Parse(XmlReader reader, String targetNamespace)
   at System.Xml.Schema.XmlSchemaSet.ParseSchema(String targetNamespace, XmlReader reader)
   at System.Xml.Schema.XmlSchemaSet.Add(String targetNamespace, String schemaUri)

Then, looking at the .Net framework source code, the following throws the exception

Source

    // Parses DOCTYPE declaration
    private bool ParseDoctypeDecl() {
        if ( dtdProcessing == DtdProcessing.Prohibit ) {
            ThrowWithoutLineInfo( v1Compat ? Res.Xml_DtdIsProhibited : Res.Xml_DtdIsProhibitedEx );
        }

Looking more closer, the XmlSchemaSet class constructs an XmlReaderSettings which has this property set

XmlSchemaSet

readerSettings = new XmlReaderSettings();
readerSettings.DtdProcessing = DtdProcessing.Prohibit;

Now, this explains the reason for the error.

I could not find a public way to over-ride this property. If you really want to change this, you can use reflection.

        XmlSchemaSet schema = new XmlSchemaSet();

        var value = schema.GetType().GetProperty("ReaderSettings", BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(schema) as XmlReaderSettings;

        value.DtdProcessing = DtdProcessing.Parse;

Use the above code with caution, as the internal properties / fields can be changed in future versions of .Net framework.

Based on this, I guess the more correct option is to look for an XSD (instead of DTD) for your schema.

XSD is more preferred.

I found a way not using reflection, as documented here: https://social.msdn.microsoft.com/Forums/expression/en-US/c88ef0b0-39a8-413e-8e35-deb95fb57e58/validate-xsd-against-w3-xmlschemaxsd?forum=xmlandnetfx

Solution is to use XmlSchemaSet and add schema with your own XmlReader.

XmlSchemaSet set = new XmlSchemaSet();
using (XmlReader xr = XmlReader.Create(
    new XmlTextReader("https://www.w3.org/2001/XMLSchema.xsd"),
    new XmlReaderSettings() { DtdProcessing = DtdProcessing.Ignore }))
{
    set.Add(null, xr);
}
set.Compile();

// Set the validation settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(set);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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