【问题标题】:XmlSchemaSet DTD ProcessingXmlSchemaSet DTD 处理
【发布时间】:2018-01-21 18:04:42
【问题描述】:

我正在尝试针对 xsd 验证 xml。

 XmlSchemaSet schema = new XmlSchemaSet();
 schema.Add("", "http://abc.cba/OrderRequest"); <-- 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

首先,没有任何 XmlReader.Create 方法,所以想知道为什么该行会出现这种错误。

其次,我用谷歌搜索并通过不知道在哪里将 readersettings 添加到架构中找到了以下代码。

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

【问题讨论】:

    标签: c# xml


    【解决方案1】:

    我一开始以为reading the Xml时会抛出这个错误。但是,查看您的问题,我做了一些测试,可以看到尝试添加 DTD 文件会引发此异常。

    由于 XSD 也是一个 Xml 文件,因此在内部是“读取 Xml”引发此异常。

    仔细看,我得到以下 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)
    

    然后,查看.Net框架源码,如下抛出异常

    Source

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

    仔细观察,XmlSchemaSet 类构造了一个具有此属性集的 XmlReaderSettings

    XmlSchemaSet

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

    现在,这解释了错误的原因。

    我找不到覆盖此属性的公共方式。如果你真的想改变这一点,你可以使用反射。

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

    请谨慎使用上述代码,因为内部属性/字段可以在 .Net 框架的未来版本中更改。

    基于此,我想更正确的选择是为您的架构寻找 XSD(而不是 DTD)。

    XSD 是 more 首选。

    【讨论】:

      【解决方案2】:

      我找到了一种不使用反射的方法,如下所述:https://social.msdn.microsoft.com/Forums/expression/en-US/c88ef0b0-39a8-413e-8e35-deb95fb57e58/validate-xsd-against-w3-xmlschemaxsd?forum=xmlandnetfx

      解决方案是使用 XmlSchemaSet 并使用您自己的 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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-20
        • 1970-01-01
        • 1970-01-01
        • 2012-09-11
        • 1970-01-01
        • 1970-01-01
        • 2011-07-26
        • 1970-01-01
        相关资源
        最近更新 更多