<?xml encoding="UTF-8"?>
<!--
SPDX-FileCopyrightText: 2024, 2025 Lady <https://www.ladys.computer/about/#lady>
SPDX-License-Identifier: CC0-1.0
-->

<!-- Text Markup -->
<!ENTITY % blocks '(list|p|table)+'>
<!ENTITY % inlines 'code|em|ptr|ref|resource|strong|value'>
<!ELEMENT p (#PCDATA|%inlines;|note)*>
<!ELEMENT code (#PCDATA)>
<!ELEMENT em (#PCDATA)>
<!ELEMENT strong (#PCDATA)>

<!-- Notes -->
<!ELEMENT note (%blocks;)>
<!ATTLIST note
	n CDATA #REQUIRED
>

<!-- Links -->
<!ELEMENT ptr EMPTY>
<!ATTLIST ptr
	target CDATA #REQUIRED
	type (class|property|individual) #IMPLIED
>
<!ELEMENT ref (#PCDATA)>
<!ATTLIST ref
	target CDATA #REQUIRED
	type (class|property|individual) #IMPLIED
>

<!-- Tables -->
<!ELEMENT table (row)+>
<!ELEMENT row (cell)+>
<!ATTLIST row
	role (label|data) "data"
>
<!ELEMENT cell (#PCDATA|%inlines;)*>
<!ATTLIST cell
	role (label|data) "data"
>

<!-- Lists -->
<!ELEMENT list (item)*>
<!ATTLIST list
	rend (bulleted|numbered) "bulleted"
>
<!ELEMENT item (%blocks;)>

<!-- Anno -->
<!ELEMENT SpecificResource EMPTY><!-- this actually becomes anno:ResourceSelection, not anno:SpecificResource, but changing the name to match would require editing a lot of files -->
<!ATTLIST SpecificResource
  source CDATA #REQUIRED
  fragment CDATA #IMPLIED
>

<!-- Skos -->
<!ELEMENT inScheme (resource)>

<!-- Shacl -->
<!ELEMENT declare (prefix,namespace)>
<!ELEMENT namespace (#PCDATA)>
<!ELEMENT prefix (#PCDATA)>

<!-- Annotations -->
<!ENTITY % annotations '(label*,comment*,isDefinedBy*)'>
<!ELEMENT comment (%blocks;)>
<!ATTLIST comment
	xml:lang NMTOKEN #REQUIRED
>
<!ELEMENT isDefinedBy (resource|SpecificResource)>
<!ELEMENT label (#PCDATA)>
<!ATTLIST label
	xml:lang NMTOKEN #REQUIRED
>

<!-- Helper Elements -->
<!ELEMENT resource (#PCDATA)>
<!ATTLIST resource
	name CDATA #REQUIRED
>
<!ELEMENT value (#PCDATA)>
<!ATTLIST value
	datatype CDATA #IMPLIED
	xml:lang NMTOKEN #IMPLIED
>

<!-- Axioms -->
<!ELEMENT allValuesFrom (Class|Datatype|Restriction|resource)>
<!ELEMENT assertionProperty (resource)>
<!ELEMENT cardinality (#PCDATA)>
<!ELEMENT complementOf (Class|Restriction|resource)>
<!ELEMENT datatypeComplementOf (Datatype|resource)>
<!ELEMENT differentFrom (resource)>
<!ELEMENT disjointUnionOf (Class|Restriction|resource)+>
<!ELEMENT disjointWith (Class|Datatype|Restriction|resource)>
<!ELEMENT domain (Class|Restriction|resource)>
<!ELEMENT equivalentClass (Class|Datatype|Restriction|resource)>
<!ELEMENT equivalentProperty (DatatypeProperty|ObjectProperty|resource)>
<!ELEMENT hasKey (DatatypeProperty|ObjectProperty|resource)+>
<!ELEMENT hasSelf EMPTY>
<!ELEMENT hasValue (resource|value)>
<!ELEMENT intersectionOf (Class|Datatype|Restriction|resource)+>
<!ELEMENT inverseOf (Class|Datatype|Restriction|resource)>
<!ELEMENT maxCardinality (#PCDATA)>
<!ELEMENT maxQualifiedCardinality (#PCDATA)>
<!ELEMENT members (Class|Restriction|resource)+>
<!ELEMENT minCardinality (#PCDATA)>
<!ELEMENT minQualifiedCardinality (#PCDATA)>
<!ELEMENT onClass (Class|Restriction|resource)>
<!ELEMENT onDataRange (Datatype|resource)>
<!ELEMENT onDatatype (resource)>
<!ELEMENT onProperty (ObjectProperty|DatatypeProperty|resource)>
<!ELEMENT oneOf (Class|Datatype|Restriction|resource)+>
<!ELEMENT propertyChainAxiom (ObjectProperty|resource)+>
<!ELEMENT propertyDisjointWith (DatatypeProperty|ObjectProperty|resource)>
<!ELEMENT qualifiedCardinality (#PCDATA)>
<!ELEMENT range (Class|Datatype|Restriction|resource)>
<!ELEMENT sameAs (resource)>
<!ELEMENT someValuesFrom (Class|Datatype|Restriction|resource)>
<!ELEMENT sourceIndividual (resource)>
<!ELEMENT subClassOf (Class|Restriction|resource)>
<!ELEMENT subPropertyOf (DatatypeProperty|ObjectProperty|resource)>
<!ELEMENT superClassOf (Class|Restriction)> <!-- inverse subClassOf; only use for anonymous subclasses -->
<!ELEMENT targetIndividual (resource)>
<!ELEMENT type (Class|Restriction|resource)>
<!ELEMENT unionOf (Class|Datatype|Restriction|resource)+>
<!ELEMENT withRestrictions (langRange|length|maxExclusive|maxInclusive|maxLength|minExclusive|minInclusive|minLength|pattern)+>

<!-- Restrictions -->
<!ELEMENT langRange (#PCDATA)>
<!ELEMENT length (#PCDATA)>
<!ELEMENT maxExclusive (#PCDATA)>
<!ATTLIST maxExclusive
	datatype CDATA #REQUIRED
>
<!ELEMENT maxInclusive (#PCDATA)>
<!ATTLIST maxInclusive
	datatype CDATA #REQUIRED
>
<!ELEMENT maxLength (#PCDATA)>
<!ELEMENT minExclusive (#PCDATA)>
<!ATTLIST minExclusive
	datatype CDATA #REQUIRED
>
<!ELEMENT minInclusive (#PCDATA)>
<!ATTLIST minInclusive
	datatype CDATA #REQUIRED
>
<!ELEMENT minLength (#PCDATA)>
<!ELEMENT pattern (#PCDATA)>

<!-- Axiom Classes -->
<!ELEMENT AllDifferent (members)>
<!ELEMENT AllDisjointClasses (members)>
<!ELEMENT AllDisjointProperties (members)>
<!ELEMENT NegativeObjectPropertyAssertion (assertionProperty,sourceIndividual,targetIndividual)>

<!-- Restrictions -->
<!ELEMENT Restriction (onProperty,(((minQualifiedCardinality|maxQualifiedCardinality|qualifiedCardinality),(onClass|onDataRange))|allValuesFrom|cardinality|hasValue|hasSelf|minCardinality|maxCardinality|someValuesFrom))>

<!-- Declarations -->
<!ELEMENT Class (%annotations;,((equivalentClass*,subClassOf*,superClassOf*,disjointWith*,hasKey*)|complementOf|disjointUnionOf|intersectionOf|oneOf|unionOf))>
<!ATTLIST Class
	name CDATA #IMPLIED
	status (plumbing|unstable|testing|stable|archaic) #IMPLIED
>
<!ELEMENT Datatype (%annotations;,(equivalentClass|datatypeComplementOf|intersectionOf|unionOf|(onDatatype,withRestrictions)))> <!-- oneOf not supported; lists of literals are difficult -->
<!ATTLIST Datatype
	name CDATA #IMPLIED
	status (plumbing|unstable|testing|stable|archaic) #IMPLIED
>
<!ELEMENT AnnotationProperty (%annotations;,subPropertyOf*,domain*,range*)>
<!ATTLIST AnnotationProperty
	name CDATA #IMPLIED
	status (plumbing|unstable|testing|stable|archaic) #IMPLIED
>
<!ELEMENT ObjectProperty (%annotations;,equivalentProperty*,subPropertyOf*,inverseOf*,propertyDisjointWith*,propertyChainAxiom*,domain*,range*)>
<!ATTLIST ObjectProperty
	asymmetric (no|yes) "no"
	functional (no|yes) "no"
	inverseFunctional (no|yes) "no"
	irreflexive (no|yes) "no"
	name CDATA #IMPLIED
	reflexive (no|yes) "no"
	status (plumbing|unstable|testing|stable|archaic) #IMPLIED
	symmetric (no|yes) "no"
	transitive (no|yes) "no"
>
<!ELEMENT DatatypeProperty (%annotations;,equivalentProperty*,subPropertyOf*,propertyDisjointWith*,domain*,range*)>
<!ATTLIST DatatypeProperty
	functional (no|yes) "no"
	name CDATA #IMPLIED
	status (plumbing|unstable|testing|stable|archaic) #IMPLIED
>
<!ELEMENT NamedIndividual (%annotations;,type*,sameAs*,differentFrom*,inScheme*)>
<!ATTLIST NamedIndividual
	name CDATA #IMPLIED
	status (plumbing|unstable|testing|stable|archaic) #IMPLIED
>

<!-- Ontology -->
<!ELEMENT Ontology (%annotations;,declare*)>
<!ATTLIST Ontology
	name CDATA #IMPLIED
>