【问题标题】:Can I declare and use DTD entities in App.config?我可以在 App.config 中声明和使用 DTD 实体吗?
【发布时间】:2013-02-14 11:23:04
【问题描述】:

我尝试在App.config 中定义和使用 DTD 实体。例如:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration [
  <!ENTITY dataSource ".\SQLEXPRESS">
]>
<configuration>
  <appSettings>
    <add key="FooDataSource" value="&dataSource;" />
  </appSettings>
  <connectionStrings>
    <add name="Foo" connectionString="Data Source=&dataSource;;Integrated Security=SSPI;" />
  </connectionStrings>
</configuration>

使用System.Configuration.ConfigurationManager 读取appSettingsconnectionStrings 不会引发错误,但也不会解析DTD 实体。

(有时程序根本不会执行。我不知道为什么 .NET 有时只抱怨配置错误。)

是我对 DTD 的使用不正确,还是 .NET 不支持 App.config 中的自定义 DTD 实体?

【问题讨论】:

    标签: .net app-config dtd


    【解决方案1】:

    System.Configuration 使用默认 XmlReaderSettings 来确定如何读取 .config 文件。其中有一个 ProhibitDtd 属性。你可以通过这段代码看到它的默认值:

      Console.WriteLine(new XmlReaderSettings().ProhibitDtd);
    

    输出:真

    这就是为什么您的 .config 文件不起作用的简单解释。没有任何方法可以将其配置为覆盖该设置。

    解释您的程序启动困难的原因需要更多的努力。第一次读取文件的时间很早,甚至在 CLR 启动之前。引导程序需要读取 .config 文件以确定要加载的 CLR 版本,&lt;requestedRuntime&gt; 元素很重要。它没有使用成熟的 XML 解析器,它是一个非常精简的解析器,删除了所有 DTD 解析位。下载SSCLI20可以看到,XML解析器存放在clr/src/xmlparser子目录下。究竟什么可能出错还不是很清楚,但是如果该解析器对 .config 文件有任何问题,那么您将不会找出问题可能是什么。这种情况发生得太早,无法生成任何合理的诊断。检查“输出”窗口以获取提供提示的可能退出代码号。

    【讨论】:

    • 优秀的答案!对不起这个毫无意义的评论,但我不得不给你荣誉:)
    【解决方案2】:

    您对实体的使用是正确的;这是格式正确的 XML,使用属性中的属性引用应该没有任何问题。

    它必须是 .NET* 的东西(我不知道)。

    为了证明实体是正确的,下面是通过解析实体的 XSLT 身份转换传递的 XML:

    XML 输入

    <!DOCTYPE configuration [
      <!ENTITY dataSource ".\SQLEXPRESS">
    ]>
    <configuration>
      <appSettings>
        <add key="FooDataSource" value="&dataSource;" />
      </appSettings>
      <connectionStrings>
        <add name="Foo" connectionString="Data Source=&dataSource;;Integrated Security=SSPI;" />
      </connectionStrings>
    </configuration>
    

    XSLT

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
    </xsl:stylesheet>
    

    XML 输出

    <configuration>
       <appSettings>
          <add key="FooDataSource" value=".\SQLEXPRESS"/>
       </appSettings>
       <connectionStrings>
          <add name="Foo"
               connectionString="Data Source=.\SQLEXPRESS;Integrated Security=SSPI;"/>
       </connectionStrings>
    </configuration>
    

    *以下是我发现的一些链接,其中提到其他人无法让 XML 实体工作:

    【讨论】:

      【解决方案3】:

      Reflector(在.NET 4.0上)说System.Configuration.ConfigXmlReader(内部,密封)用于读取配置数据,它基于System.Xml.XmlTextReader并调用它的构造函数XmlTextReader(TextReader input),它创建internal XmlTextReaderImpl(TextReader input),而这个构造函数调用this(string.Empty, input, new NameTable()),它调用this(nt)(仅限NameTable),将私有字段初始化为this.entityHandling = EntityHandling.ExpandCharEntities;

      MSDN says 表示 ExpandCharEntities:

      扩展字符实体并将一般实体返回为 EntityReference 节点。

      所以看起来你不能在 .config 文件中使用你自己的实体:(

      【讨论】:

        猜你喜欢
        • 2011-05-14
        • 1970-01-01
        • 2015-06-10
        • 2017-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多