我可以在App.config中声明和使用DTD实体吗?

时间:2013-02-28 10:05:59

标签: .net app-config dtd

我试图在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实体?

3 个答案:

答案 0 :(得分:4)

System.Configuration使用默认的XmlReaderSettings来确定如何读取.config文件。其中有一个ProhibitDtd属性。您可以使用以下代码查看其默认值:

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

输出:True

这就是为什么.config文件不起作用的简单解释。无法将其配置为覆盖设置。

解释为什么您的程序启动有问题需要更多努力。在CLR开始之前,第一次读取文件非常早。引导程序需要读取.config文件以确定要加载的CLR版本,<requestedRuntime>元素很重要。它没有使用完整的XML解析器,它是一个非常修剪的,它删除了所有DTD解析位。您可以通过下载SSCLI20来查看它,XML解析器存储在clr / src / xmlparser子目录中。究竟什么可能出错也不是那么清楚,但如果该解析器与.config文件有任何问题,那么你就不会发现问题可能是什么。这种情况发生得太早,无法生成任何合理的诊断。检查“输出”窗口,查找提示提示的退出代码编号。

答案 1 :(得分:1)

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

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

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

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实体工作:

答案 2 :(得分:1)

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文件中使用你自己的实体:(