我试图在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
来阅读appSettings
或connectionStrings
不会引发错误,但它也无法解析DTD实体。
(有时程序根本不会执行。我不知道为什么.NET有时会抱怨配置错误。)
我对DTD的使用是否不正确,或者.NET不支持App.config
中的自定义DTD实体?
答案 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文件中使用你自己的实体:(