# revised DTD for the RFC document series, draft of 2009-10-06

# Typical invocation:
#     <!DOCTYPE rfc PUBLIC "-//IETF//DTD RFC 2629//EN"
#                          "http://xml.resource.org/authoring/rfc2629.dtd" [
#       ... dtd subset ...
#     ]>
#   or
#     <!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
#       ... dtd subset ...
#     ]>

# Contents
# 
#   Character entities
# 
#   DTD data types
# 
#   The top-level
# 
#   Front matter
# 
#   The Body
# 
#   Back matter

# Character entities

# DTD data types:
# 
#       entity        description
#       ======        ===============================================
#       NUMBER        [0-9]+
#       NUMBERS       a comma-separated list of NUMBER
# 
#       DAY           the day of the month, e.g., "1"
#       MONTH         the month of the year, e.g., "January"
#       YEAR          a four-digit year, e.g., "1999"
# 
#       URI           e.g., "http://invisible.net/"
# 
#       ATEXT/CTEXT   printable ASCII text (no line-terminators)
# 
#       TEXT          character data

namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"

NUMBER = string
NUMBERS = string
DAY = string
MONTH = string
YEAR = string
URI = string
ATEXT = string
CTEXT = text
TEXT = text
# The top-level

# attributes for the "rfc" element are supplied by the RFC
# editor. when preparing drafts, authors should leave them blank.
# 
# the "seriesNo" attribute is used if the category is, e.g., BCP.
rfc = element rfc { attlist.rfc, front, middle, back? }
attlist.rfc &=
  attribute number { NUMBER }?,
  [ a:defaultValue = "" ] attribute obsoletes { NUMBERS }?,
  [ a:defaultValue = "" ] attribute updates { NUMBERS }?,
  attribute category { "std" | "bcp" | "info" | "exp" | "historic" }?,
  attribute consensus { "no" | "yes" }?,
  attribute seriesNo { NUMBER }?,
  attribute ipr {
    "full2026"
    | "noDerivativeWorks2026"
    | "none"
    | "full3667"
    | "noModification3667"
    | "noDerivatives3667"
    | "full3978"
    | "noModification3978"
    | "noDerivatives3978"
    | "trust200811"
    | "noModificationTrust200811"
    | "noDerivativesTrust200811"
    | "trust200902"
    | "noModificationTrust200902"
    | "noDerivativesTrust200902"
    | "pre5378Trust200902"
  }?,
  attribute iprExtract { xsd:IDREF }?,
  [ a:defaultValue = "IETF" ]
  attribute submissionType { "IETF" | "IAB" | "IRTF" | "independent" }?,
  attribute docName { ATEXT }?,
  [ a:defaultValue = "en" ] attribute xml:lang { ATEXT }?
# Front matter
front =
  element front {
    attlist.front,
    title,
    author+,
    date,
    area*,
    workgroup*,
    keyword*,
    abstract?,
    note*
  }
attlist.front &= empty
# the "abbrev" attribute is used for headers, etc.
title = element title { attlist.title, CTEXT }
attlist.title &= attribute abbrev { ATEXT }?
author = element author { attlist.author, organization?, address? }
attlist.author &=
  attribute initials { ATEXT }?,
  attribute surname { ATEXT }?,
  attribute fullname { ATEXT }?,
  attribute role { "editor" }?
organization = element organization { attlist.organization, CTEXT }
attlist.organization &= attribute abbrev { ATEXT }?
address =
  element address {
    attlist.address, postal?, phone?, facsimile?, email?, uri?
  }
attlist.address &= empty
# this content model should be more strict:
# at most one of each the city, region, code, and country
# elements may be present
postal =
  element postal {
    attlist.postal, street+, (city | region | code | country)*
  }
attlist.postal &= empty
street = element street { attlist.street, CTEXT }
attlist.street &= empty
city = element city { attlist.city, CTEXT }
attlist.city &= empty
region = element region { attlist.region, CTEXT }
attlist.region &= empty
code = element code { attlist.code, CTEXT }
attlist.code &= empty
country = element country { attlist.country, CTEXT }
attlist.country &= empty
phone = element phone { attlist.phone, CTEXT }
attlist.phone &= empty
facsimile = element facsimile { attlist.facsimile, CTEXT }
attlist.facsimile &= empty
email = element email { attlist.email, CTEXT }
attlist.email &= empty
uri = element uri { attlist.uri, CTEXT }
attlist.uri &= empty
date = element date { attlist.date, empty }
attlist.date &=
  attribute day { DAY }?,
  attribute month { MONTH }?,
  attribute year { YEAR }?
# meta-data...
area = element area { attlist.area, CTEXT }
attlist.area &= empty
workgroup = element workgroup { attlist.workgroup, CTEXT }
attlist.workgroup &= empty
keyword = element keyword { attlist.keyword, CTEXT }
attlist.keyword &= empty
abstract = element abstract { attlist.abstract, t+ }
attlist.abstract &= empty
note = element note { attlist.note, t+ }
attlist.note &= attribute title { ATEXT }
# The body
middle = element middle { attlist.middle, section+ }
attlist.middle &= empty
section =
  element section {
    attlist.section, (t | figure | texttable | iref)*, section*
  }
attlist.section &=
  attribute anchor { xsd:ID }?,
  attribute title { ATEXT },
  [ a:defaultValue = "default" ]
  attribute toc { "include" | "exclude" | "default" }?
# use of <appendix/> is deprecated...
# <!ELEMENT appendix    ((t|figure|texttable|iref)*,appendix*)>
# <!ATTLIST appendix
#           anchor      ID                 #IMPLIED
#           title       %ATEXT;            #REQUIRED
#           toc         (include|exclude|default)
#                                          "default">

# use of <figure/> is deprecated...
t =
  element t {
    attlist.t,
    (TEXT
     | \list
     | figure
     | xref
     | eref
     | iref
     | cref
     | spanx
     | vspace)*
  }
attlist.t &=
  attribute anchor { xsd:ID }?,
  attribute hangText { ATEXT }?
# the value of the style attribute is inherited from the closest 
# parent
\list = element list { attlist.list, t+ }
attlist.list &=
  attribute style { ATEXT }?,
  attribute hangIndent { NUMBER }?,
  attribute counter { ATEXT }?
xref = element xref { attlist.xref, CTEXT }
attlist.xref &=
  attribute target { xsd:IDREF },
  [ a:defaultValue = "false" ] attribute pageno { "true" | "false" }?,
  [ a:defaultValue = "default" ]
  attribute format { "counter" | "title" | "none" | "default" }?
eref = element eref { attlist.eref, CTEXT }
attlist.eref &= attribute target { URI }
iref = element iref { attlist.iref, empty }
attlist.iref &=
  attribute item { ATEXT },
  [ a:defaultValue = "" ] attribute subitem { ATEXT }?,
  [ a:defaultValue = "false" ] attribute primary { "true" | "false" }?
cref = element cref { attlist.cref, CTEXT }
attlist.cref &=
  attribute anchor { xsd:ID }?,
  attribute source { ATEXT }?
spanx = element spanx { attlist.spanx, CTEXT }
attlist.spanx &=
  [ a:defaultValue = "preserve" ]
  attribute xml:space { "default" | "preserve" }?,
  [ a:defaultValue = "emph" ] attribute style { ATEXT }?
vspace = element vspace { attlist.vspace, empty }
attlist.vspace &=
  [ a:defaultValue = "0" ] attribute blankLines { NUMBER }?
figure =
  element figure {
    attlist.figure, iref*, preamble?, artwork, postamble?
  }
attlist.figure &=
  attribute anchor { xsd:ID }?,
  [ a:defaultValue = "" ] attribute title { ATEXT }?,
  [ a:defaultValue = "false" ]
  attribute suppress-title { "true" | "false" }?,
  attribute src { URI }?,
  [ a:defaultValue = "left" ]
  attribute align { "left" | "center" | "right" }?,
  [ a:defaultValue = "" ] attribute alt { ATEXT }?,
  [ a:defaultValue = "" ] attribute width { ATEXT }?,
  [ a:defaultValue = "" ] attribute height { ATEXT }?
preamble =
  element preamble {
    attlist.preamble, (TEXT | xref | eref | iref | cref | spanx)*
  }
attlist.preamble &= empty
artwork = element artwork { attlist.artwork, TEXT* }
attlist.artwork &=
  [ a:defaultValue = "preserve" ]
  attribute xml:space { "default" | "preserve" }?,
  [ a:defaultValue = "" ] attribute name { ATEXT }?,
  [ a:defaultValue = "" ] attribute type { ATEXT }?,
  attribute src { URI }?,
  [ a:defaultValue = "left" ]
  attribute align { "left" | "center" | "right" }?,
  [ a:defaultValue = "" ] attribute alt { ATEXT }?,
  [ a:defaultValue = "" ] attribute width { ATEXT }?,
  [ a:defaultValue = "" ] attribute height { ATEXT }?
postamble =
  element postamble {
    attlist.postamble, (TEXT | xref | eref | iref | cref | spanx)*
  }
attlist.postamble &= empty
texttable =
  element texttable {
    attlist.texttable, preamble?, ttcol+, c*, postamble?
  }
attlist.texttable &=
  attribute anchor { xsd:ID }?,
  [ a:defaultValue = "" ] attribute title { ATEXT }?,
  [ a:defaultValue = "false" ]
  attribute suppress-title { "true" | "false" }?,
  [ a:defaultValue = "center" ]
  attribute align { "left" | "center" | "right" }?,
  [ a:defaultValue = "full" ]
  attribute style { "all" | "none" | "headers" | "full" }?
ttcol = element ttcol { attlist.ttcol, CTEXT }
attlist.ttcol &=
  attribute width { ATEXT }?,
  [ a:defaultValue = "left" ]
  attribute align { "left" | "center" | "right" }?
c = element c { attlist.c, (TEXT | xref | eref | iref | cref | spanx)* }
attlist.c &= empty
# Back matter

# sections, if present, are appendices
back = element back { attlist.back, references*, section* }
attlist.back &= empty
references = element references { attlist.references, reference+ }
attlist.references &=
  [ a:defaultValue = "References" ] attribute title { ATEXT }?
reference =
  element reference {
    attlist.reference, front, seriesInfo*, format*, annotation*
  }
attlist.reference &=
  attribute anchor { xsd:ID }?,
  attribute target { URI }?
seriesInfo = element seriesInfo { attlist.seriesInfo, empty }
attlist.seriesInfo &=
  attribute name { ATEXT },
  attribute value { ATEXT }
format = element format { attlist.format, empty }
attlist.format &=
  attribute target { URI }?,
  attribute type { ATEXT },
  attribute octets { NUMBER }?
annotation =
  element annotation {
    attlist.annotation, (TEXT | xref | eref | iref | cref | spanx)*
  }
attlist.annotation &= empty
start = rfc
