内部 DTD 中的参数实体
Parameter entities in internal DTD
我有以下 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
^
为什么会这样?
在 DTD 的内部子集中,标记声明中不允许引用参数实体。您必须使用外部 DTD,即单独的文件。这在 XML 规范 here.
中记录为格式良好的约束
spec 状态:
In the internal DTD subset, parameter-entity references must not occur
within markup declarations; they may occur where markup declarations
can occur. (This does not apply to references that occur in external
parameter entities or to the external subset.)
所以在内部子集中,您不能从标记声明中引用参数实体。
虽然您可以从与标记声明相同的级别引用它。
这意味着您必须 declare/reference 像这样的参数实体:
<!DOCTYPE root [
<!ENTITY % placeholder "<!ELEMENT root (my, element, list)>">
%placeholder;
<!ELEMENT my (#PCDATA)>
<!ELEMENT element (#PCDATA)>
<!ELEMENT list (#PCDATA)>
]>
<root>
<my />
<element />
<list />
</root>
我有以下 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
^
为什么会这样?
在 DTD 的内部子集中,标记声明中不允许引用参数实体。您必须使用外部 DTD,即单独的文件。这在 XML 规范 here.
中记录为格式良好的约束spec 状态:
In the internal DTD subset, parameter-entity references must not occur within markup declarations; they may occur where markup declarations can occur. (This does not apply to references that occur in external parameter entities or to the external subset.)
所以在内部子集中,您不能从标记声明中引用参数实体。
虽然您可以从与标记声明相同的级别引用它。
这意味着您必须 declare/reference 像这样的参数实体:
<!DOCTYPE root [
<!ENTITY % placeholder "<!ELEMENT root (my, element, list)>">
%placeholder;
<!ELEMENT my (#PCDATA)>
<!ELEMENT element (#PCDATA)>
<!ELEMENT list (#PCDATA)>
]>
<root>
<my />
<element />
<list />
</root>