内部DTD中的参数实体

时间:2016-09-17 16:50:51

标签: xml 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
^

为什么会这样?

2 个答案:

答案 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>