<?xml version="1.0" encoding="UTF-8"?>
<!--W3C Schema for VOTable  = Virtual Observatory Tabular Format
.Version 1.0 : 15-Apr-2002
.Version 1.09: 23-Jan-2004 Version 1.09
.Version 1.09: 30-Jan-2004 Version 1.091
.Version 1.09: 22-Mar-2004 Version 1.092
.Version 1.094: 02-Jun-2004 GROUP does not contain FIELD
.Version 1.1 :  10-Jun-2004 remove the complexContent
.Version 1.11: GL: 23-May-2006 remove most root elements, use name= type= iso ref= structure
.Version 1.11: GL: 29-Aug-2006 review and added comments (prefixed by GL) 
              before sending to Francois Ochsenbein
.Version 1.12: FO: Preliminary Version 1.2
.Version 1.18: FO: Tested (jax) version 1.2
.Version 1.19: FO: Completed INFO attributes
.Version 1.20: FO: Added xtype; content-role is less restrictive (May2009)
.Version 1.20a: FO: PR-20090710 Cosmetics.
.Version 1.20b: FO: INFO does not accept sub-elements (2009-09-29)
.Version 1.20c: FO: elementFormDefault="qualified" to stay compatible with 1.1
-->
<xs:schema 
   xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
   xmlns="http://www.ivoa.net/xml/VOTable/v1.2"
   targetNamespace="http://www.ivoa.net/xml/VOTable/v1.2" 
>
<xs:annotation><xs:documentation>
    VOTable1.2 is meant to serialize tabular documents in the
    context of Virtual Observatory applications. This schema
    corresponds to the VOTable document available from
    http://www.ivoa.net/Documents/latest/VOT.html
</xs:documentation></xs:annotation>

<!-- Here we define some interesting new datatypes:
     - anyTEXT   may have embedded XHTML (conforming HTML)
     - astroYear is an epoch in Besselian or Julian year, e.g. J2000
     - arrayDEF  specifies an array size e.g. 12x23x*
     - dataType  defines the acceptable datatypes
     - ucdType   defines the acceptable UCDs (UCD1+)
     - precType  defines the acceptable precisions
     - yesno     defines just the 2 alternatives
-->

<xs:complexType name="anyTEXT" mixed="true">
  <xs:sequence>
    <xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
  </xs:sequence>
</xs:complexType>

<xs:simpleType  name="astroYear">
  <xs:restriction base="xs:token">
    <xs:pattern  value="[JB]?[0-9]+([.][0-9]*)?"/>
  </xs:restriction>
</xs:simpleType>

<xs:simpleType  name="ucdType">
  <xs:restriction base="xs:token">
    <xs:annotation><xs:documentation>
      Accept UCD1+
      Accept also old UCD1 (but not / + %) including SIAP convention (with :)
    </xs:documentation></xs:annotation>
    <xs:pattern  value="[A-Za-z0-9_.:;\-]*"/><!-- UCD1 use also / + % -->
  </xs:restriction>
</xs:simpleType>

<xs:simpleType  name="arrayDEF">
  <xs:restriction base="xs:token">
    <xs:pattern  value="([0-9]+x)*[0-9]*[*]?(s\W)?"/>
  </xs:restriction>
</xs:simpleType>

<xs:simpleType  name="encodingType">
  <xs:restriction base="xs:NMTOKEN">
    <xs:enumeration value="gzip"/>
    <xs:enumeration value="base64"/>
    <xs:enumeration value="dynamic"/>
    <xs:enumeration value="none"/>
  </xs:restriction>
</xs:simpleType>

<xs:simpleType name="dataType">
  <xs:restriction base="xs:NMTOKEN">
    <xs:enumeration value="boolean"/>
    <xs:enumeration value="bit"/>
    <xs:enumeration value="unsignedByte"/>
    <xs:enumeration value="short"/>
    <xs:enumeration value="int"/>
    <xs:enumeration value="long"/>
    <xs:enumeration value="char"/>
    <xs:enumeration value="unicodeChar"/>
    <xs:enumeration value="float"/>
    <xs:enumeration value="double"/>
    <xs:enumeration value="floatComplex"/>
    <xs:enumeration value="doubleComplex"/>
  </xs:restriction>
</xs:simpleType>

<xs:simpleType name="precType">
  <xs:restriction base="xs:token">
    <xs:pattern value="[EF]?[1-9][0-9]*"/>
  </xs:restriction>
</xs:simpleType>

<xs:simpleType name="yesno">
  <xs:restriction base="xs:NMTOKEN">
    <xs:enumeration value="yes"/>
    <xs:enumeration value="no"/>
  </xs:restriction>
</xs:simpleType>

  <xs:complexType name="Min">
    <xs:attribute name="value" type="xs:string" use="required"/>
    <xs:attribute name="inclusive" type="yesno" default="yes"/>
  </xs:complexType>
  <xs:complexType name="Max">
    <xs:attribute name="value" type="xs:string" use="required"/>
    <xs:attribute name="inclusive" type="yesno" default="yes"/>
  </xs:complexType>
  <xs:complexType name="Option">
    <xs:sequence>
      <xs:element name="OPTION" type="Option" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="name" type="xs:token"/>
    <xs:attribute name="value" type="xs:string" use="required"/>
  </xs:complexType>
  
  <!-- VALUES expresses the values that can be taken by the data 
    in a column or by a parameter
  -->
  <xs:complexType name="Values">
    <xs:sequence>
      <xs:element name="MIN" type="Min" minOccurs="0"/>
      <xs:element name="MAX" type="Max" minOccurs="0"/>
      <xs:element name="OPTION" type="Option" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="ID" type="xs:ID"/>
    <xs:attribute name="type" default="legal">
      <xs:simpleType>
        <xs:restriction base="xs:NMTOKEN">
          <xs:enumeration value="legal"/>
          <xs:enumeration value="actual"/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
    <xs:attribute name="null" type="xs:token"/>
    <xs:attribute name="ref"  type="xs:IDREF"/>
    <!-- xs:attribute name="invalid" type="yesno" default="no"/ -->
  </xs:complexType>
  
  <!-- The LINK is a URL (href) or some other kind of reference (gref) -->
  <xs:complexType name="Link">
    <xs:annotation><xs:documentation> 
    content-role was previsouly restricted as: <![CDATA[
    <xs:attribute name="content-role">
      <xs:simpleType>
        <xs:restriction base="xs:NMTOKEN">
          <xs:enumeration value="query"/>
          <xs:enumeration value="hints"/>
          <xs:enumeration value="doc"/>
          <xs:enumeration value="location"/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>]]>; is now a name token.
    </xs:documentation></xs:annotation>
    <xs:attribute name="ID" type="xs:ID"/>
    <xs:attribute name="content-role" type="xs:NMTOKEN"/>
    <xs:attribute name="content-type" type="xs:NMTOKEN"/>
    <xs:attribute name="title" type="xs:string"/>
    <xs:attribute name="value" type="xs:string"/>
    <xs:attribute name="href" type="xs:anyURI"/>
    <xs:attribute name="gref" type="xs:token"/><!-- Deprecated in V1.1 -->
    <xs:attribute name="action" type="xs:anyURI"/>
  </xs:complexType>
  
<!-- INFO is defined in Version 1.2 as a PARAM of String type 
<xs:complexType name="Info">
  <xs:complexContent>
    <xs:restriction base="Param">
      <xs:attribute name="unit" fixed=""/>
      <xs:attribute name="datatype" fixed="char"/>
      <xs:attribute name="arraysize" fixed="*"/>
    </xs:restriction>
  </xs:complexContent>
</xs:complexType>
 -or- as a full definition:
<xs:complexType name="Info">
  <xs:sequence> 
  <xs:element name="DESCRIPTION" type="anyTEXT" minOccurs="0"/>
    <xs:element name="VALUES" type="Values" minOccurs="0"/>
    <xs:element name="LINK" type="Link" minOccurs="0" maxOccurs="unbounded"/> 
  </xs:sequence>
  <xs:attribute name="name" type="xs:token" use="required"/>
  <xs:attribute name="value" type="xs:string" use="required"/>
  <xs:attribute name="ID" type="xs:ID"/>
  <xs:attribute name="unit" type="xs:token"/>
  <xs:attribute name="xtype" type="xs:token"/>
  <xs:attribute name="ref" type="xs:IDREF"/>
  <xs:attribute name="ucd" type="ucdType"/>
  <xs:attribute name="utype" type="xs:string"/>
</xs:complexType>
-->
<!-- No sub-element is accepted in INFO for backward compatibility -->
<xs:complexType name="Info">
  <xs:simpleContent>
    <xs:extension base="xs:string">
      <xs:attribute name="ID" type="xs:ID"/>
      <xs:attribute name="name"  type="xs:token" use="required"/>
      <xs:attribute name="value" type="xs:string" use="required"/>
      <xs:attribute name="unit"  type="xs:token"/>
      <xs:attribute name="xtype" type="xs:token"/>
      <xs:attribute name="ref"   type="xs:IDREF"/>
      <xs:attribute name="ucd"   type="ucdType"/>
      <xs:attribute name="utype" type="xs:string"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>

<!-- Expresses the coordinate system we are using --><!-- Deprecated V1.2 -->
<xs:complexType name="CoordinateSystem">
  <xs:annotation><xs:documentation>
    Deprecated in Version 1.2
  </xs:documentation></xs:annotation>
  <xs:simpleContent>
    <xs:extension base="xs:string">
      <xs:attribute name="ID" type="xs:ID" use="required"/>
      <xs:attribute name="equinox" type="astroYear"/>
      <xs:attribute name="epoch" type="astroYear"/>
      <xs:attribute name="system" default="eq_FK5">
        <xs:simpleType>
          <xs:restriction base="xs:NMTOKEN">
            <xs:enumeration value="eq_FK4"/>
            <xs:enumeration value="eq_FK5"/>
            <xs:enumeration value="ICRS"/>
            <xs:enumeration value="ecl_FK4"/>
            <xs:enumeration value="ecl_FK5"/>
            <xs:enumeration value="galactic"/>
            <xs:enumeration value="supergalactic"/>
            <xs:enumeration value="xy"/>
            <xs:enumeration value="barycentric"/>
            <xs:enumeration value="geo_app"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>

<xs:complexType name="Definitions">
  <xs:annotation><xs:documentation>
    Deprecated in Version 1.1
  </xs:documentation></xs:annotation>
  <xs:choice minOccurs="0" maxOccurs="unbounded">
    <xs:element name="COOSYS" type="CoordinateSystem"/><!-- Deprecated in V1.2 -->
    <xs:element name="PARAM" type="Param"/>
  </xs:choice>
</xs:complexType>

<!-- FIELD is the definition of what is in a column of the table -->
<xs:complexType name="Field">
  <xs:sequence> <!-- minOccurs="0" maxOccurs="unbounded" -->
    <xs:element name="DESCRIPTION" type="anyTEXT" minOccurs="0"/>
    <xs:element name="VALUES" type="Values" minOccurs="0"/> <!-- maxOccurs="2" -->
    <xs:element name="LINK" type="Link" minOccurs="0" maxOccurs="unbounded"/>
  </xs:sequence>
  <xs:attribute name="ID" type="xs:ID"/>
  <xs:attribute name="unit" type="xs:token"/>
  <xs:attribute name="datatype" type="dataType" use="required"/>
  <xs:attribute name="precision" type="precType"/>
  <xs:attribute name="width" type="xs:positiveInteger"/>
  <xs:attribute name="xtype" type="xs:token"/>
  <xs:attribute name="ref" type="xs:IDREF"/>
  <xs:attribute name="name" type="xs:token" use="required"/>
  <xs:attribute name="ucd" type="ucdType"/>
  <xs:attribute name="utype" type="xs:string"/>
  <xs:attribute name="arraysize" type="xs:string"/>
    <!-- GL: is the next deprecated element remaining 
        (is not in PARAM, but will in new model be inherited) 
    -->
  <xs:attribute name="type">
    <!-- type is not in the Version 1.1, but is kept for
         backward compatibility purposes
    -->
    <xs:simpleType>
      <xs:restriction base="xs:NMTOKEN">
        <xs:enumeration value="hidden"/>
        <xs:enumeration value="no_query"/>
        <xs:enumeration value="trigger"/>
        <xs:enumeration value="location"/>
      </xs:restriction>
    </xs:simpleType>
  </xs:attribute>
</xs:complexType>


<!-- A PARAM is similar to a FIELD, but it also has a "value" attribute -->
<!--  GL: implemented here as a subtype as suggested we do in Kyoto. -->
<xs:complexType name="Param">
  <xs:complexContent>
    <xs:extension base="Field">
      <xs:attribute name="value" type="xs:string" use="required"/>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>


<!-- GROUP groups columns; may include descriptions, fields/params/groups -->
<xs:complexType name="Group">
  <xs:sequence>
    <xs:element name="DESCRIPTION" type="anyTEXT" minOccurs="0"/>
<!--  GL I guess I can understand the next choice element as one may (?) 
      really want to group fields and params and groups in a particular order.
-->    
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="FIELDref" type="FieldRef"/> 
      <xs:element name="PARAMref" type="ParamRef"/> 
      <xs:element name="PARAM" type="Param"/> 
      <xs:element name="GROUP" type="Group"/> 
      <!-- GL a GroupRef could remove recursion -->
    </xs:choice>
  </xs:sequence>
  <xs:attribute name="ID"   type="xs:ID"/>
  <xs:attribute name="name" type="xs:token"/>
  <xs:attribute name="ref"  type="xs:IDREF"/>
  <xs:attribute name="ucd"  type="ucdType"/>
  <xs:attribute name="utype" type="xs:string"/>
</xs:complexType>

<!-- FIELDref and PARAMref are references to FIELD or PARAM defined
     in the parent TABLE or RESOURCE -->
<!-- GL This can not be enforced in XML Schema, so why not IDREF in <Group> ?
     In particular if the UCD and utype attributes will NOT be added -->
<xs:complexType name="FieldRef">
  <xs:attribute name="ref" type="xs:IDREF" use="required"/>
  <xs:attribute name="ucd"  type="ucdType"/>
  <xs:attribute name="utype" type="xs:string"/>
</xs:complexType>

<xs:complexType name="ParamRef">
  <xs:attribute name="ref" type="xs:IDREF" use="required"/>
  <xs:attribute name="ucd"  type="ucdType"/>
  <xs:attribute name="utype" type="xs:string"/>
</xs:complexType>

<!-- DATA is the actual table data, in one of three formats -->
<!-- 
  GL in Kyoto we discussed the option of having the specific Data items 
  be subtypes of Data:
-->
<!-- 
<xs:complexType name="Data" abstract="true"/>

<xs:complexType name="TableData">
  <xs:complexContent>
    <xs:extension base="Data">
     ... etc
    </xs:extension>
  </xs:complexContent>
</xs:complexType>
 -->
<xs:complexType name="Data">
  <xs:annotation><xs:documentation>
    Added in Version 1.2: INFO for diagnostics
  </xs:documentation></xs:annotation>
  <xs:sequence>
    <xs:choice>
      <xs:element name="TABLEDATA" type="TableData"/>
      <xs:element name="BINARY" type="Binary"/>
      <xs:element name="FITS" type="FITS"/>
    </xs:choice>
    <xs:element name="INFO" type="Info" minOccurs="0" maxOccurs="unbounded"/>
  </xs:sequence>
</xs:complexType>

<!-- Pure XML data -->
<xs:complexType name="TableData">
  <xs:sequence>
    <xs:element name="TR" type="Tr" minOccurs="0" maxOccurs="unbounded"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="Td">
  <xs:simpleContent>
    <xs:extension base="xs:string">
      <!-- xs:attribute name="ref" type="xs:IDREF"/ -->
      <xs:annotation><xs:documentation>
          The 'encoding' attribute is added here to avoid
          problems of code generators which do not properly
          interpret the TR/TD structures.
          'encoding' was chosen because it appears in
          appendix A.5
      </xs:documentation></xs:annotation>
      <xs:attribute name="encoding" type="encodingType"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>

<xs:complexType name="Tr">
  <xs:annotation><xs:documentation>
    The ID attribute is added here to the TR tag to avoid 
    problems of code generators which do not properly 
    interpret the TR/TD structures
  </xs:documentation></xs:annotation>
  <xs:sequence>
    <xs:element name="TD" type="Td" maxOccurs="unbounded"/>
  </xs:sequence>
  <xs:attribute name="ID" type="xs:ID"/>
</xs:complexType>

<!-- FITS file, perhaps with specification of which extension to seek to -->
<xs:complexType name="FITS">
  <xs:sequence>
    <xs:element name="STREAM" type="Stream"/>
  </xs:sequence>
  <xs:attribute name="extnum" type="xs:positiveInteger"/>
</xs:complexType>

<!-- BINARY data format -->
<xs:complexType name="Binary">
  <xs:sequence>
    <xs:element name="STREAM" type="Stream"/>
  </xs:sequence>
</xs:complexType>

<!-- STREAM can be local or remote, encoded or not -->
<xs:complexType name="Stream">
  <xs:simpleContent>
    <xs:extension base="xs:string">
      <xs:attribute name="type" default="locator">
        <xs:simpleType>
          <xs:restriction base="xs:NMTOKEN">
            <xs:enumeration value="locator"/>
            <xs:enumeration value="other"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="href" type="xs:anyURI"/>
      <xs:attribute name="actuate" default="onRequest">
        <xs:simpleType>
          <xs:restriction base="xs:NMTOKEN">
            <xs:enumeration value="onLoad"/>
            <xs:enumeration value="onRequest"/>
            <xs:enumeration value="other"/>
            <xs:enumeration value="none"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="encoding" type="encodingType" default="none"/>
      <xs:attribute name="expires" type="xs:dateTime"/>
      <xs:attribute name="rights" type="xs:token"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>

<!-- A TABLE is a sequence of FIELD/PARAMs and LINKS and DESCRIPTION, 
     possibly followed by a DATA section 
-->
<xs:complexType name="Table">
  <xs:annotation><xs:documentation>
    Added in Version 1.2: INFO for diagnostics
  </xs:documentation></xs:annotation>
  <xs:sequence>
    <xs:element name="DESCRIPTION" type="anyTEXT" minOccurs="0"/>
<!-- GL: why a choice iso for example -->
<!-- 
      <xs:element name="PARAM" type="Param" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="FIELD" type="Field" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="GROUP" type="Group" minOccurs="0" maxOccurs="unbounded"/>
-->
<!-- 
  This could also enforce groups to be defined after the fields and params 
  to which they must have a reference, which is somewhat more logical
-->
    <!-- Added Version 1.2: -->
    <xs:element name="INFO" type="Info" minOccurs="0" maxOccurs="unbounded"/> 
    <!-- An empty table without any FIELD/PARAM should not be acceptable -->
    <xs:choice minOccurs="1" maxOccurs="unbounded"> 
      <xs:element name="FIELD" type="Field"/>
      <xs:element name="PARAM" type="Param"/>
      <xs:element name="GROUP" type="Group"/>
    </xs:choice>
    <xs:element name="LINK" type="Link" minOccurs="0" maxOccurs="unbounded"/>
    <!-- This would allow several DATA parts in a table (future extension?)
    <xs:sequence minOccurs="0" maxOccurs="unbounded">  
      <xs:element name="DATA" type="Data"/>
      <xs:element name="INFO" type="Info" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    -->
    <xs:element name="DATA" type="Data" minOccurs="0"/>
    <xs:element name="INFO" type="Info" minOccurs="0" maxOccurs="unbounded"/>
  </xs:sequence>
  <xs:attribute name="ID"   type="xs:ID"/>
  <xs:attribute name="name" type="xs:token"/>
  <xs:attribute name="ref"  type="xs:IDREF"/>
  <xs:attribute name="ucd"  type="ucdType"/>
  <xs:attribute name="utype" type="xs:string"/>
  <xs:attribute name="nrows" type="xs:nonNegativeInteger"/>
</xs:complexType>

<!-- RESOURCES can contain DESCRIPTION, (INFO|PARAM|COSYS), LINK, TABLEs -->
<xs:complexType name="Resource">
  <xs:annotation><xs:documentation>
     Added in Version 1.2: INFO for diagnostics in several places
  </xs:documentation></xs:annotation>
  <xs:sequence>
    <xs:element name="DESCRIPTION" type="anyTEXT" minOccurs="0"/>
    <xs:element name="INFO" type="Info" minOccurs="0" maxOccurs="unbounded"/>
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="COOSYS" type="CoordinateSystem"/><!-- Deprecated in V1.2 -->
      <xs:element name="GROUP" type="Group" />
      <xs:element name="PARAM" type="Param" />
    </xs:choice>
    <xs:sequence minOccurs="0" maxOccurs="unbounded">
      <xs:element name="LINK" type="Link" minOccurs="0" maxOccurs="unbounded"/>
      <xs:choice>
        <xs:element name="TABLE" type="Table" />
        <xs:element name="RESOURCE" type="Resource" />
      </xs:choice>
      <xs:element name="INFO" type="Info" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <!-- Suggested Doug Tody, to include new RESOURCE types -->
    <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
  </xs:sequence>
  <xs:attribute name="name" type="xs:token"/>
  <xs:attribute name="ID"   type="xs:ID"/>
  <xs:attribute name="utype" type="xs:string"/>
  <xs:attribute name="type" default="results">
    <xs:simpleType>
      <xs:restriction base="xs:NMTOKEN">
        <xs:enumeration value="results"/>
        <xs:enumeration value="meta"/>
      </xs:restriction>
    </xs:simpleType>
  </xs:attribute>
  <!-- Suggested Doug Tody, to include new RESOURCE attributes -->
  <xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:complexType>

<!-- VOTable is the root element -->
<xs:element name="VOTABLE">
<xs:complexType>
  <xs:sequence>
    <xs:element name="DESCRIPTION" type="anyTEXT" minOccurs="0"/>
    <xs:element name="DEFINITIONS" type="Definitions" minOccurs="0"/><!-- Deprecated -->
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="COOSYS" type="CoordinateSystem"/><!-- Deprecated in V1.2 -->
      <xs:element name="GROUP" type="Group" />
      <xs:element name="PARAM" type="Param" />
      <xs:element name="INFO" type="Info" minOccurs="0" maxOccurs="unbounded"/>
    </xs:choice>
    <xs:element name="RESOURCE" type="Resource" minOccurs="1" maxOccurs="unbounded"/>
    <xs:element name="INFO" type="Info" minOccurs="0" maxOccurs="unbounded"/>
  </xs:sequence>
  <xs:attribute name="ID" type="xs:ID"/>
  <xs:attribute name="version">
     <xs:simpleType>
       <xs:restriction base="xs:NMTOKEN">
         <xs:enumeration value="1.2"/>
       </xs:restriction>
     </xs:simpleType>
   </xs:attribute>
</xs:complexType>
</xs:element>

</xs:schema>
