MiJo
MiJo

Reputation: 569

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

For example, lets say one XML file book_list.xml is a list view of books with 0 or more books each having only 3 child elements id, title and 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>

Another XML file book.xml is a detailed view of a single book with many other required attributes such as publisher, year, isbn. The root element for this document is 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>

My question is can we provide overloaded definitions for book element in a single DTD where book element has only 3 child elements when it is a child of bookList but is "required" to have many other child elements if book itself is the document root or do we have to create separate DTD files?

Upvotes: 3

Views: 3136

Answers (2)

Daniel Haley
Daniel Haley

Reputation: 52858

I think the closest you can come to this type of functionality with DTD is by using INCLUDE and IGNORE sections.

You can create parameter entities to hold the INCLUDE/IGNORE values. The DTD can be setup to default to one of the book declarations.

To switch to the other book declaration, you need to redefine your parameter entities in the internal subset of your DOCTYPE declaration.

Example (validated in oXygen using Xerces)

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>

Upvotes: 4

potame
potame

Reputation: 7905

No, it's not possible.

When an element is defined in DTDs, its definition will be the same, whatever the context you are using this element, and the only possibility would be to provide an overall definition of your book element with optional tags or attributes.

However it is a feature you have (with a few conditions) in XML Schemas, where you can provide local definitions for element content.

Upvotes: 0

Related Questions