Объекты параметров во внутреннем DTD

#php #xml #domdocument #dtd

#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
^
 

Почему это так?

Ответ №1:

Во внутреннем подмножестве DTD ссылки на объекты параметров не допускаются в объявлениях разметки. Вы должны использовать внешний DTD, то есть отдельный файл. Это задокументировано как ограничение корректности в спецификации XML здесь.

Комментарии:

1. Во внутреннем подмножестве DTD ссылки на объекты параметров запрещены. Чтобы немного прояснить; ссылки на объекты параметров не могут встречаться в объявлениях разметки, но они могут встречаться на том же уровне, что и объявления разметки.

2. @DanielHaley Да, исправил мой ответ. Спасибо.

Ответ №2:

Спецификация гласит:

Во внутреннем подмножестве 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>