<!--

  A DTD for Dan's Kinda Hacky XML Validation Format (DKHXVF)
  
  Basically, this format allows us to enforce some additional rules
  that DTD's do not.  Specifically, we can:
  
  - specify min and max for number of each child element
  - specify a regular expression that text elements and attributes must match
  - specify type of text elements and attributes (int, float, string, timestamp)
  - specify min and max for any type.  (length compare for strings, numeric otherwise)

  The hope is that this will allow the rapid creation of new formats, and modification
  of existing formats (adding/removing tags, attributes etc), without requiring
  code changes in the validation software.
  
  This is not in any way intended to be an alternative to XML schemas.  In the
  absence of code supporting XML schemas, I created this, but it is meant as
  a transitional work only.
  
  For more on XML schemas, see:
  http://www.w3.org/1999/05/06-xmlschema-1/ and
  http://www.w3.org/1999/05/06-xmlschema-2/
  
  This is also not meant to replace DTDs.  There are many things that you can do
  with DTDs that you cannot do with this format.  For example, you cannot declare
  entities with this format.  You must do that in the DTD.  If you want your
  parser to interpret them correctly, you must use a validating parser.
  
  It is possible to use these schemas without DTD validation, however you may run
  into problems with entity expansion and other things.

  Dan Libby - danda@netscape.com
  $Log: schema-1.0.dtd,v $
  Revision 1.2  2001/04/26 03:02:34  eedrin
  commiting my to channel chgs

  Revision 1.1.1.1  2001/03/03 22:27:15  rdist
  Initial Migration Import

  Revision 1.1  1999/07/25 07:59:32  danda
  DTDs for RSS

  Revision 1.2  1999/07/22 07:17:03  danda
  fixing spacing

  Revision 1.1  1999/06/09 07:01:29  danda
  adding schema and dtd for rss 0.9 and 1.0

  
-->

<!-- 
Tag: Schema
Description: Document wrapper.  
Sub tags: Element & Attribute
Attributes: version, root, name
Notes: 
 version must be "DKHXVF 1.0"
 root is the document root.
-->
<!ELEMENT Schema (Element | Attribute)*>
<!ATTLIST Schema
          version   CDATA    #FIXED "DKHXVF 1.0"
          root      CDATA    #REQUIRED
          name      CDATA    #REQUIRED>

<!-- 
Tag: Element
Description: Definition of an allowed element (tag)  
Sub tags: Contains, Attrib, Matches
Attributes: id, type, min, max, exactly
Notes: exactly="1" is equivalent to min="1" max="1"
-->
<!ELEMENT Element ((Contains | Attrib)* | Matches?)>
<!ATTLIST Element
          id        CDATA    #REQUIRED
          type      (int | float | container | string | timestamp)    #REQUIRED
          min       CDATA    #IMPLIED
          max       CDATA    #IMPLIED
          exactly   CDATA    #IMPLIED>

<!-- 
Tag: Contains
Description: Defines rules for a sub-element.  
Sub tags: None, this tag must be empty.
Attributes: ref, min, max, exactly
Notes: ref must refer to the 'id' of an element defined elsewhere or the schema
is invalid.
-->
<!ELEMENT Contains EMPTY>
<!ATTLIST Contains
          ref       CDATA    #REQUIRED
          min       CDATA    #IMPLIED
          max       CDATA    #IMPLIED
          exactly   CDATA    #IMPLIED>

<!-- 
Tag: Attrib
Description: Defines rules for an element attribute.  
Sub tags: None, this tag must be empty
Attributes: ref, min, max, exactly
Notes: ref must refer to the 'id' of an Attribute defined elsewhere or the schema
is invalid.
-->
<!ELEMENT Attrib EMPTY>
<!ATTLIST Attrib
          ref      CDATA     #REQUIRED
          min      CDATA     #IMPLIED
          max      CDATA     #IMPLIED
          exactly  CDATA     #IMPLIED>

<!-- 
Tag: Attribute
Description: Definition of an allowed attribute  
Sub tags: Matches
Attributes: id, type, min, max, exactly
Notes: none
-->
<!ELEMENT Attribute (Matches?)>
<!ATTLIST Attribute
          id        CDATA    #REQUIRED
          type      (int | float | string | timestamp)    #REQUIRED
          min       CDATA    #IMPLIED
          max       CDATA    #IMPLIED
          exactly   CDATA    #IMPLIED>

<!-- 
Tag: Matches
Description: A regular expression that values will be compared against
Sub tags: None
Attributes: None
Notes: Matches may be used for elements of any type but container, and for attributes.

An example of a useful matching pattern is:

<Matches>^(foo|bar|foobar)$</Matches>

This will allow any values that exactly match "foo", "bar", or "foobar".

Whitespace is allowed in the regex and '#' is used for comments.  The following
is valid:

<Matches>
&amp;#                      # Start of a numeric entity reference, xml escaped &
(?P&lt;char&gt;             # xml escaped <, >
[0-9]+[^0-9]                # Decimal form
| 0[0-7]+[^0-7]             # Octal form
| x[0-9a-fA-F]+[^0-9a-fA-F] # Hexadecimal form
)
</Matches>

which is equivalent to:

<Matches>&amp;#(?P&lt;char&gt;[0-9]+[^0-9]| 0[0-7]+[^0-7]| x[0-9a-fA-F]+[^0-9a-fA-F])</Matches>

For help on regular expressions, see:
http://www.python.org/doc/howto/regex/regex.html or
http://www.ciser.cornell.edu/info/regex.html
-->
<!ELEMENT Matches (#PCDATA)>


<!--
Example of a DKHXVF 1.0 file:

<?xml version="1.0"?>
<!DOCTYPE Schema PUBLIC "-//Netscape Communications//DTD Schema 1.0//EN" "http://channel.netscape.com/publish/formats/schema-1.0.dtd">

<Schema version="DKHXVF 1.0" root="rdf:RDF" name="RSS 0.9">
   <Element id="rdf:RDF" type="container">
      <Contains ref="channel" exactly="1"/>
      <Contains ref="image" min="0" max="1"/>
      <Contains ref="item" min="1" max="15"/>
      <Contains ref="textinput" min="0" max="1"/>
      <Attrib ref="xmlns" exactly="1"/>
      <Attrib ref="xmlns:rdf" exactly="1"/>
   </Element>
   
   <Attribute id="xmlns" type="string">
      <Matches>http://channel.netscape.com/rdf/simple/0.9/</Matches>
   </Attribute>
   
   <Attribute id="xmlns:rdf" type="string">
      <Matches>http://www.w3.org/1999/02/22-rdf-syntax-ns#</Matches>
   </Attribute>
   
   <Element id="channel" type="container">
      <Contains ref="link" exactly="1"/>
      <Contains ref="title" exactly="1"/>
      <Contains ref="description" exactly="1"/>
   </Element>
   
   <Element id="item" type="container">
      <Contains ref="title" exactly="1"/>
      <Contains ref="link" exactly="1"/>
   </Element>
   
   <Element id="image" type="container">
      <Contains ref="title" exactly="1"/>
      <Contains ref="link" exactly="1" />
      <Contains ref="url" exactly="1"/>
   </Element>
   
   <Element id="textinput" type="container">
      <Contains ref="title" exactly="1"/>
      <Contains ref="description" exactly="1"/>
      <Contains ref="link" exactly="1"/>
      <Contains ref="name" exactly="1"/>
   </Element>
   
   <Element id="title" type="string" min="1" max="100"/>
   <Element id="description" type="string" min="1" max="500"/>
   
   <Element id="url" type="string" min="1" max="500">
      <Matches>^(http://|^ftp://)</Matches>
   </Element>

   <Element id="link" type="string" min="1" max="500">
      <Matches>^(http://|^ftp://)</Matches>
   </Element>
   
   <Element id="name" type="string" min="1" max="20"/>

</Schema>

-->

