在 XML DTD 中,是否可以根据同一元素是否为文档根来提供多个定义?

In XML DTDs is it possible to provide multiple definitions for same element depending on whether it will be document root or not?

例如,假设一个 XML 文件 book_list.xml 是包含 0 本书或多本书的列表视图,每本书只有 3 个子元素 id、title 和 author。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE bookList SYSTEM "books.dtd">
<bookList>
    <book>
        <id>123</id>
        <title>One Book Title</title>
        <author>......</author>
    </book>

    <book>
        <id>456</id>
        <title>Another Book Title</title>
        <author>......</author>
    </book>
</bookList>

另一个 XML 文件 book.xml 是单本书的详细视图,其中包含许多其他必需属性,例如出版商、年份、isbn。此文档的根元素是 book.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book SYSTEM "books.dtd">
<book>
    <id>123</id>
    <title>One Book Title</title>
    <author>.....</author>
    <isbn>......</isbn>
    <year>......</year>
    <publisher>......</publisher>
</book>

我的问题是我们能否在单个 DTD 中为 book 元素提供重载定义,其中 book 元素只有 3 个子元素,当它是 bookList 的子元素时 "required" 如果 book 本身是文档根,那么有许多其他子元素,还是我们必须创建单独的 DTD 文件?

不,这不可能。

当一个元素在 DTD 中定义时,它的定义将是相同的,无论您使用该元素的上下文如何,唯一的可能性是提供 book 元素的整体定义,并提供可选的标签或属性。

然而,这是您在 XML 架构中拥有的一项功能(有一些条件),您可以在其中为元素内容提供本地定义。

我认为使用 DTD 最接近此类功能的方法是使用 INCLUDE and IGNORE sections

您可以创建参数实体来保存 INCLUDE/IGNORE 值。 DTD 可以设置为默认 book 声明之一。

要切换到其他 book 声明,您需要在 DOCTYPE 声明的内部子集中重新定义参数实体。

示例(使用 Xerces 在 oXygen 中验证)

books.dtd

<!ENTITY % bigbook   "IGNORE">
<!ENTITY % smallbook "INCLUDE">

<!ELEMENT bookList (book)+>

<![%smallbook;[
<!ELEMENT book (id,title,author)>
]]>

<![%bigbook;[
<!ELEMENT book (id,title,author,isbn,year,publisher)>
]]>

<!ELEMENT id (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT isbn (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT publisher (#PCDATA)>

book_list.xml

<!DOCTYPE bookList SYSTEM "books.dtd">
<bookList>
    <book>
        <id>123</id>
        <title>One Book Title</title>
        <author>......</author>
    </book>    
    <book>
        <id>456</id>
        <title>Another Book Title</title>
        <author>......</author>
    </book>
</bookList>

book.xml

<!DOCTYPE book SYSTEM "books.dtd" [
<!ENTITY % bigbook   "INCLUDE">
<!ENTITY % smallbook "IGNORE">
]>
<book>
    <id>123</id>
    <title>One Book Title</title>
    <author>.....</author>
    <isbn>......</isbn>
    <year>......</year>
    <publisher>......</publisher>
</book>