如果您只想将一个通用实体作为正文内容中的文本字符串扩展为文件路径,您可以立即执行此操作:
<!ENTITY system "SystemA">
<!ENTITY path "&system;.config">
但是,如果您想从 .config 文件中获取标记声明以使其成为 DTD 的一部分,那么您需要一个外部实体声明(正如您已经弄清楚的那样)。要在 声明 中使用文本替换(相对于内容),您必须使用 参数实体 而不是一般实体。参数实体使用百分号声明(注意声明中百分号后面的空格,而参数实体 references 必须没有空格;
<!ENTITY % paramentity "SystemA">
现在您可以使用%paramentity; 替换成字符串SystemA 在标记声明中;
<!ELEMENT x ..,>
%paramentity;
尽管上述内容会出现错误,因为字符串 SystemA(或任何其他字符数据)不允许出现在 DTD/文档序言中。
还有一个额外的问题:参数实体引用没有在标识符文字中扩展,所以这不工作:
<!ENTITY % myent SYSTEM "%paramentity;/f.config">
相反,字符串%paramentity;/f.config 被逐字作为%myent; 的替换值。要从参数实体构建系统标识符,您应该将文字标记作为一个整体来定位:
<!ENTITY % sysid "'filename'">
<!ENTITY file SYSTEM %sysid;>
XML 的这种行为是由于 SGML(XML 作为子集派生而来)。具体来说,SGML 设置了许多限制,参数实体扩展可以出现在文档序言中(或者,对于 SGML 但不是没有这些的 XML),也可以在内容中的标记声明中(例如标记的部分声明)。 SGML 这样做是为了防止混淆使用标记。