summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'metadata/xml-schema')
-rw-r--r--metadata/xml-schema/glsa.xsd280
-rw-r--r--metadata/xml-schema/metadata.xsd559
-rw-r--r--metadata/xml-schema/projects.xsd98
-rw-r--r--metadata/xml-schema/repositories.xsd356
4 files changed, 1293 insertions, 0 deletions
diff --git a/metadata/xml-schema/glsa.xsd b/metadata/xml-schema/glsa.xsd
new file mode 100644
index 000000000000..e94f3ca5b227
--- /dev/null
+++ b/metadata/xml-schema/glsa.xsd
@@ -0,0 +1,280 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+ <xs:element name='glsa' type='glsaType'/>
+
+ <!-- elements -->
+ <xs:complexType name='glsaType'>
+ <xs:sequence>
+ <xs:element name='title' type='xs:token'/>
+ <xs:element name='synopsis' type='xs:token'/>
+ <xs:element name='product' type='productType'/>
+ <xs:element name='announced' type='xs:date'/>
+ <xs:element name='revised' type='revisedType'/>
+ <xs:element name='bug' type='xs:positiveInteger'
+ minOccurs='0' maxOccurs='unbounded'/>
+ <xs:element name='access' type='xs:token'
+ minOccurs='0' maxOccurs='1'/>
+ <xs:element name='affected' type='affectedType'/>
+ <xs:element name='background' type='partialHTMLType'
+ minOccurs='0' maxOccurs='1'/>
+ <xs:element name='description' type='partialHTMLType'/>
+ <xs:element name='impact' type='impactType'/>
+ <xs:element name='workaround' type='partialHTMLType'/>
+ <xs:element name='resolution' type='partialHTMLType'/>
+ <xs:element name='references' type='referencesType'/>
+ <xs:element name='license' type='licenseType'
+ minOccurs='0' maxOccurs='1'/>
+ <xs:element name='metadata' type='metadataType'
+ minOccurs='0' maxOccurs='unbounded'/>
+ </xs:sequence>
+ <xs:attribute name='id' type='glsaIdType' use='required'/>
+ </xs:complexType>
+
+ <xs:complexType name='productType'>
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name='type' type='productTypeType' use='required'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name='revisedType'>
+ <xs:simpleContent>
+ <xs:extension base='xs:date'>
+ <xs:attribute name='count' type='xs:positiveInteger'
+ default='1'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name='affectedType'>
+ <xs:sequence>
+ <xs:element name='package' type='affectedPackageType'
+ minOccurs='0' maxOccurs='unbounded'/>
+ <xs:element name='service' type='affectedServiceType'
+ minOccurs='0' maxOccurs='unbounded'/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name='affectedPackageType'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='vulnerable' type='affectedPackageVulnerableType'/>
+ <xs:element name='unaffected' type='affectedPackageUnaffectedType'/>
+ </xs:choice>
+ <xs:attribute name='name' type='pkgType' use='required'/>
+ <xs:attribute name='auto' type='yesNoType' use='required'/>
+ <xs:attribute name='arch' type='archType' use='required'/>
+ </xs:complexType>
+
+ <xs:complexType name='affectedServiceType'>
+ <xs:simpleContent>
+ <xs:extension base='serviceURLType'>
+ <xs:attribute name='type' type='serviceTypeType'
+ use='required'/>
+ <xs:attribute name='fixed' type='yesNoType'
+ default='no'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name='affectedPackageVulnerableType'>
+ <xs:simpleContent>
+ <xs:extension base='versionType'>
+ <xs:attribute name='range' type='versionRangeType'
+ use='required'/>
+ <xs:attribute name='slot' type='slotType'
+ default='*'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name='affectedPackageUnaffectedType'>
+ <xs:simpleContent>
+ <xs:extension base='versionType'>
+ <xs:attribute name='range' type='versionRangeType'
+ use='required'/>
+ <xs:attribute name='slot' type='slotType'
+ default='*'/>
+ <xs:attribute name='name' type='pkgType'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <!-- value types -->
+ <xs:simpleType name='glsaIdType'>
+ <xs:restriction base='xs:token'>
+ <!-- YYYYMM-NN -->
+ <xs:pattern value="[0-9]{4}(0[1-9]|1[0-2])-[0-9]{2}"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='productTypeType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='ebuild'/>
+ <xs:enumeration value='informational'/>
+ <xs:enumeration value='infrastructure'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='yesNoType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='yes'/>
+ <xs:enumeration value='no'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='archType'>
+ <xs:restriction base='xs:token'>
+ <!-- '*' or 1+ arches -->
+ <xs:pattern value="[*]|[a-z0-9-]+(\s+[a-z0-9-]+)*"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='versionRangeType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='le'/>
+ <xs:enumeration value='lt'/>
+ <xs:enumeration value='eq'/>
+ <xs:enumeration value='gt'/>
+ <xs:enumeration value='ge'/>
+ <xs:enumeration value='rle'/>
+ <xs:enumeration value='rlt'/>
+ <xs:enumeration value='rgt'/>
+ <xs:enumeration value='rge'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='serviceURLType'>
+ <xs:restriction base='xs:token'>
+ <!-- TODO: improve this? -->
+ <xs:pattern value="((https?|ftps?|rsync)://\S+)?"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='serviceTypeType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='rsync'/>
+ <xs:enumeration value='web'/>
+ <xs:enumeration value='mirror'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name='impactType'>
+ <xs:complexContent>
+ <xs:extension base="partialHTMLType">
+ <xs:attribute name='type' type='xs:token' use='required'/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name='referencesType'>
+ <xs:sequence>
+ <xs:element name='uri' type='htmlURIType'
+ minOccurs='0' maxOccurs='unbounded'/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name='licenseType'>
+ <!-- empty by design -->
+ </xs:complexType>
+
+ <xs:complexType name='metadataType'>
+ <xs:simpleContent>
+ <xs:extension base='xs:token'>
+ <!-- TODO: enumerate allowed values? -->
+ <xs:attribute name='tag' type='xs:token' use='required'/>
+ <xs:attribute name='revision' type='xs:token'/>
+ <xs:attribute name='author' type='xs:token'/>
+ <xs:attribute name='timestamp' type='xs:dateTime'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <!-- PMS types -->
+ <xs:simpleType name='pkgType'>
+ <xs:restriction base='xs:token'>
+ <!-- PMS 3.1.1 Category Names + 3.1.2 Package Names -->
+ <!-- note: this does not enforce the 'anything matching
+ the version syntax' requirement -->
+ <xs:pattern
+ value="[A-Za-z0-9_][A-Za-z0-9+_.-]*/[A-Za-z0-9_][A-Za-z0-9+_-]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='versionType'>
+ <xs:restriction base='xs:token'>
+ <!-- PMS 3.2 Version Specifications -->
+ <!-- (optionally followed by '*', for 'eq' operator -->
+ <xs:pattern value="[0-9]+(\.[0-9]+)*[a-z]?((_alpha|_beta|_pre|_rc|_p)[0-9]*)*(-r[0-9]+)?[*]?"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='slotType'>
+ <xs:restriction base='xs:token'>
+ <!-- PMS 3.1.3 Slot Names + special value '*' -->
+ <xs:pattern value="[A-Za-z0-9_][A-Za-z0-9+_.-]*|[*]"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- Horrible HTML-like mixed-text -->
+ <xs:complexType name='partialHTMLType'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='p' type='htmlPType'/>
+ <xs:element name='ul' type='htmlListType'/>
+ <xs:element name='ol' type='htmlListType'/>
+ <xs:element name='code' type='xs:string'/>
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:complexType name='htmlPType' mixed='true'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='mail' type='htmlMailType'/>
+ <xs:element name='uri' type='htmlURIType'/>
+ <xs:element name='b' type='xs:token'/>
+ <xs:element name='i' type='xs:token'/>
+ <xs:element name='br' type='htmlBRType'/>
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:complexType name='htmlListType'>
+ <xs:sequence>
+ <xs:element name='li' type='xs:token'
+ minOccurs='1' maxOccurs='unbounded'/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name='htmlBRType'>
+ <!-- empty -->
+ </xs:complexType>
+
+ <xs:complexType name='htmlMailType'>
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name='link' type='mailLinkType' use='required'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name='htmlURIType'>
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name='link' type='uriLinkType' use='required'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name='mailLinkType'>
+ <xs:restriction base='xs:token'>
+ <!-- TODO: improve? -->
+ <xs:pattern value="[^@]+@[^.\s]+\.\S+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='uriLinkType'>
+ <xs:restriction base='xs:token'>
+ <!-- TODO: improve? -->
+ <xs:pattern value="(http|ftp)s?://\S+"/>
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
diff --git a/metadata/xml-schema/metadata.xsd b/metadata/xml-schema/metadata.xsd
new file mode 100644
index 000000000000..8b8ac0b56cd7
--- /dev/null
+++ b/metadata/xml-schema/metadata.xsd
@@ -0,0 +1,559 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+ <!-- top-level variants -->
+ <xs:element name='pkgmetadata' type='pkgMetadataType'>
+ <!-- note: restrict uniquity rules are simplified
+ the spec says: one for each matched package
+ we can only do: one for each restrict rule -->
+ <xs:unique name='longDescUniquityConstraint'>
+ <xs:selector xpath='longdescription'/>
+ <xs:field xpath='@lang'/>
+ <xs:field xpath='@restrict'/>
+ </xs:unique>
+ <xs:key name='maintainerKeyConstraint'>
+ <xs:selector xpath='maintainer'/>
+ <xs:field xpath='email'/>
+ <xs:field xpath='@restrict'/>
+ </xs:key>
+ <xs:unique name='slotsUniquityConstraint'>
+ <xs:selector xpath='slots'/>
+ <xs:field xpath='@lang'/>
+ </xs:unique>
+ <xs:unique name='stabilizeAllArchesUniquityConstraint'>
+ <xs:selector xpath='stabilize-all-arches'/>
+ <xs:field xpath='@restrict'/>
+ </xs:unique>
+ <xs:unique name='upstreamSingleConstraint'>
+ <xs:selector xpath='upstream'/>
+ <xs:field xpath='@fake-only-once'/>
+ </xs:unique>
+ <xs:unique name='useUniquityConstraint'>
+ <xs:selector xpath='use'/>
+ <xs:field xpath='@lang'/>
+ </xs:unique>
+ </xs:element>
+ <xs:element name='catmetadata' type='catMetadataType'>
+ <xs:unique name='catLongDescUniquityConstraint'>
+ <xs:selector xpath='longdescription'/>
+ <xs:field xpath='@lang'/>
+ </xs:unique>
+ </xs:element>
+
+ <!-- global elements -->
+ <xs:complexType name='pkgMetadataType'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='longdescription' type='longDescType'/>
+ <xs:element name='maintainer' type='maintainerType'>
+ <xs:unique name='maintainerNameSingleConstraint'>
+ <xs:selector xpath='name'/>
+ <xs:field xpath='@fake-only-once'/>
+ </xs:unique>
+ <xs:unique name='maintainerDescUniquityConstraint'>
+ <xs:selector xpath='description'/>
+ <xs:field xpath='@lang'/>
+ </xs:unique>
+ </xs:element>
+ <xs:element name='slots' type='slotsType'>
+ <xs:unique name='slotUniquityConstraint'>
+ <xs:selector xpath='slot'/>
+ <xs:field xpath='@name'/>
+ </xs:unique>
+ <xs:unique name='subslotsSingleConstraint'>
+ <xs:selector xpath='subslots'/>
+ <xs:field xpath='@fake-only-once'/>
+ </xs:unique>
+ </xs:element>
+ <xs:element name='stabilize-allarches' type='stabilizeAllArchesType'/>
+ <xs:element name='upstream' type='upstreamType'>
+ <xs:unique name='upstreamMaintainerUniquityConstraint'>
+ <xs:selector xpath='maintainer'/>
+ <xs:field xpath='name'/>
+ </xs:unique>
+ <xs:unique name='bugsToSingleConstraint'>
+ <xs:selector xpath='bugs-to'/>
+ <xs:field xpath='@fake-only-once'/>
+ </xs:unique>
+ <xs:unique name='changelogSingleConstraint'>
+ <xs:selector xpath='changelog'/>
+ <xs:field xpath='@fake-only-once'/>
+ </xs:unique>
+ <!-- prevent accidentally repeating the same remote -->
+ <xs:unique name='upstreamRemoteIdRepetitionConstraint'>
+ <xs:selector xpath='remote-id'/>
+ <xs:field xpath='@type'/>
+ <xs:field xpath='.'/>
+ </xs:unique>
+ <xs:unique name='upstreamDocUniquityConstraint'>
+ <xs:selector xpath='doc'/>
+ <xs:field xpath='@lang'/>
+ </xs:unique>
+ </xs:element>
+ <xs:element name='use' type='useType'>
+ <xs:unique name='flagUniquityConstraint'>
+ <xs:selector xpath='flag'/>
+ <xs:field xpath='@name'/>
+ <xs:field xpath='@restrict'/>
+ </xs:unique>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:complexType name='catMetadataType'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='longdescription' type='catLongDescType'/>
+ </xs:choice>
+ </xs:complexType>
+
+ <!-- the huge <upstream/> structure -->
+ <xs:complexType name='upstreamType'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='maintainer' type='upstreamMaintainerType'/>
+ <xs:element name='changelog' type='urlOnceType'/>
+ <xs:element name='doc' type='upstreamDocType'/>
+ <xs:element name='bugs-to' type='urlOnceType'/>
+ <xs:element name='remote-id' type='upstreamRemoteIdType'/>
+ </xs:choice>
+ <xs:attribute name='fake-only-once'
+ fixed='there can be at most one &lt;upstream/&gt; element'/>
+ </xs:complexType>
+
+ <!-- maintainer in two variants -->
+ <xs:complexType name='maintainerType'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='email' type='emailType'/>
+ <xs:element name='name' type='tokenOnceType'/>
+ <xs:element name='description' type='maintainerDescType'/>
+ </xs:choice>
+ <xs:attribute name='type' type='maintainerTypeAttrType'
+ use='required'/>
+ <xs:attribute name='restrict' type='restrictAttrType'
+ default=''/>
+ </xs:complexType>
+
+ <xs:simpleType name='maintainerTypeAttrType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='person'/>
+ <xs:enumeration value='project'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name='upstreamMaintainerType'>
+ <xs:all>
+ <xs:element name='email' type='emailType'
+ minOccurs='0'/>
+ <xs:element name='name' type='xs:token'
+ minOccurs='1'/>
+ </xs:all>
+ <xs:attribute name='status' type='upstreamMaintainerStatusAttrType'
+ default='unknown'/>
+ </xs:complexType>
+
+ <xs:simpleType name='upstreamMaintainerStatusAttrType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='active'/>
+ <xs:enumeration value='inactive'/>
+ <xs:enumeration value='unknown'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name='maintainerDescType'>
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name='lang' type='langAttrType' default='en'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <!-- long description -->
+ <xs:complexType name='longDescType' mixed='true'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='pkg' type='pkgType'/>
+ <xs:element name='cat' type='catType'/>
+ </xs:choice>
+ <xs:attribute name='lang' type='langAttrType' default='en'/>
+ <xs:attribute name='restrict' type='restrictAttrType' default=''/>
+ </xs:complexType>
+
+ <xs:complexType name='catLongDescType' mixed='true'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='pkg' type='pkgType'/>
+ <xs:element name='cat' type='catType'/>
+ </xs:choice>
+ <xs:attribute name='lang' type='langAttrType' default='en'/>
+ </xs:complexType>
+
+ <!-- slots -->
+ <xs:complexType name='slotsType'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='slot' type='slotType'/>
+ <xs:element name='subslots' type='tokenOnceType'/>
+ </xs:choice>
+ <xs:attribute name='lang' type='langAttrType' default='en'/>
+ </xs:complexType>
+
+ <xs:complexType name='slotType'>
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name='name' type='slotNameAttrType'
+ use='required'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name='slotNameAttrType'>
+ <xs:restriction base='xs:token'>
+ <!-- PMS 3.1.3 Slot Names + special value '*' -->
+ <xs:pattern value="[A-Za-z0-9_][A-Za-z0-9+_.-]*|[*]"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- stabilize-allarches -->
+ <xs:complexType name='stabilizeAllArchesType'>
+ <xs:attribute name='restrict' type='restrictAttrType'
+ default=''/>
+ </xs:complexType>
+
+ <!-- use flags -->
+ <xs:complexType name='useType'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='flag' type='flagType'/>
+ </xs:choice>
+ <xs:attribute name='lang' type='langAttrType' default='en'/>
+ </xs:complexType>
+
+ <xs:complexType name='flagType' mixed='true'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='cat' type='catType'/>
+ <xs:element name='pkg' type='pkgType'/>
+ </xs:choice>
+ <xs:attribute name='name' type='flagNameAttrType'
+ use='required'/>
+ <xs:attribute name='restrict' type='restrictAttrType'
+ default=''/>
+ </xs:complexType>
+
+ <xs:simpleType name='flagNameAttrType'>
+ <xs:restriction base='xs:token'>
+ <!-- PMS 3.1.4 USE Flag Names -->
+ <xs:pattern value="[A-Za-z0-9][A-Za-z0-9+_@-]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- upstream-specific types -->
+ <xs:complexType name='upstreamDocType'>
+ <xs:simpleContent>
+ <xs:extension base="urlType">
+ <xs:attribute name='lang' type='langAttrType' default='en'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name='upstreamRemoteIdType'>
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name='type' type='upstreamRemoteIdTypeAttrType'
+ use='required'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name='upstreamRemoteIdTypeAttrType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='bitbucket'/>
+ <xs:enumeration value='cpan'/>
+ <xs:enumeration value='cpan-module'/>
+ <xs:enumeration value='cpe'/>
+ <xs:enumeration value='cran'/>
+ <xs:enumeration value='ctan'/>
+ <xs:enumeration value='freecode'/>
+ <xs:enumeration value='freshmeat'/>
+ <xs:enumeration value='github'/>
+ <xs:enumeration value='gitlab'/>
+ <xs:enumeration value='gitorious'/>
+ <xs:enumeration value='google-code'/>
+ <xs:enumeration value='launchpad'/>
+ <xs:enumeration value='pear'/>
+ <xs:enumeration value='pecl'/>
+ <xs:enumeration value='pypi'/>
+ <xs:enumeration value='rubyforge'/>
+ <xs:enumeration value='rubygems'/>
+ <xs:enumeration value='sourceforge'/>
+ <xs:enumeration value='sourceforge-jp'/>
+ <xs:enumeration value='vim'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- creepy mixed-text types -->
+ <xs:simpleType name='catType'>
+ <xs:restriction base='xs:token'>
+ <!-- PMS 3.1.1 Category Names -->
+ <xs:pattern value="[A-Za-z0-9_][A-Za-z0-9+_.-]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name='pkgType'>
+ <xs:restriction base='xs:token'>
+ <!-- PMS 3.1.1 Category Names + 3.1.2 Package Names -->
+ <!-- note: this does not enforce the 'anything matching
+ the version syntax' requirement -->
+ <xs:pattern
+ value="[A-Za-z0-9_][A-Za-z0-9+_.-]*/[A-Za-z0-9_][A-Za-z0-9+_-]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- common attributes -->
+ <xs:simpleType name='langAttrType'>
+ <xs:restriction base='xs:token'>
+ <!-- ISO 639-1 language codes -->
+ <xs:enumeration value='aa'/>
+ <xs:enumeration value='ab'/>
+ <xs:enumeration value='ae'/>
+ <xs:enumeration value='af'/>
+ <xs:enumeration value='ak'/>
+ <xs:enumeration value='am'/>
+ <xs:enumeration value='an'/>
+ <xs:enumeration value='ar'/>
+ <xs:enumeration value='as'/>
+ <xs:enumeration value='av'/>
+ <xs:enumeration value='ay'/>
+ <xs:enumeration value='az'/>
+ <xs:enumeration value='ba'/>
+ <xs:enumeration value='be'/>
+ <xs:enumeration value='bg'/>
+ <xs:enumeration value='bh'/>
+ <xs:enumeration value='bi'/>
+ <xs:enumeration value='bm'/>
+ <xs:enumeration value='bn'/>
+ <xs:enumeration value='bo'/>
+ <xs:enumeration value='bo'/>
+ <xs:enumeration value='br'/>
+ <xs:enumeration value='bs'/>
+ <xs:enumeration value='ca'/>
+ <xs:enumeration value='ce'/>
+ <xs:enumeration value='ch'/>
+ <xs:enumeration value='co'/>
+ <xs:enumeration value='cr'/>
+ <xs:enumeration value='cs'/>
+ <xs:enumeration value='cs'/>
+ <xs:enumeration value='cu'/>
+ <xs:enumeration value='cv'/>
+ <xs:enumeration value='cy'/>
+ <xs:enumeration value='cy'/>
+ <xs:enumeration value='da'/>
+ <xs:enumeration value='de'/>
+ <xs:enumeration value='de'/>
+ <xs:enumeration value='dv'/>
+ <xs:enumeration value='dz'/>
+ <xs:enumeration value='ee'/>
+ <xs:enumeration value='el'/>
+ <xs:enumeration value='el'/>
+ <xs:enumeration value='en'/>
+ <xs:enumeration value='eo'/>
+ <xs:enumeration value='es'/>
+ <xs:enumeration value='et'/>
+ <xs:enumeration value='eu'/>
+ <xs:enumeration value='eu'/>
+ <xs:enumeration value='fa'/>
+ <xs:enumeration value='fa'/>
+ <xs:enumeration value='ff'/>
+ <xs:enumeration value='fi'/>
+ <xs:enumeration value='fj'/>
+ <xs:enumeration value='fo'/>
+ <xs:enumeration value='fr'/>
+ <xs:enumeration value='fr'/>
+ <xs:enumeration value='fy'/>
+ <xs:enumeration value='ga'/>
+ <xs:enumeration value='ga'/>
+ <xs:enumeration value='Ga'/>
+ <xs:enumeration value='gd'/>
+ <xs:enumeration value='gl'/>
+ <xs:enumeration value='gn'/>
+ <xs:enumeration value='gu'/>
+ <xs:enumeration value='gv'/>
+ <xs:enumeration value='ha'/>
+ <xs:enumeration value='he'/>
+ <xs:enumeration value='hi'/>
+ <xs:enumeration value='ho'/>
+ <xs:enumeration value='hr'/>
+ <xs:enumeration value='ht'/>
+ <xs:enumeration value='hu'/>
+ <xs:enumeration value='hy'/>
+ <xs:enumeration value='hy'/>
+ <xs:enumeration value='hz'/>
+ <xs:enumeration value='ia'/>
+ <xs:enumeration value='id'/>
+ <xs:enumeration value='ie'/>
+ <xs:enumeration value='ig'/>
+ <xs:enumeration value='ii'/>
+ <xs:enumeration value='ik'/>
+ <xs:enumeration value='io'/>
+ <xs:enumeration value='is'/>
+ <xs:enumeration value='is'/>
+ <xs:enumeration value='it'/>
+ <xs:enumeration value='iu'/>
+ <xs:enumeration value='ja'/>
+ <xs:enumeration value='jv'/>
+ <xs:enumeration value='ka'/>
+ <xs:enumeration value='ka'/>
+ <xs:enumeration value='kg'/>
+ <xs:enumeration value='ki'/>
+ <xs:enumeration value='kj'/>
+ <xs:enumeration value='kk'/>
+ <xs:enumeration value='kl'/>
+ <xs:enumeration value='km'/>
+ <xs:enumeration value='kn'/>
+ <xs:enumeration value='ko'/>
+ <xs:enumeration value='kr'/>
+ <xs:enumeration value='ks'/>
+ <xs:enumeration value='ku'/>
+ <xs:enumeration value='kv'/>
+ <xs:enumeration value='kw'/>
+ <xs:enumeration value='ky'/>
+ <xs:enumeration value='la'/>
+ <xs:enumeration value='lb'/>
+ <xs:enumeration value='lg'/>
+ <xs:enumeration value='li'/>
+ <xs:enumeration value='ln'/>
+ <xs:enumeration value='lo'/>
+ <xs:enumeration value='lt'/>
+ <xs:enumeration value='lu'/>
+ <xs:enumeration value='lv'/>
+ <xs:enumeration value='mg'/>
+ <xs:enumeration value='mh'/>
+ <xs:enumeration value='mi'/>
+ <xs:enumeration value='mi'/>
+ <xs:enumeration value='mk'/>
+ <xs:enumeration value='mk'/>
+ <xs:enumeration value='ml'/>
+ <xs:enumeration value='mn'/>
+ <xs:enumeration value='mr'/>
+ <xs:enumeration value='ms'/>
+ <xs:enumeration value='ms'/>
+ <xs:enumeration value='mt'/>
+ <xs:enumeration value='my'/>
+ <xs:enumeration value='my'/>
+ <xs:enumeration value='na'/>
+ <xs:enumeration value='nb'/>
+ <xs:enumeration value='nd'/>
+ <xs:enumeration value='ne'/>
+ <xs:enumeration value='ng'/>
+ <xs:enumeration value='nl'/>
+ <xs:enumeration value='nl'/>
+ <xs:enumeration value='nn'/>
+ <xs:enumeration value='no'/>
+ <xs:enumeration value='nr'/>
+ <xs:enumeration value='nv'/>
+ <xs:enumeration value='ny'/>
+ <xs:enumeration value='oc'/>
+ <xs:enumeration value='oj'/>
+ <xs:enumeration value='om'/>
+ <xs:enumeration value='or'/>
+ <xs:enumeration value='os'/>
+ <xs:enumeration value='pa'/>
+ <xs:enumeration value='pi'/>
+ <xs:enumeration value='pl'/>
+ <xs:enumeration value='ps'/>
+ <xs:enumeration value='pt'/>
+ <xs:enumeration value='qu'/>
+ <xs:enumeration value='rm'/>
+ <xs:enumeration value='rn'/>
+ <xs:enumeration value='ro'/>
+ <xs:enumeration value='ro'/>
+ <xs:enumeration value='ru'/>
+ <xs:enumeration value='rw'/>
+ <xs:enumeration value='sa'/>
+ <xs:enumeration value='sc'/>
+ <xs:enumeration value='sd'/>
+ <xs:enumeration value='se'/>
+ <xs:enumeration value='sg'/>
+ <xs:enumeration value='si'/>
+ <xs:enumeration value='sk'/>
+ <xs:enumeration value='sk'/>
+ <xs:enumeration value='sl'/>
+ <xs:enumeration value='sm'/>
+ <xs:enumeration value='sn'/>
+ <xs:enumeration value='so'/>
+ <xs:enumeration value='sq'/>
+ <xs:enumeration value='sq'/>
+ <xs:enumeration value='sr'/>
+ <xs:enumeration value='ss'/>
+ <xs:enumeration value='st'/>
+ <xs:enumeration value='su'/>
+ <xs:enumeration value='sv'/>
+ <xs:enumeration value='sw'/>
+ <xs:enumeration value='ta'/>
+ <xs:enumeration value='te'/>
+ <xs:enumeration value='tg'/>
+ <xs:enumeration value='th'/>
+ <xs:enumeration value='ti'/>
+ <xs:enumeration value='tk'/>
+ <xs:enumeration value='tl'/>
+ <xs:enumeration value='tn'/>
+ <xs:enumeration value='to'/>
+ <xs:enumeration value='tr'/>
+ <xs:enumeration value='ts'/>
+ <xs:enumeration value='tt'/>
+ <xs:enumeration value='tw'/>
+ <xs:enumeration value='ty'/>
+ <xs:enumeration value='ug'/>
+ <xs:enumeration value='uk'/>
+ <xs:enumeration value='ur'/>
+ <xs:enumeration value='uz'/>
+ <xs:enumeration value='ve'/>
+ <xs:enumeration value='vi'/>
+ <xs:enumeration value='vo'/>
+ <xs:enumeration value='wa'/>
+ <xs:enumeration value='wo'/>
+ <xs:enumeration value='xh'/>
+ <xs:enumeration value='yi'/>
+ <xs:enumeration value='yo'/>
+ <xs:enumeration value='za'/>
+ <xs:enumeration value='zh'/>
+ <xs:enumeration value='zh'/>
+ <xs:enumeration value='zu'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='restrictAttrType'>
+ <xs:restriction base='xs:token'>
+ <!-- simplified package dependency syntax -->
+ <!-- note: 'pure' package atom is technically valid too
+ but not really meaningful -->
+ <xs:pattern
+ value="(([&lt;&gt;]=?|[=~])[A-Za-z0-9_][A-Za-z0-9+_.-]*/[A-Za-z0-9_][A-Za-z0-9+_-]*-[0-9]+(\.[0-9]+)*[a-z]?((_alpha|_beta|_pre|_rc|_p)[0-9]*)*(-r[0-9]+)?\*?)?"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- generic types -->
+ <xs:simpleType name='emailType'>
+ <xs:restriction base='xs:token'>
+ <!-- minimal safe regex -->
+ <xs:pattern value="[^@]+@[^.]+\..+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name='tokenOnceType'>
+ <xs:simpleContent>
+ <xs:extension base="xs:token">
+ <xs:attribute name='fake-only-once'
+ fixed='there can be at most one element of this type'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name='urlType'>
+ <xs:restriction base='xs:token'>
+ <!-- TODO: something better? -->
+ <xs:pattern value="(mailto:[^@]+@[^.\s]+\.\S+|https?://\S+)"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name='urlOnceType'>
+ <xs:simpleContent>
+ <xs:extension base="urlType">
+ <xs:attribute name='fake-only-once'
+ fixed='there can be at most one element of this type'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+</xs:schema>
diff --git a/metadata/xml-schema/projects.xsd b/metadata/xml-schema/projects.xsd
new file mode 100644
index 000000000000..beaaf4e83fb2
--- /dev/null
+++ b/metadata/xml-schema/projects.xsd
@@ -0,0 +1,98 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+ <xs:element name='projects'>
+ <xs:complexType>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='project' type='projectType'>
+ <xs:unique name='descUniquityConstraint'>
+ <xs:selector xpath='description'/>
+ <xs:field xpath='@fake-only-once'/>
+ </xs:unique>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ <xs:key name='projectKey'>
+ <xs:selector xpath='project'/>
+ <xs:field xpath='email'/>
+ </xs:key>
+ <xs:keyref name='subprojectRef' refer='projectKey'>
+ <xs:selector xpath='project/subproject'/>
+ <xs:field xpath='@ref'/>
+ </xs:keyref>
+ <!-- define additional keys to enforce exactly one element
+ of each kind -->
+ <xs:key name='projectNameKey'>
+ <xs:selector xpath='project'/>
+ <xs:field xpath='name'/>
+ </xs:key>
+ <xs:key name='projectURLKey'>
+ <xs:selector xpath='project'/>
+ <xs:field xpath='url'/>
+ </xs:key>
+ </xs:element>
+
+ <xs:complexType name='projectType'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='email' type='emailType'/>
+ <xs:element name='name' type='xs:token'/>
+ <xs:element name='url' type='urlType'/>
+ <xs:element name='description' type='descriptionType'/>
+ <xs:element name='subproject' type='subprojectType'/>
+ <xs:element name='member' type='memberType'/>
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:complexType name='descriptionType'>
+ <xs:simpleContent>
+ <xs:extension base='xs:token'>
+ <xs:attribute name='fake-only-once'
+ fixed='there can be at most one &lt;description/&gt; element'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name='subprojectType'>
+ <xs:attribute name='inherit-members' type='numericBoolType'/>
+ <xs:attribute name='ref' type='projectRefType'/>
+ </xs:complexType>
+
+ <xs:simpleType name='projectRefType'>
+ <xs:restriction base='emailType'>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name='memberType'>
+ <xs:all>
+ <xs:element name='email' type='emailType'
+ minOccurs='1' maxOccurs='1'/>
+ <xs:element name='name' type='xs:token'
+ minOccurs='0' maxOccurs='1'/>
+ <xs:element name='role' type='xs:token'
+ minOccurs='0' maxOccurs='1'/>
+ </xs:all>
+ <xs:attribute name='is-lead' type='numericBoolType'/>
+ </xs:complexType>
+
+ <!-- generic types -->
+ <xs:simpleType name='emailType'>
+ <xs:restriction base='xs:token'>
+ <!-- minimal safe regex -->
+ <xs:pattern value="[^@]+@[^.]+\..+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='urlType'>
+ <xs:restriction base='xs:token'>
+ <!-- TODO: something better? -->
+ <xs:pattern value="https?://\S+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='numericBoolType'>
+ <xs:restriction base='xs:integer'>
+ <xs:minInclusive value='0'/>
+ <xs:maxInclusive value='1'/>
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
diff --git a/metadata/xml-schema/repositories.xsd b/metadata/xml-schema/repositories.xsd
new file mode 100644
index 000000000000..54bf62a63288
--- /dev/null
+++ b/metadata/xml-schema/repositories.xsd
@@ -0,0 +1,356 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+ <xs:element name='repositories'>
+ <xs:complexType>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='repo' type='repoType'/>
+ </xs:choice>
+ <xs:attribute name='version' fixed='1.0' use='required'/>
+ </xs:complexType>
+ <xs:key name='repoKey'>
+ <xs:selector xpath='repo'/>
+ <xs:field xpath='name'/>
+ </xs:key>
+ <xs:unique name='descUniquityConstraint'>
+ <xs:selector xpath='description'/>
+ <xs:field xpath='@lang'/>
+ </xs:unique>
+ <xs:unique name='longDescUniquityConstraint'>
+ <xs:selector xpath='longdescription'/>
+ <xs:field xpath='@lang'/>
+ </xs:unique>
+ <xs:unique name='homepageSingleConstraint'>
+ <xs:selector xpath='homepage'/>
+ <xs:field xpath='@fake-only-once'/>
+ </xs:unique>
+ </xs:element>
+
+ <xs:complexType name='repoType'>
+ <xs:choice minOccurs='0' maxOccurs='unbounded'>
+ <xs:element name='name' type='repoNameType'/>
+ <xs:element name='description' type='descriptionType'/>
+ <xs:element name='longdescription' type='descriptionType'/>
+ <xs:element name='homepage' type='urlOnceType'/>
+ <xs:element name='owner' type='ownerType'/>
+ <xs:element name='source' type='sourceType'/>
+ <xs:element name='feed' type='urlType'/>
+ </xs:choice>
+ <xs:attribute name='priority' type='xs:integer'/>
+ <xs:attribute name='quality' type='repoQualityAttrType'
+ use='required'/>
+ <xs:attribute name='status' type='repoStatusAttrType'
+ use='required'/>
+ </xs:complexType>
+
+ <xs:simpleType name='repoNameType'>
+ <xs:restriction base='xs:token'>
+ <!-- PMS 3.1.5 Repository Name -->
+ <!-- note: this doesn't enforce 'not look like a version'
+ rule -->
+ <xs:pattern value='[A-Za-z0-9_][A-Za-z0-9_-]*'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name='descriptionType'>
+ <xs:simpleContent>
+ <xs:extension base='xs:token'>
+ <xs:attribute name='lang' type='langAttrType' default='en'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name='ownerType'>
+ <xs:all>
+ <xs:element name='email' type='emailType'
+ minOccurs='1' maxOccurs='1'/>
+ <xs:element name='name' type='xs:token'
+ minOccurs='0' maxOccurs='1'/>
+ </xs:all>
+ <xs:attribute name='type' type='ownerTypeAttrType'
+ use='required'/>
+ </xs:complexType>
+
+ <xs:complexType name='sourceType'>
+ <xs:simpleContent>
+ <xs:extension base='urlType'>
+ <xs:attribute name='type' type='sourceTypeAttrType'
+ use='required'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <!-- attributes -->
+ <xs:simpleType name='langAttrType'>
+ <xs:restriction base='xs:token'>
+ <!-- ISO 639-1 language codes -->
+ <xs:enumeration value='aa'/>
+ <xs:enumeration value='ab'/>
+ <xs:enumeration value='ae'/>
+ <xs:enumeration value='af'/>
+ <xs:enumeration value='ak'/>
+ <xs:enumeration value='am'/>
+ <xs:enumeration value='an'/>
+ <xs:enumeration value='ar'/>
+ <xs:enumeration value='as'/>
+ <xs:enumeration value='av'/>
+ <xs:enumeration value='ay'/>
+ <xs:enumeration value='az'/>
+ <xs:enumeration value='ba'/>
+ <xs:enumeration value='be'/>
+ <xs:enumeration value='bg'/>
+ <xs:enumeration value='bh'/>
+ <xs:enumeration value='bi'/>
+ <xs:enumeration value='bm'/>
+ <xs:enumeration value='bn'/>
+ <xs:enumeration value='bo'/>
+ <xs:enumeration value='bo'/>
+ <xs:enumeration value='br'/>
+ <xs:enumeration value='bs'/>
+ <xs:enumeration value='ca'/>
+ <xs:enumeration value='ce'/>
+ <xs:enumeration value='ch'/>
+ <xs:enumeration value='co'/>
+ <xs:enumeration value='cr'/>
+ <xs:enumeration value='cs'/>
+ <xs:enumeration value='cs'/>
+ <xs:enumeration value='cu'/>
+ <xs:enumeration value='cv'/>
+ <xs:enumeration value='cy'/>
+ <xs:enumeration value='cy'/>
+ <xs:enumeration value='da'/>
+ <xs:enumeration value='de'/>
+ <xs:enumeration value='de'/>
+ <xs:enumeration value='dv'/>
+ <xs:enumeration value='dz'/>
+ <xs:enumeration value='ee'/>
+ <xs:enumeration value='el'/>
+ <xs:enumeration value='el'/>
+ <xs:enumeration value='en'/>
+ <xs:enumeration value='eo'/>
+ <xs:enumeration value='es'/>
+ <xs:enumeration value='et'/>
+ <xs:enumeration value='eu'/>
+ <xs:enumeration value='eu'/>
+ <xs:enumeration value='fa'/>
+ <xs:enumeration value='fa'/>
+ <xs:enumeration value='ff'/>
+ <xs:enumeration value='fi'/>
+ <xs:enumeration value='fj'/>
+ <xs:enumeration value='fo'/>
+ <xs:enumeration value='fr'/>
+ <xs:enumeration value='fr'/>
+ <xs:enumeration value='fy'/>
+ <xs:enumeration value='ga'/>
+ <xs:enumeration value='ga'/>
+ <xs:enumeration value='Ga'/>
+ <xs:enumeration value='gd'/>
+ <xs:enumeration value='gl'/>
+ <xs:enumeration value='gn'/>
+ <xs:enumeration value='gu'/>
+ <xs:enumeration value='gv'/>
+ <xs:enumeration value='ha'/>
+ <xs:enumeration value='he'/>
+ <xs:enumeration value='hi'/>
+ <xs:enumeration value='ho'/>
+ <xs:enumeration value='hr'/>
+ <xs:enumeration value='ht'/>
+ <xs:enumeration value='hu'/>
+ <xs:enumeration value='hy'/>
+ <xs:enumeration value='hy'/>
+ <xs:enumeration value='hz'/>
+ <xs:enumeration value='ia'/>
+ <xs:enumeration value='id'/>
+ <xs:enumeration value='ie'/>
+ <xs:enumeration value='ig'/>
+ <xs:enumeration value='ii'/>
+ <xs:enumeration value='ik'/>
+ <xs:enumeration value='io'/>
+ <xs:enumeration value='is'/>
+ <xs:enumeration value='is'/>
+ <xs:enumeration value='it'/>
+ <xs:enumeration value='iu'/>
+ <xs:enumeration value='ja'/>
+ <xs:enumeration value='jv'/>
+ <xs:enumeration value='ka'/>
+ <xs:enumeration value='ka'/>
+ <xs:enumeration value='kg'/>
+ <xs:enumeration value='ki'/>
+ <xs:enumeration value='kj'/>
+ <xs:enumeration value='kk'/>
+ <xs:enumeration value='kl'/>
+ <xs:enumeration value='km'/>
+ <xs:enumeration value='kn'/>
+ <xs:enumeration value='ko'/>
+ <xs:enumeration value='kr'/>
+ <xs:enumeration value='ks'/>
+ <xs:enumeration value='ku'/>
+ <xs:enumeration value='kv'/>
+ <xs:enumeration value='kw'/>
+ <xs:enumeration value='ky'/>
+ <xs:enumeration value='la'/>
+ <xs:enumeration value='lb'/>
+ <xs:enumeration value='lg'/>
+ <xs:enumeration value='li'/>
+ <xs:enumeration value='ln'/>
+ <xs:enumeration value='lo'/>
+ <xs:enumeration value='lt'/>
+ <xs:enumeration value='lu'/>
+ <xs:enumeration value='lv'/>
+ <xs:enumeration value='mg'/>
+ <xs:enumeration value='mh'/>
+ <xs:enumeration value='mi'/>
+ <xs:enumeration value='mi'/>
+ <xs:enumeration value='mk'/>
+ <xs:enumeration value='mk'/>
+ <xs:enumeration value='ml'/>
+ <xs:enumeration value='mn'/>
+ <xs:enumeration value='mr'/>
+ <xs:enumeration value='ms'/>
+ <xs:enumeration value='ms'/>
+ <xs:enumeration value='mt'/>
+ <xs:enumeration value='my'/>
+ <xs:enumeration value='my'/>
+ <xs:enumeration value='na'/>
+ <xs:enumeration value='nb'/>
+ <xs:enumeration value='nd'/>
+ <xs:enumeration value='ne'/>
+ <xs:enumeration value='ng'/>
+ <xs:enumeration value='nl'/>
+ <xs:enumeration value='nl'/>
+ <xs:enumeration value='nn'/>
+ <xs:enumeration value='no'/>
+ <xs:enumeration value='nr'/>
+ <xs:enumeration value='nv'/>
+ <xs:enumeration value='ny'/>
+ <xs:enumeration value='oc'/>
+ <xs:enumeration value='oj'/>
+ <xs:enumeration value='om'/>
+ <xs:enumeration value='or'/>
+ <xs:enumeration value='os'/>
+ <xs:enumeration value='pa'/>
+ <xs:enumeration value='pi'/>
+ <xs:enumeration value='pl'/>
+ <xs:enumeration value='ps'/>
+ <xs:enumeration value='pt'/>
+ <xs:enumeration value='qu'/>
+ <xs:enumeration value='rm'/>
+ <xs:enumeration value='rn'/>
+ <xs:enumeration value='ro'/>
+ <xs:enumeration value='ro'/>
+ <xs:enumeration value='ru'/>
+ <xs:enumeration value='rw'/>
+ <xs:enumeration value='sa'/>
+ <xs:enumeration value='sc'/>
+ <xs:enumeration value='sd'/>
+ <xs:enumeration value='se'/>
+ <xs:enumeration value='sg'/>
+ <xs:enumeration value='si'/>
+ <xs:enumeration value='sk'/>
+ <xs:enumeration value='sk'/>
+ <xs:enumeration value='sl'/>
+ <xs:enumeration value='sm'/>
+ <xs:enumeration value='sn'/>
+ <xs:enumeration value='so'/>
+ <xs:enumeration value='sq'/>
+ <xs:enumeration value='sq'/>
+ <xs:enumeration value='sr'/>
+ <xs:enumeration value='ss'/>
+ <xs:enumeration value='st'/>
+ <xs:enumeration value='su'/>
+ <xs:enumeration value='sv'/>
+ <xs:enumeration value='sw'/>
+ <xs:enumeration value='ta'/>
+ <xs:enumeration value='te'/>
+ <xs:enumeration value='tg'/>
+ <xs:enumeration value='th'/>
+ <xs:enumeration value='ti'/>
+ <xs:enumeration value='tk'/>
+ <xs:enumeration value='tl'/>
+ <xs:enumeration value='tn'/>
+ <xs:enumeration value='to'/>
+ <xs:enumeration value='tr'/>
+ <xs:enumeration value='ts'/>
+ <xs:enumeration value='tt'/>
+ <xs:enumeration value='tw'/>
+ <xs:enumeration value='ty'/>
+ <xs:enumeration value='ug'/>
+ <xs:enumeration value='uk'/>
+ <xs:enumeration value='ur'/>
+ <xs:enumeration value='uz'/>
+ <xs:enumeration value='ve'/>
+ <xs:enumeration value='vi'/>
+ <xs:enumeration value='vo'/>
+ <xs:enumeration value='wa'/>
+ <xs:enumeration value='wo'/>
+ <xs:enumeration value='xh'/>
+ <xs:enumeration value='yi'/>
+ <xs:enumeration value='yo'/>
+ <xs:enumeration value='za'/>
+ <xs:enumeration value='zh'/>
+ <xs:enumeration value='zh'/>
+ <xs:enumeration value='zu'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='repoQualityAttrType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='core'/>
+ <xs:enumeration value='stable'/>
+ <xs:enumeration value='testing'/>
+ <xs:enumeration value='experimental'/>
+ <xs:enumeration value='graveyard'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='repoStatusAttrType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='official'/>
+ <xs:enumeration value='unofficial'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='ownerTypeAttrType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='person'/>
+ <xs:enumeration value='project'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='sourceTypeAttrType'>
+ <xs:restriction base='xs:token'>
+ <xs:enumeration value='bzr'/>
+ <xs:enumeration value='cvs'/>
+ <xs:enumeration value='darcs'/>
+ <xs:enumeration value='git'/>
+ <xs:enumeration value='mercurial'/>
+ <xs:enumeration value='rsync'/>
+ <xs:enumeration value='svn'/>
+ <xs:enumeration value='tar'/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- generic types -->
+ <xs:simpleType name='emailType'>
+ <xs:restriction base='xs:token'>
+ <!-- minimal safe regex -->
+ <xs:pattern value="[^@]+@[^.]+\..+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name='urlType'>
+ <xs:restriction base='xs:token'>
+ <!-- TODO: something better? -->
+ <xs:pattern value="[^:\s]+:\S+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name='urlOnceType'>
+ <xs:simpleContent>
+ <xs:extension base="urlType">
+ <xs:attribute name='fake-only-once'
+ fixed='there can be at most one element of this type'/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+</xs:schema>