3. Λογικές Δομές (Logical Structures)

 

Κάθε XML έγγραφο περιέχει ένα ή περισσότερα στοιχεία (elements), τα όρια των οποίων καθορίζονται από start-tags και end-tags, για κενά(empty) στοιχεία, από έναν empty element tag. Κάθε στοιχείο έχει έναν τύπο που καθορίζεται από το όνομά του,  που μερικές φορές ονομάζεται generic identifier(GI), και που μπορεί να έχει ένα σύνολο χαρακτηριστικών προδιαγραφής. Κάθε χαρακτηριστικό προδιαγραφής έχει ένα όνομα(name) και μια τιμή(value).

  Αυτή η προδιαγραφή δεν περιορίζει τη σημασιολογία αλλά χρησιμοποιεί ονόματα των στοιχείων και των χαρακτηριστικών εκτός από τα ονόματα που ξεκινούν ως εξής:

((‘Χ’! ‘x’) (‘M’! ‘m’) (‘L’! ‘l’)) και είναι δεσμευμένα για τυποποίηση σε αυτήν ή σε μελλοντικές εκδόσεις αυτής της προδιαγραφής.

 

Περιορισμός Well-formed: Ταίριασμα Του Τύπου Στοιχείου

Το name στο end-tag ενός στοιχείου πρέπει να ταιριάζει με τον τύπο στοιχείου στο start-tag.

Περιορισμός Valid: Valid Στοιχεία

Ένα στοιχείο είναι έγκυρο όταν υπάρχει δήλωση elementdecl όπου το name να ταιριάζει στον τύπο στοιχείου και να ισχύουν τα ακόλουθα:

            1.      Η δήλωση είναι EMPTY και τo στοιχείο δεν έχει περιεχόμενο(content).

2.      Η δήλωση είναι children και μια αλληλουχία στοιχείων παιδιού(child elements) ανήκει στη γλώσσα και παράγεται από μια συνήθη έκφραση στο μοντέλο περιεχομένου, με λευκά κενά(χαρακτήρες που να ταιριάζουν στο s) ανάμεσα σε κάθε ζεύγος στοιχείων παιδιού.

3.      Η δήλωση είναι mixed και το περιεχόμενο περιέχει χαρακτήρες δεδομένων και στοιχεία παιδιού των οποίων οι τύποι ταιριάζουν με τα ονόματα στο μοντέλο περιεχομένου.

4.      Η δήλωση είναι ANY και οι τύποι όλων των στοιχείων παιδιού έχουν δηλωθεί.

 

3.1 Start-tags, End-tags και Empty-element tags.

  Το ξεκίνημα κάθε μη κενού XML στοιχείου γίνεται με ένα start-tag .

Το name στα start και end tags δίνει τον τύπο του στοιχείου. Τα ζεύγη name-attvalue αναφέρονται ως προδιαγραφές χαρακτηριστικών του στοιχείου, με το name σε κάθε ζεύγος να αναφέρεται στο χαρακτηριστικό όνομα και το  περιεχόμενο του attvalue στο χαρακτηριστικό τιμή.

 

Περιορισμός Well-formed: Μοναδικό Att Spec

Κανένα χαρακτηριστικό όνομα δεν μπορεί να εμφανιστεί περισσότερη από μια φορά στο ίδιο start-tag ή empty-element tag.

Περιορισμός Valid: Χαρακτηριστικό τύπου τιμής.

Το χαρακτηριστικό πρέπει να δηλωθεί; η τιμή θα πρέπει να ανήκει στον τύπο δήλωσης.

 

Περιορισμός Well-formed: Καμία Εξωτερική Αναφορά Οντότητας

Τα χαρακτηριστικά τιμής δεν μπορούν να περιέχουν άμεσες ή έμμεσες αναφορές οντοτήτων σε εξωτερικές οντότητες.

 

Περιορισμός Well-formed: Μη ύπαρξη του συμβόλου < στα χαρακτηριστικά τιμής.

Το κείμενο αντικατάστασης σε οποιαδήποτε οντότητα που αναφέρεται άμεσα ή έμμεσα σε χαρακτηριστικό τιμής (εκτός του “&lt”) δεν πρέπει να περιέχει το σύμβολο <.

 Ένα παράδειγμα start-tag είναι το εξής:

<termdef id="dt-dog" term="dog">

Το τέλος κάθε στοιχείου που ξεκινάει με ένα start-tag πρέπει να δηλώνεται με ένα end-tag το οποίο να περιέχει ένα όνομα που να αντιστοιχεί στον τύπο στοιχείου όπως δίνεται από το start-tag.

Ένα παράδειγμα από end-tag είναι το εξής:

</termdef>

Το κείμενο μεταξύ του start-tag και του end-tag ονομάζεται περιεχόμενο στοιχείου.

 

Εάν ένα στοιχείο είναι κενό, θα πρέπει θα πρέπει να αντιπροσωπεύεται είτε από ένα tag αρχής ακολουθούμενο από ένα tag τέλους είτε από ένα tag κενού στοιχείου(empty element tag). 

Τα tag κενού στοιχείου μπορούν να χρησιμοποιηθούν για οποιοδήποτε στοιχείο που δεν έχει περιεχόμενο, είτε είναι δηλωμένο χρησιμοποιώντας τη λέξη EMPTY είτε όχι.

 Παραδείγματα κενών στοιχείων: 

<IMG align="left"
src="http://www.w3.org/Icons/WWW/w3c_home" />
<br></br>
<br/>

  

3.2 Δηλώσεις Τύπου Στοιχείου (Element Type Declarations)

 Η δομή του στοιχείου ενός XML εγγράφου μπορεί, για σκοπούς εγκυρότητας, να είναι περιορισμένη χρησιμοποιώντας τύπους στοιχείων και δηλώσεις λίστας χαρακτηριστικών. Μια  δήλωση τύπου στοιχείου περιορίζει το περιεχόμενο του στοιχείου.

 Οι δηλώσεις τύπου στοιχείου συχνά καθορίζουν ποιοι τύποι στοιχείων μπορούν να εμφανίζονται ως παιδιά του στοιχείου. Κατά την εκλογή του χρήστη , ο XML επεξεργαστής μπορεί να εισάγει μια ειδοποίηση όταν η δήλωση αναφέρεται σε έναν τύπο στοιχείου για τον οποίο δεν παρέχεται δήλωση, αλλά αυτό δεν είναι λάθος.

 Όπου το name δίνει τον τύπο στοιχείου που δηλώνεται.

 Περιορισμός Valid: Μοναδική Δήλωση Τύπου Στοιχείου

Κανένας τύπος στοιχείου δεν μπορεί να δηλώνεται περισσότερες από μια φορές.

Παραδείγματα δηλώσεων τύπων στοιχείων:

 

<!ELEMENT br EMPTY>
<!ELEMENT p (#PCDATA|emph)* >
<!ELEMENT %name.para; %content.p>
<!ELEMENT container ANY>

3.2.1 Περιεχόμενο Στοιχείου (Element Content)

Ένας τύπος στοιχείου έχει ένα περιεχόμενο στοιχείου, όταν τα στοιχεία αυτού του τύπου περιέχουν υποχρεωτικά στοιχεία παιδιών (και όχι χαρακτήρες δεδομένων), χωρισμένα μεταξύ τους με το λευκό κενό. Σ’ αυτήν την περίπτωση, ο περιορισμός περιλαμβάνει ένα μοντέλο περιεχομένου, μια απλή γραμματική που ελέγχει τους επιτρεπτούς τύπους των στοιχείων παιδιών και την σειρά στην οποία επιτρέπονται να εμφανίζονται. Η γραμματική βασίζεται σε μόρια περιεχομένου(cps), τα οποία αποτελούνται από ονόματα , λίστες επιλογής των μορίων περιεχομένου ή λίστες αλληλουχίας των μορίων περιεχομένου.

Όπου κάθε Name είναι ο τύπος του στοιχείου που μπορεί να εμφανιστεί ως παιδί. Οποιοδήποτε μόριο περιεχομένου σε μια λίστα επιλογής μπορεί να εμφανιστεί στο περιεχόμενο στοιχείου στο μέρος όπου εμφανίζεται η λίστα επιλογής στην γραμματική. Τα μόρια περιεχομένου που υπάρχουν  σε μια λίστα αλληλουχίας εμφανίζονται στο περιεχόμενο στοιχείου στην θέση που δίνεται από τη λίστα. Ο προαιρετικός χαρακτήρας που ακολουθεί ένα όνομα ή μια λίστα καθορίζει πότε το στοιχείο ή τα μόρια περιεχομένου μπορούν να εμφανίζονται στη λίστα μια ή περισσότερες φορές (+), καμία ή περισσότερες (*), καμία ή μια φορά (?).Η απουσία τέτοιου τελεστή σημαίνει ότι το στοιχείο ή τα μόρια περιεχομένου πρέπει να εμφανίζονται ακριβώς μια φορά. Αυτή η συντακτική και η έννοια είναι παρόμοια με αυτά που χρησιμοποιούνται στην παραγωγή αυτής της προδιαγραφής.

 

Το περιεχόμενο ενός στοιχείου ταιριάζει στο περιεχόμενο μοντέλου μόνον εάν είναι δυνατόν να δημιουργηθεί ένας διάδρομος μέσω του περιεχομένου μοντέλου , που να υπακούει στην αλληλουχία, στην επιλογή στους επαναληπτικούς τελεστές και να ταιριάζουν σε κάθε στοιχείο στο περιεχόμενο σε αντίθεση με έναν τύπο στοιχείου στο περιεχόμενο μοντέλου. Επιστρέφει σφάλμα εάν το στοιχείο στο έγγραφο συμβεί να ταιριάζει περισσότερες από μια φορές στον τύπο στοιχείου στο περιεχόμενο μοντέλου.

 

Περιορισμός Valid: Proper Group/PE Nesting

Το κείμενο αντικατάστασης των παραμέτρων οντοτήτων πρέπει να φωλιάζεται κατάλληλα με παρενθετικά σύνολα. Αυτό σημαίνει ότι, οποιεσδήποτε παρενθέσεις ανοίγματος ή κλεισίματος σε μια choice, seg ή mixed κατασκευή που περιέχονται σε κείμενο αντικατάστασης για παραμέτρους οντοτήτων, και οι δυο πρέπει να περιέχονται στο ίδιο κείμενο αντικατάστασης. Εάν μια αναφορά μιας παραμέτρου οντότητας εμφανίζεται σε μια choice, seg ή mixed   κατασκευή το κείμενο αντικατάστασής του δεν πρέπει να είναι κενό και ούτε μπορεί να είναι σύνδεσμος ο πρώτος ή ο δεύτερος μη κενός χαρακτήρας του συνδέσμου αντικατάστασης.

 

Παραδείγματα μοντέλων των στοιχείων περιεχομένου:

 

<!ELEMENT spec (front, body, back?)>
<!ELEMENT div1 (head, (p | list | note)*, div2*)>
<!ELEMENT dictionary-body (%div.mix; | %dict.mix;)*>

  

3.2.2 Μικτό Περιεχόμενο (Mixed Content)

 Ένας τύπος στοιχείου έχει μικτό περιεχόμενο όταν τα στοιχεία αυτού του τύπου περιλαμβάνουν χαρακτήρες δεδομένων σε συνδυασμό με στοιχεία παιδιών. Σ’ αυτήν την περίπτωση, οι τύποι των στοιχείων παιδιών μπορεί να είναι περιορισμένοι αλλά όχι η διάταξή τους ή ο αριθμός των εμφανίσεών τους.
Όπου τα
names δίνουν τον τύπο των στοιχείων που μπορούν να εμφανίζονται ως παιδιά.

 

Περιορισμός Valid: Δεν υπάρχουν Διπλότυποι Τύποι.

Το ίδιο όνομα δεν μπορεί να εμφανίζεται περισσότερες από μια φορές σε μια μοναδική δήλωση μικτού περιεχομένου.

 Παραδείγματα δήλωσης μικτού περιεχομένου:

 

<!ELEMENT p (#PCDATA|a|ul|b|i|em)*>
<!ELEMENT p (#PCDATA | %font; | %phrase; | %special; | %form;)* >
<!ELEMENT b (#PCDATA)>

  

3.3 Δήλωση Λίστας Χαρακτηριστικών (Attribute-List Declarations)

 Τα χαρακτηριστικά συνδέουν τα ζεύγη ονόματος – τιμής με τα στοιχεία. Οι προδιαγραφές των χαρακτηριστικών εμφανίζονται μονάχα μέσα στα start-tags ή στα empty element tags; Οι δηλώσεις της  Λίστας Χαρακτηριστικών μπορούν να χρησιμοποιηθούν:

 

·        Για να καθορίσουν ένα σύνολο χαρακτηριστικών που αναφέρονται σε ένα δοσμένο τύπο στοιχείων.

·        Για να καθορίσουν περιορισμούς τύπων για αυτά τα χαρακτηριστικά.

·        Για να παρέχουν default τιμές στα χαρακτηριστικά.

 

Οι δηλώσεις της  Λίστας Χαρακτηριστικών καθορίζουν το όνομα, τον τύπο δεδομένων, και την default τιμή του καθενός χαρακτηριστικού που συνδέεται με έναν δοσμένο τύπο στοιχείων.

Το name στον κανόνα AttlistDecl είναι ο τύπος του στοιχείου. Εάν για έναν τύπο στοιχείων που δεν είναι δηλωμένος ο ίδιος δηλώσουμε κάποια χαρακτηριστικά, ο XML επεξεργαστής θα βγάλει μήνυμα προειδοποίησης αλλά όχι λάθους. Το name στον κανόνα AttDef είναι το όνομα του χαρακτηριστικού.

 

Εάν παρέχονται περισσότερα του ενός AttlistDecl για ένα δοσμένο τύπο στοιχείων, τα περιεχόμενα όλων αυτών συγχωνεύονται. Όταν δίνονται περισσότερες από μια ερμηνείες στο ίδιο χαρακτηριστικό ενός δοσμένου τύπου στοιχείων, η πρώτη δήλωση είναι δεσμεύσιμη και οι επόμενες αγνοούνται. Οι συγγραφείς του  DTD μπορεί να επιλέξουν να παρέχουν τουλάχιστον μια δήλωση λίστας χαρακτηριστικών για ένα δοσμένο τύπο στοιχείων, τουλάχιστον μια ερμηνεία χαρακτηριστικού για ένα δοσμένο χαρακτηριστικό ονόματος και τουλάχιστον μια ερμηνεία χαρακτηριστικού για κάθε δήλωση λίστας χαρακτηριστικών. Όταν περισσότερες από μια δηλώσεις λίστας χαρακτηριστικών παρέχονται για ένα δοσμένο τύπο στοιχείων ή όταν  περισσότερες από μια ερμηνείες χαρακτηριστικών παρέχονται σε ένα δοσμένο χαρακτηριστικό, ο XML επεξεργαστής εισάγει προειδοποίηση και όχι μήνυμα λάθους.

 

3.3.1 Τύποι Χαρακτηριστικών (Attribute Types)

 

Οι XML τύποι χαρακτηριστικών είναι τρεις:

1.      Ο τύπος string, ο οποίος μπορεί να πάρει ως τιμή οποιοδήποτε αληθινό string.

2.      Ένα σύνολο συμβολικών τύπων, οι οποίοι έχουν ποικίλους λεξιλογικούς και εννοιολογικούς περιορισμούς, τους εξής:

Περιορισμός Valid:ID

Οι τιμές των τύπων ID πρέπει να ταιριάζουν στο προϊόν name. Το name δεν πρέπει να εμφανίζεται περισσότερες από μια φορές στο XML έγγραφο ως τιμή αυτού του τύπου, π.χ. οι ID τιμές θα πρέπει να προσδιορίζουν τα στοιχεία που τις παράγουν.

 

Περιορισμός Valid: Ένα ID για κάθε τύπο στοιχείων

Κανένας τύπος στοιχείων δεν μπορεί να έχει περισσότερα από ένα καθορισμένα ID χαρακτηριστικά.

 

Περιορισμός Valid: ID Χαρακτηριστικό Μηδενικής Απόδοσης Τιμής

Ένα ID χαρακτηριστικό παίρνει ως default τιμές τις εξής: #implied / #required

 

Περιορισμός Valid: IDREF

Οι τιμές του τύπου IDREF πρέπει να ταιριάζουν στο προϊόν name, και οι τιμές του τύπου IDREFS πρέπει να ταιριάζουν στο προϊόν names. Κάθε name πρέπει να αντιστοιχεί στην αξία ενός ID χαρακτηριστικού σε κάποιο στοιχείο σε ένα XML έγγραφο, π.χ. οι τιμές IDREF θα πρέπει να αντιστοιχούν στην αξία κάποιων ID χαρακτηριστικών.

 

Περιορισμός Valid: Όνομα Οντότητας

Οι τιμές του τύπου ENTITY πρέπει να ταιριάζουν στο προϊόν name, και οι τιμές του τύπου ENTITIES πρέπει να ταιριάζουν στο προϊόν names. Κάθε name πρέπει να ταιριάζει με το όνομα μιας μη αναλυμένης οντότητας που δηλώνεται στο DTD.

 

Περιορισμός Valid: Σύμβολο Ονόματος

Οι τιμές του τύπου NMTOKEN πρέπει να ταιριάζουν στο προϊόν Nmtoken, και οι τιμές του τύπου NMTOKENS πρέπει να ταιριάζουν στο προϊόν Nmtokens.

 

3.      Οι αριθμημένοι τύποι

 

Τα αριθμημένα χαρακτηριστικά μπορούν να πάρουν μια τιμή από τη λίστα που παρέχεται στην δήλωση.

Το χαρακτηριστικό NOTATION προσδιορίζει ένα σχόλιο, δηλώνεται στο DTD με κοινούς προσδιοριστές για να χρησιμοποιείται στη μετάφραση του στοιχείου στο οποίο ανήκει το χαρακτηριστικό.

 

Περιορισμός Valid: Χαρακτηριστικά Σχολίου

Οι τιμές αυτού του τύπου θα πρέπει να ταιριάζουν σε ένα από τα ονόματα σχολίων που περιλαμβάνει η δήλωση: όλα τα ονόματα σχολίων στην δήλωση θα πρέπει να δηλωθούν.

 

Περιορισμός Valid: Απαρίθμηση

Οι τιμές αυτού του τύπου πρέπει να ταιριάζουν σε ένα από τα σύμβολα Nmtoken στην δήλωση.

 

Το ίδιο Nmtoken δεν θα συμβεί περισσότερες από μια φορές στον τύπο αριθμημένων χαρακτηριστικών ενός μοναδικού τύπου στοιχείου.

3.3.2 Χαρακτηριστικά Μηδενικής Τιμής

 

Μια δήλωση χαρακτηριστικών παρέχει πληροφορίες για το αν είναι απαραίτητη η παρουσία του χαρακτηριστικού, και αν όχι πώς αντιδρά ο XML επεξεργαστής αν δηλωμένα χαρακτηριστικά απουσιάζουν σε ένα κείμενο.

 

Σε μια δήλωση χαρακτηριστικών το #required σημαίνει ότι το χαρακτηριστικό πρέπει να παρέχεται πάντοτε ενώ το #implied ότι δεν παρέχεται καμία default τιμή. Αν η δήλωση δεν είναι ούτε #required ούτε #implied τότε η τιμή AttValue περιέχει την δηλωμένη default τιμή. Η λέξη-κλειδί #fixed δηλώνει ότι το χαρακτηριστικό πρέπει να έχει πάντοτε την default τιμή. Αν μια default τιμή είναι δηλωμένη, όταν ο XML επεξεργαστής αντιμετωπίζει ένα χαρακτηριστικό που έχει παραληφθεί, συμπεριφέρεται σαν να ήταν παρόν το χαρακτηριστικό με τη δηλωμένη default τιμή.

   

Περιορισμός Valid: Απαιτούμενο Χαρακτηριστικό

Αν η default δήλωση είναι η λέξη-κλειδί #required τότε το χαρακτηριστικό πρέπει να καθοριστεί για  όλα τα στοιχεία του τύπου στην δήλωση της λίστας χαρακτηριστικών.

 

Περιορισμός Valid: Νόμιμο χαρακτηριστικό Default

Η δηλωμένη default τιμή πρέπει να συναντήσει τους λεξιλογικούς περιορισμούς του δηλωμένου τύπου χαρακτηριστικών.

 

Περιορισμός Valid: Αμετάβλητη τιμή Default

Αν ένα χαρακτηριστικό έχει μια default τιμή δηλωμένη με τη λέξη-κλειδί #fixed, τα παραδείγματα αυτού του χαρακτηριστικού θα πρέπει να ταιριάζουν με την default τιμή.

 

Παραδείγματα της δήλωσης λίστας χαρακτηριστικών:

 

<!ATTLIST termdef
         id ID #REQUIRED
         name CDATA #IMPLIED>
<!ATTLIST list
         type (bullets|ordered|glossary) "ordered">
<!ATTLIST form
         method CDATA #FIXED "POST">

 

 

3.3.3 Κανονικοποίηση Απόδοσης Τιμής (Attribute-Value Normalization)

 

Πριν περαστεί η τιμή του χαρακτηριστικού στην εφαρμογή ή πριν ελεγχθεί για αξιοπιστία , ο XML επεξεργαστής πρέπει να την κανονικοποιήσει ως εξής:

 

·        Μια αναφορά χαρακτηριστικού παράγεται προσαρτώντας τον δηλωμένο χαρακτήρα στην τιμή του χαρακτηριστικού.

·        Μια αναφορά οντότητας παράγεται αν επεξεργάζεται περιοδικά το κείμενο αντικατάστασης της οντότητας.

·        Ένας λευκός χαρακτήρας (#x20, #xD, #xA, #x9) παράγεται προσαρτώντας το #x20 στην κανονικοποιημένη τιμή, εκτός από το γεγονός ότι μονάχα ένα #x20 προσαρτάται σε μια αλληλουχία “#xD, #xA” που είναι μέρος μιας εξωτερικής αναλυμένης οντότητας ή της αληθινής οντότητας μιας εσωτερικής αναλυμένης οντότητας.

·        Άλλοι χαρακτήρες παράγονται προσαρτώντας τους στην κανονικοποιημένη τιμή.

 

Αν η δηλωμένη τιμή δεν είναι CDATA, ο XML επεξεργαστής πρέπει να επεξεργαστεί μετέπειτα την κανονικοποιημένη τιμή του χαρακτηριστικού απορρίπτοντας οποιουσδήποτε κύριους και δευτερεύοντες χαρακτήρες κενού αντικαθιστώντας αλληλουχίες κενών χαρακτήρων με έναν μοναδικό κενό χαρακτήρα.

 

Τα χαρακτηριστικά για τα οποία δεν υπάρχει δήλωση πρέπει να συμπεριφέρονται από έναν μη έγκυρο αναλυτή ως δηλωμένα CDATA.

 

3.4 Υποθετικοί Τομείς (Conditional Sections)

Οι υποθετικοί τομείς είναι τμήματα της δήλωσης τύπου εγγράφου εξωτερικού υποσυνόλου τα οποία περιέχονται ή εξέρχονται από τη λογική δομή ενός DTD βασιζόμενου στη λέξη-κλειδί που τα καθορίζει.

Όπως τα εσωτερικά και τα εξωτερικά DTD υποσύνολα, ένας υποθετικός τομέας μπορεί να περιλαμβάνει μια ή περισσότερες ολοκληρωμένες δηλώσεις, σχόλια, οδηγίες επεξεργασίας αναμειγνυόμενα με το «λευκό κενό».

 

Αν η λέξη-κλειδί του υποθετικού τμήματος είναι INCLUDE, τότε τα περιεχόμενα του υποθετικού τμήματος είναι τμήμα του DTD. Αν η λέξη-κλειδί του υποθετικού τμήματος είναι IGNORE, τότε τα περιεχόμενα του υποθετικού τμήματος  δεν είναι τμήμα του DTD. Για αξιόπιστη ανάλυση, τα περιεχόμενα ακόμη και των πιο αγνοημένων υποθετικών τμημάτων πρέπει να μελετούνται έτσι ώστε να εντοπίζονται φωλιασμένοι υποθετικοί τομείς και να προσδιορίζεται το τέλος τους. Όταν υπάρχει ένας υποθετικός τομέας με τη λέξη-κλειδί INCLUDE μέσα σε ένα μεγαλύτερο υποθετικό τομέα με τη λέξη-κλειδί IGNORE, τόσο ο εξωτερικός όσο και ο εσωτερικός υποθετικός τομέας αγνοούνται.

 

Αν η λέξη-κλειδί ενός υποθετικού τομέα είναι μια αναφορά οντότητας παραμέτρων , αυτή πρέπει να αντικαθιστάται από το περιεχόμενό του πριν ο επεξεργαστής αποφασίσει αν περιλάβει ή αν αγνοήσει τον υποθετικό τομέα.

 

Ένα παράδειγμα:

 

<!ENTITY % draft 'INCLUDE' >
<!ENTITY % final 'IGNORE' >

<![%draft;[
<!ELEMENT book (comments*, title, body, supplements?)>
]]>
<![%final;[
<!ELEMENT book (title, body, supplements?)>
]]>