我有以下simple.dtd
:
<!ENTITY % placeholder "my, element, list">
<!ELEMENT root (%placeholder;)>
<!ELEMENT my (#PCDATA)>
<!ELEMENT element (#PCDATA)>
<!ELEMENT list (#PCDATA)>
和simple.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE root SYSTEM "simple.dtd">
<root>
<my />
<element />
<list />
</root>
这是有效的。
但完全相同的DTD内联:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE root [
<!ENTITY % placeholder "my, element, list">
<!ELEMENT root (%placeholder;)>
<!ELEMENT my (#PCDATA)>
<!ELEMENT element (#PCDATA)>
<!ELEMENT list (#PCDATA)>
]>
<root>
<my />
<element />
<list />
</root>
因错误而失败:
$ xmllint --valid simple.xml
simple.xml:4: parser error : ContentDecl : Name or '(' expected
<!ELEMENT root (%placeholder;)>
^
simple.xml:4: parser error : expected '>'
<!ELEMENT root (%placeholder;)>
^
Entity: line 1: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
%placeholder;
^
Entity: line 1:
my, element, list
^
Entity: line 1: parser error : DOCTYPE improperly terminated
%placeholder;
^
Entity: line 1:
my, element, list
^
Entity: line 1: parser error : Start tag expected, '<' not found
%placeholder;
^
Entity: line 1:
my, element, list
^
为什么会这样?
答案 0 :(得分:2)
在DTD的内部子集中,标记声明中不允许引用参数实体。您必须使用外部DTD,即单独的文件。这被记录为XML规范here中的格式良好约束。
答案 1 :(得分:2)
spec州:
在内部DTD子集中,不得出现参数实体引用 标记声明中;它们可能出现在标记声明的地方 可以发生。 (这不适用于在外部发生的引用 参数实体或外部子集。)
因此,在内部子集中,您无法在标记声明中引用参数实体。
你可以从与标记声明相同的级别引用它。
这意味着您必须声明/引用参数实体,如下所示:
<!DOCTYPE root [
<!ENTITY % placeholder "<!ELEMENT root (my, element, list)>">
%placeholder;
<!ELEMENT my (#PCDATA)>
<!ELEMENT element (#PCDATA)>
<!ELEMENT list (#PCDATA)>
]>
<root>
<my />
<element />
<list />
</root>