<!--  XDF.dtd - eXtensible Data Format - version 0.18
	Date: June 28, 2002
	XML lanaguage Document Type Definition (DTD).

	An XDF document contains arrays and data structures.  It  is
designed to be both an interchange format for scientific data 
and to be of archival quality.
Multidimensional tables and scalar or vector fields are represented
in a consistent way and become thoroughly self describing.
Axial information provides a full description of  the space in which 
each datum  resides.  This means that XDF provides a consistent way to 
hold spectra with their wavelength scales, images with coordinate axes, 
vector fields with unitDirection, data cubes in complicated 
spaces, tables with column headers, and series of tables
with cut-in-heads. 

-->
<!ENTITY nbsp "&#160;">
<!-- no-break space = non-breaking space,
                                  U+00A0 ISOnum> -->
<!ENTITY space "&#32;">
<!-- The following entities allow subfield/specialty keywords to be added
to the elements: XDF, structure, array, axis, and field.  Do not change here.
Rather create a subfieldML.dtd that overrides/reverses these and XDF_TYPE and
calls XDF.dtd by a parameter entity.  Yes, DTDs can have inheritance.  It is
a bit more restrictive than Schema, but that is not necessarily bad.
-->
<!ENTITY % INCLUDE_XDF_CHILDREN 'IGNORE'>
<!ENTITY % BASIC_XDF 'INCLUDE'>
<!ENTITY % INCLUDE_STRUCTURE_CHILDREN 'IGNORE'>
<!ENTITY % BASIC_STRUCTURE 'INCLUDE'>
<!ENTITY % INCLUDE_ARRAY_CHILDREN 'IGNORE'>
<!ENTITY % BASIC_ARRAY 'INCLUDE'>
<!ENTITY % INCLUDE_AXIS_CHILDREN 'IGNORE'>
<!ENTITY % BASIC_AXIS 'INCLUDE'>
<!ENTITY % INCLUDE_FIELD_CHILDREN 'IGNORE'>
<!ENTITY % BASIC_FIELD 'INCLUDE'>
<!--The attribute value XDF_TYPE is changed from "basic" if one is using the 
above *_CHILDREN to add more elements.  Some examples of these are  
"FITSML" and "CDFML" for converted FITS and CDF files-->
<!ENTITY % XDF_TYPE "basic">
<!--Here is the root element!-->
<![ %BASIC_XDF; [ 
<!ELEMENT  XDF ((structure | parameter | parameterGroup | array | note)+)>
]]>
<![ %INCLUDE_XDF_CHILDREN; [ 
<!ELEMENT  XDF ((structure | parameter | parameterGroup | array | note)+,%XDF_CHILDREN;)>
]]>
<!ATTLIST XDF
	name CDATA #IMPLIED
	description CDATA #IMPLIED
	type CDATA "%XDF_TYPE;"
>
<![ %BASIC_STRUCTURE; [ 
<!ELEMENT structure ((array|parameter|parameterGroup|note|structure)+)>
]]>
<![ %INCLUDE_STRUCTURE_CHILDREN; [ 
<!ELEMENT structure (%STRUCTURE_CHILDREN;,(array|parameter|parameterGroup|note|structure)+)>
]]>
<!ATTLIST structure
	name CDATA #IMPLIED
	description CDATA #IMPLIED
>
<!--Parameter holds individual or short lists of datum.  Usually these are 
ancillary information about the arrays of data; in other words,  they are 
metadata.  They have scope downward but not upward.  That is, their 
scope is the entire level in which they reside and down the hierarchy, 
unless/until  they are superceded at a lower level.  They are undefined at 
higher levels.  -->
<!ELEMENT parameter ((units | unitless), (value | valueList | valueGroup)+, note*)>
<!ATTLIST parameter
	name CDATA #IMPLIED
	description CDATA #IMPLIED
	paramId ID #IMPLIED
	paramIdRef IDREF #IMPLIED
	datatype (integer | float | exponential | string | url) #IMPLIED
>
<!--    The unit strings should be written out without abbreviations to
avoid ambiguity, unless system SI units 
(http://physics.nist.gov/cuu/Units/index.html) are used.  
When non SI are used, the singular form should be chosen.  units="unitless" 
means unitless, <units><unit></unit></units> means undefined or unknown. 
Units are multiplied together (divide by using power="-1").
Units can begin with a constant multiplier in float format (F) exponential 
(E) format. 
	  10^12 kg*m/s^2  is expressed as,
	<units system="SI" factor="1E12" > 
		<unit>kg</unit><unit>m</unit>
		<unit power="-2">s</unit>
	</units>
This element will be superseded in a future version by a system in which the units are mathematically handled followining to MathML methods.-->
<!--Conversion allows expressoin of an algorithm to be applied to the data.   One can string together a sequence of operations to be applied to the stored data values. Applications would have the ability to optionally apply this and to invert it when storing.-->
<!ELEMENT conversion (multiply | add | logarithmBase | exponent | takeAsExponent)>
<!--number to multiply the data value  (cx).-->
<!ELEMENT multiply (#PCDATA)>
<!--nujmber to add to data (a constant offse: x + c).-->
<!ELEMENT add (#PCDATA)>
<!--take the log with base set by value here log_c(x).-->
<!ELEMENT logarithmBase (#PCDATA)>
<!--take power with exponent set by value here (x^c).-->
<!ELEMENT exponent (#PCDATA)>
<!-- base of value here and take to power (c^x)-->
<!ELEMENT takeAsExponent (#PCDATA)>
<!ELEMENT units (unit+)>
<!ATTLIST units
	name CDATA #IMPLIED
	description CDATA #IMPLIED
>
<!ELEMENT unit (#PCDATA)>
<!ATTLIST unit
	power NMTOKEN #IMPLIED
	description CDATA #IMPLIED
>
<!ELEMENT unitless EMPTY>
<!ATTLIST unitless
	name CDATA #IMPLIED
	description CDATA #IMPLIED
	factor CDATA #IMPLIED
	offset CDATA #IMPLIED
>
<!--    For the 'value' of the parameter, the attribute special is used
	to set the data to infinity, negative infinity, noData.  The  element is left empty in these cases.
        A noData implies that the value is unknown. 
	When special is used the value element should be empty.
	The inequality is used to indicate that the parameter is not
	necessarily equal to the value, but is limited in some way by 
	this value.  The datatype of the value is set by the attribute, 
	therefore, when an inequality is used with datatype integer the 
	parameter is set to all integers satisfying the constraint.
	A new value for a parameter overrides the previous one
	A parameter can be constrained to a finite range:
		<parameter name="x"><value inequality="greaterThan">2</value>
		<value inequality="lessThan">12</value></parameter>

	In this schema, <anyelement anyelementIDRef="xx" /> means to
	copy the content of the referenced element to this point.
-->
<!ELEMENT value (#PCDATA)>
<!ATTLIST value
	valueId ID #IMPLIED
	valueRef IDREF #IMPLIED
	special (infinite | infiniteNegative | noData | notANumber | underflow | overflow) #IMPLIED
	inequality (lessThan | lessThanOrEqual | greaterThan | greaterThanOrEqual) #IMPLIED
	positiveErrorValue NMTOKEN #IMPLIED
	negativeErrorValue NMTOKEN #IMPLIED
>
<!--The indices of an axis, which run from 0 to size-1,  can optionally be given values that  more 
appropriately specify the coordinate values along the axis.  One can fill valueList with value elements 
or a delimited list of values.
-->
<!ELEMENT valueList (#PCDATA)>
<!ATTLIST valueList
	delimiter CDATA "&space;"
	valueListId ID #IMPLIED
	valueListIdRef IDREF #IMPLIED
	infiniteValue CDATA #IMPLIED
	infiniteNegativeValue CDATA #IMPLIED
	noDataValue CDATA #IMPLIED
	notANumberValue CDATA #IMPLIED
	underflowValue CDATA #IMPLIED
	overflowValue CDATA #IMPLIED
>
<!--One can fill valueList by algorithm.  For now, there is one such algorithm.  A polynomial with optional logarithm.
-->
<!ELEMENT valueListAlgorithm (polynomial)>
<!ATTLIST valueListAlgorithm
	valueListId ID #IMPLIED
	valueListIdRef IDREF #IMPLIED
>
<!--A polynomial evaluated at x=0,1,2....size-1.  The coefficients are inserted as a list with space char as 
delimiter  (c0 c1 c2 ...).  The number of coefficients is arbitrary.  For examples,
0 2 4 6   has size=4 polynomial = "0 2"
1 3 5 7 9 has size=5 polynomial="1 2"
1 2 5 10 17 26 has size=6 polynomial="1 0 1"
reverse, if true, would have x=size-1, size-2, ... 1,0.
The logarithm of the resulting series is taken if @logarithm is present.  The base of the logarithm is 
either 10 or e.-->
<!ELEMENT polynomial EMPTY>
<!ATTLIST polynomial
	size NMTOKEN #IMPLIED
	reverse (true | false) "false"
	logarithm (10 | natural) #IMPLIED
>
<!ELEMENT parameterGroup ((parameter | parameterGroup)+)>
<!ATTLIST parameterGroup
	name CDATA #IMPLIED
	description CDATA #IMPLIED
>
<!--  There are several ways to fill the valueList array:
	1) delimited valueList
	<valueList size="3">1.3 2.3 3.7</valueList>
	<valueList size="3" delimiter="|">M31|NGC1316|Milky Way</valueList>


	 2) Use built-in facilities
		<valueList size="601" start="0" step="2" />

	 Hopefully, in the future we will support scripts as well.
	[Note: If using Perl XML::DOM::Parser need KeepCDATA=1]
	-->
<!-- An array is a set of mixed native datatype data (strings
	or numbers) that are to be read into an N-dimensioned variable.  
	It is embedded in a coordinate space and therefore will have 
	axis information.  Only one fieldAxis is permitted otherwise one could 
	have conflicting data units.
	array/@appendTo will extend the axis referred to with the current
	array.  This makes it possible to assemble tiles of data that piece
	 together into a very large array.  It is necessary to use axis/@align
	 on each axis of the current array to properly assemble it.

-->
<![ %BASIC_ARRAY; [
<!ELEMENT array
( 	
	 (parameter | parameterGroup)*, 	
		(
			( 
				(fieldAxis,axis*,dataStyle)
				 |
				(fieldAxis,(rowAxis|colAxis)) 
			)
			 |
			(
				conversion?, (units|unitless), dataFormat,
				 	(
				 		(axis*,dataStyle)
				 		 |
						(colAxis,rowAxis?) 
						| 
						(rowAxis,colAxis?)
					)  
			)
		), 
	data, notes?
)
>
]]>
<![ %INCLUDE_ARRAY_CHILDREN; [
<!ELEMENT array
( 	
	%ARRAY_CHILDREN;, (parameter | parameterGroup)*, 	
		(
			( 
				(fieldAxis,axis*,dataStyle) 
				|
				(fieldAxis,(rowAxis|colAxis)) 
			) 
		|
			(
				conversion?, (units|unitless), dataFormat,
				 	(
				 		(axis*,dataStyle)
				 		 |
						(colAxis,rowAxis?) 
						| 
						(rowAxis,colAxis?)
					)  
			)
		), 
	data, notes?
)
>
]]>
<!ATTLIST array
	name CDATA #IMPLIED
	description CDATA #IMPLIED
	arrayId ID #IMPLIED
	appendTo IDREF #IMPLIED
	class (spatial | temporal) #IMPLIED
	infiniteValue CDATA #IMPLIED
	infiniteNegativeValue CDATA #IMPLIED
	noDataValue CDATA #IMPLIED
	notANumberValue CDATA #IMPLIED
	underflowValue CDATA #IMPLIED
	overflowValue CDATA #IMPLIED
	disabledValue CDATA #IMPLIED
>
<!--    Each dimension of an N-dimensional structure is introduced by
	an axis element.  The order is not important because the read element
	describes the layout of the data.
 	axis/valueList is a list of numbers or strings (space delimited with
	quotes where necessary) that describes one dimension of the array,
	as in, the wavelength scale of a spectrum, or distance along
	the width of an image.
	In curvilinear coordinates the axis can merely 
	reflect the index number in the array.  A
	more detailed description of the space coordinates can be accomplished
	by adding another dimension to a fieldAxis. Two dimensional data 
	would need two fieldAxis/field/@class="coordinate" maps.  
        axis/@align should refer to an axisId to indicate that these two axes 
        runs essentially along the same direction.  It is required
        to accomplish an array/@apppendTo.

-->
<!ENTITY % basicAxisChildren "conversion?,(units|unitless),dataFormat?, (valueListAlgorithm | valueList | valueGroup | value)*">
<![ %BASIC_AXIS; [ 
<!ENTITY % axisChildren "(%basicAxisChildren;)" >
]]>
<![ %INCLUDE_AXIS_CHILDREN; [ 
<!ENTITY % axisChildren "(%AXIS_CHILDREN;,%basicAxisChildren;)">
]]>
<!ELEMENT axis (%axisChildren;)>
<!ATTLIST axis
	name CDATA #IMPLIED
	description CDATA #IMPLIED
	axisId ID #REQUIRED
	axisIdRef IDREF #IMPLIED
	align IDREF #IMPLIED
	size CDATA #REQUIRED
>
<!ELEMENT colAxis (%axisChildren;)>
<!ATTLIST colAxis
	name CDATA #IMPLIED
	description CDATA #IMPLIED
	align IDREF #IMPLIED
	size CDATA #REQUIRED
>
<!ELEMENT rowAxis (%axisChildren;)>
<!ATTLIST rowAxis
	name CDATA #IMPLIED
	description CDATA #IMPLIED
	align IDREF #IMPLIED
	size CDATA #REQUIRED
>
<!-- a table or a set of tables can be formatted in XDF. In the same
	way that axis describes the value for each column in an image,  
	fieldAxis/field elements are used to describe each column in the 
	table.
	
	Another use for fieldAxis is to hold several images with 
	different data units. 

	A special field is field/@class="spatial" which is a pixel 
	mapping of a coordinate for all of the nonspatial slices in
	the array.  Generally, one spatial map for 
	each coordinate. Each map is of the same size as 
	the initial data.
-->
<!-- A vector field requires additional components  represented by a fieldAxis with unitDirection fields.  These  could be named "x-hat",
"y-hat", and "z-hat". When the direction is along one of the
 axes, the unitDirectionAxisIdRef attribute should refer to that axis.
A fieldAxis can also be used to hold complex number with the 
attribute complexComponent set to "imaginary" in one field and "real"
in another.  As you may have gathered, fieldAxis is a neat and  general
way to define n-tuples.
-->
<!ELEMENT fieldAxis ((field | fieldGroup)+)>
<!ATTLIST fieldAxis
	name CDATA #IMPLIED
	description CDATA #IMPLIED
	axisId ID #REQUIRED
	axisIdRef IDREF #IMPLIED
	size CDATA #REQUIRED
>
<![ %BASIC_FIELD; [ 
<!ELEMENT field (conversion?,(units|unitless), dataFormat, relation?, note*)>
]]>
<![ %INCLUDE_FIELD_CHILDREN; [ 
<!ELEMENT field (%FIELD_CHILDREN;,conversion?,(units|unitless), dataFormat, relation?, note*)>
]]>
<!ATTLIST field
	name CDATA #IMPLIED
	description CDATA #IMPLIED
	fieldId ID #IMPLIED
	fieldIdRef IDREF #IMPLIED
	class (spatial | temporal) #IMPLIED
	complexComponent (real | imaginary) #IMPLIED
	unitDirectionAxisRef IDREF #IMPLIED
	lessThanValue NMTOKEN #IMPLIED
	lessThanOrEqualValue NMTOKEN #IMPLIED
	greaterThanValue NMTOKEN #IMPLIED
	greaterThanOrEqualValue NMTOKEN #IMPLIED
	infiniteValue CDATA #IMPLIED
	infiniteNegativeValue CDATA #IMPLIED
	noDataValue CDATA #IMPLIED
	notANumberValue CDATA #IMPLIED
	underflowValue CDATA #IMPLIED
	overflowValue CDATA #IMPLIED
	disabledValue CDATA #IMPLIED
>
<!ELEMENT relation EMPTY>
<!ATTLIST relation
	description CDATA #IMPLIED
	fieldIdRefs IDREFS #REQUIRED
	role (precision | positiveError | negativeError | error | sensitivity | weight | reference | noteMark | quality) #REQUIRED
>
<!--  Each array can contain notes to individual datum.
-->
<!ELEMENT notes (locationOrder?, note+)>
<!ELEMENT locationOrder (index+)>
<!ELEMENT index EMPTY>
<!ATTLIST index
	axisIdRef IDREF #REQUIRED
>
<!ELEMENT note (#PCDATA)>
<!ATTLIST note
	mark CDATA #IMPLIED
	noteId ID #IMPLIED
	noteIdRef IDREF #IMPLIED
	location CDATA #IMPLIED
	href CDATA #IMPLIED
>
<!-- 
There are times when two or more of elements need to be logically
connected into a higher level object. 
This can be accomplished with the fieldGroup element.
For instance, two fields, say "longitude" and  "latitude"  may be
grouped together with name="position".	
-->
<!-- 	Relationships between fields in a fieldGroup can be expressed with 
	the field/relation element.  
	Measurements and their errors could be linked in this way. -->
<!ELEMENT fieldGroup ((field | fieldGroup)+)>
<!ATTLIST fieldGroup
	name CDATA #IMPLIED
	description CDATA #IMPLIED
	class (spatial | temporal) #IMPLIED
>
<!ELEMENT valueGroup ((value | valueList | valueListAlgorithm | valueGroup)+)>
<!ATTLIST valueGroup
	name CDATA #IMPLIED
	description CDATA #IMPLIED
>
<!-- dataFormat will have a series of text or binary format elements
	one for each element until the end of a record (at the terminator).
	Or, if there are no terminators, the set of formats are 
	repeated until the end of the data. 
-->
<!ELEMENT dataFormat (float | integer | string | binaryInteger | binaryFloat | arrayRef)>
<!-- 
The element float is used for text format of non-integer (floating point) 
numbers.  If exponential format is to be used, supply the width of the exponent
with the exponent attribute.  If the exponent attribute is set then all numbers
are expected to be read or written as E-format.  One can not mix E and F-format.
-->
<!ELEMENT float EMPTY>
<!ATTLIST float
	width NMTOKEN #REQUIRED
	precision NMTOKEN #REQUIRED
	exponent NMTOKEN #IMPLIED
>
<!ELEMENT integer EMPTY>
<!ATTLIST integer
	type (decimal | octal | hexadecimal) "decimal"
	width NMTOKEN #REQUIRED
	signed (yes | no) "yes"
>
<!ELEMENT string EMPTY>
<!ATTLIST string
	length NMTOKEN #REQUIRED
>
<!ELEMENT binaryInteger EMPTY>
<!ATTLIST binaryInteger
	signed (yes | no) "yes"
	bits NMTOKEN #REQUIRED
>
<!-- BinaryFloats will need to conform to the IEEE-754 standard.  
However, only real*4 and real*8 are universally accepted (real*10 and
real*16 are common but not everywhere).
1 bit is used for the sign and 8(11) bits for exponent.  
1.mantissa * 2^(exponent-bias) where the bias is 127(1023).
-->
<!ELEMENT binaryFloat EMPTY>
<!ATTLIST binaryFloat
	bits (32 | 64) #REQUIRED
>
<!ELEMENT arrayRef EMPTY>
<!ATTLIST arrayRef
	width CDATA #REQUIRED
>
<!ELEMENT dataStyle (fixedWidth | tagged | delimited)>
<!ATTLIST dataStyle
	encoding (ANSI | ISO-8859-1 | UTF-8 | UTF-16) "ISO-8859-1"
	endian (BigEndian | LittleEndian) #IMPLIED
	dataStyleId ID #IMPLIED
	dataStyleIdRef IDREF #IMPLIED
>
<!ELEMENT tagged (tagToAxis+)>
<!ELEMENT delimited (delimitedInstruction, for)>
<!ELEMENT delimitedInstruction (delimiter, recordTerminator)>
<!ELEMENT delimiter ((chars | newLine)*)>
<!ATTLIST delimiter
	repeatable (yes | no) "yes"
>
<!ELEMENT recordTerminator ((chars | newLine)*)>
<!--    for elements are instructions for reading in the data, 
	they refer to axis elements. The order 
	for filling up n-dimensional variables is indicated by the nesing
	with the most nested being the most rapidly moving index.  
	The format information and the data appear inside the most 
	nested read element.  
-->
<!ELEMENT for (for | doInstruction)>
<!ATTLIST for
	axisIdRef IDREF #REQUIRED
>
<!ELEMENT doInstruction EMPTY>
<!ELEMENT fixedWidth (fixedWidthInstruction, for)>
<!ELEMENT fixedWidthInstruction (repeat | readCell | skip)+>
<!-- repeatable attribute (above) means that one or more of the delimiter 
     may occur as a single delimiter.  Here, especially, one must use
     a noData-value to indicate null. -->
<!ELEMENT repeat ((readCell | skip | repeat)+)>
<!ATTLIST repeat
	count NMTOKEN #REQUIRED
>
<!ELEMENT readCell EMPTY>
<!--
	A skip is used to skip over superfluous characters
between data values and at the end of format statement
to skip over the new-Line character. The chars that are
skipped over are not kept nor are they checked to match
the chars/@value value.  If a particular character is desired 
on output, it may be specified using  the chars/@value or
newLine child elements.  The default skip is one char with output of a single space.
-->
<!ELEMENT skip ((chars | newLine)+)>
<!-- note: you cant put in a newline in any XML attribute (e.g. value for chars element). 
     Use 'newLine' child element to have the newLine character (correct for the
     platform) output.
-->
<!ELEMENT chars EMPTY>
<!ATTLIST chars
	value CDATA "&space;"
>
<!-- the 'logical' newline: may be CR or CRLF  or LF.-->
<!ELEMENT newLine EMPTY>
<!--  If the data is tagged, use tagToAxis to associate the tag with 
the particular axis.  For now, one is restricted to use d0...d7 for tagnames.
-->
<!ELEMENT tagToAxis EMPTY>
<!ATTLIST tagToAxis
	tag (d0 | d1 | d2 | d3 | d4 | d5 | d6 | d7) #REQUIRED
	axisIdRef IDREF #REQUIRED
>
<!-- The Data element is a very general container for data.
	It could be marked up with d0...dN for N+1 dimensional data.
	It can be float format, or delimited data.  If it is not tagged data
	it can begin with a <![CDATA[ and end with ]]>.  
	However, a data element may contain data elements
	within it.  For instance, an animation would be a set of frames
	and it may be convenient to bracket each frame with a data tag.
	These data tags are not needed to build the structure because the
	structure is prescribed by the axis element.  Nevertheless,
	an application can use the nested data tags to indicate exactly
	where a problem lies in the data and aid in editing.  
	Also, the application 
	can use parts of the structure as soon as it hits some closed
	data tags.  The parser can pass the images to the display applet
	rather than waiting for the entire data set to arrive.	Of course,
	external entities can be used, so that the data
	may resides in one or several separate physical files. 
  
	Note that data OUTSIDE the specified byte range of startByte to endByte
      	will be preserved by XDF (the rest is thrown away at read time). 
        If endByte is not specified, it is accepted to mean the last available byte
        (e.g. the default condition is to use ALL of the bytes in the data section).
-->
<!ELEMENT data (#PCDATA | data | d0 | row | column | dataURL)*>
<!ATTLIST data
	startByte NMTOKEN "0"
	endByte NMTOKEN #IMPLIED
	checksum NMTOKEN #IMPLIED
	encoding (uuencoded | base64) #IMPLIED
	compression (zip | gzip | bzip2 | compress) #IMPLIED
>
<!ELEMENT dataURL (#PCDATA) >
<!ATTLIST dataURL
	xlink:href CDATA #IMPLIED
	xlink:type (simple|extended|locator|arc) #IMPLIED
	xlink:show (new|embed|replace) #IMPLIED 
>
	
<!--The elements d0, d1 are a lot like tr,td  in HTML. 
The elements d2,d3,etc allow extension to higher dimensions.-->
<!ELEMENT d0 (#PCDATA | d1)*>
<!ELEMENT d1 (#PCDATA | d2)*>
<!ELEMENT d2 (#PCDATA | d3)*>
<!ELEMENT d3 (#PCDATA | d4)*>
<!ELEMENT d4 (#PCDATA | d5)*>
<!ELEMENT d5 (#PCDATA | d6)*>
<!ELEMENT d6 (#PCDATA | d7)*>
<!ELEMENT d7 (#PCDATA)>
<!-- these allow the user to specify space-delimited data for 
     row/column in  a 1 or 2-D table -->
<!ELEMENT row (#PCDATA | cell | cells)*>
<!ELEMENT column (#PCDATA | cell | cells)*>
<!ELEMENT cell (#PCDATA)>
<!ELEMENT cells (#PCDATA)>
<!-- End of XDF.dtd -->
