
      
   default namespace = "http://www.idpf.org/2007/opf"
   namespace opf = "http://www.idpf.org/2007/opf"
   namespace dc = "http://purl.org/dc/elements/1.1/"
   
   include "./mod/datatypes.rnc"
   include "./mod/epub-prefix-attr.rnc"
   
      
   start = element package { opf.package.attlist & opf.package.content }
   
   opf.package.attlist &= opf.version.attr & opf.unique.identifier.attr & opf.id.attr? & epub.prefix.attr? & opf.i18n.attrs            
   opf.version.attr = attribute version { '3.0' }
   opf.unique.identifier.attr = attribute unique-identifier { datatype.IDREF }
   
   opf.package.content = opf.metadata, opf.manifest, opf.spine, opf.guide?, opf.bindings?, opf.collection*

   opf.metadata = element metadata { opf.id.attr? & opf.i18n.attrs & opf.metadata.content }
   opf.metadata.content = opf.dc.elems & opf.meta* & opf.link* 
   
   opf.meta = element meta { 
      opf.epub3.meta.content | opf.epub2.meta.content
   }
   
   opf.epub3.meta.content = (opf.property.attr & opf.refines.attr? & opf.id.attr? & opf.scheme.attr? & opf.i18n.attrs & datatype.string.nonempty)
   opf.epub2.meta.content = (attribute name { text } & attribute content { text })  #legacy
   
   opf.link = element link { opf.href.attr & opf.rel.attr & opf.id.attr? & opf.refines.attr? & opf.media-type.attr? }         
      
   opf.property.attr = attribute property { datatype.property }
   opf.rel.attr = attribute rel { datatype.properties }
   opf.scheme.attr = attribute scheme { datatype.property }
   opf.refines.attr = attribute refines { datatype.URI }
   
   opf.dc.identifier = element dc:identifier { opf.id.attr? & datatype.string.nonempty } 
   opf.dc.title = element dc:title { opf.dc.attlist & datatype.string.nonempty }
   opf.dc.language = element dc:language { opf.id.attr? & datatype.languagecode }
   opf.dc.date = element dc:date { opf.id.attr? & datatype.string.nonempty }
   opf.dc.source = element dc:source { opf.dc.attlist & datatype.string.nonempty }
   opf.dc.type = element dc:type { opf.id.attr? & datatype.string.nonempty }
   opf.dc.format = element dc:format { opf.id.attr? & datatype.string.nonempty }
   opf.dc.creator = element dc:creator { opf.dc.attlist & datatype.string.nonempty }
   opf.dc.subject = element dc:subject { opf.dc.attlist & datatype.string.nonempty }
   opf.dc.description = element dc:description { opf.dc.attlist & datatype.string.nonempty }
   opf.dc.publisher = element dc:publisher { opf.dc.attlist & datatype.string.nonempty }
   opf.dc.contributor = element dc:contributor { opf.dc.attlist & datatype.string.nonempty }
   opf.dc.relation = element dc:relation { opf.dc.attlist & datatype.string.nonempty }
   opf.dc.coverage = element dc:coverage { opf.dc.attlist & datatype.string.nonempty }
   opf.dc.rights = element dc:rights { opf.dc.attlist & datatype.string.nonempty }
   
   opf.dc.elems = opf.dc.identifier+
                & opf.dc.title+
                & opf.dc.language+
                & opf.dc.date?
                & opf.dc.source*
                & opf.dc.type*
                & opf.dc.format*
                & opf.dc.creator*
                & opf.dc.subject*
                & opf.dc.description*
                & opf.dc.publisher*
                & opf.dc.contributor*
                & opf.dc.relation*
                & opf.dc.coverage*
                & opf.dc.rights*

   opf.dc.attlist = opf.id.attr? & opf.i18n.attrs
      
   opf.manifest = element manifest { opf.manifest.attlist & opf.manifest.content }
   opf.manifest.attlist &= opf.id.attr?
   opf.manifest.content = opf.item+
   
   
   opf.item = element item { opf.item.attlist }
   opf.item.attlist &= opf.id.attr & opf.href.attr & opf.media-type.attr & opf.fallback.attr? & opf.media-overlay.attr? & opf.properties.attr?  
   
   opf.fallback.attr = attribute fallback { datatype.IDREF }
   opf.media-overlay.attr = attribute media-overlay { datatype.IDREF }   
   opf.properties.attr = attribute properties { datatype.properties }
   
   
   opf.spine = element spine { opf.spine.attlist & opf.spine.content }
   opf.spine.attlist &= opf.id.attr? & opf.spine.toc.attr? & opf.ppd.attr?
   opf.spine.toc.attr = attribute toc { datatype.IDREF }
   opf.ppd.attr = attribute page-progression-direction { 'ltr' | 'rtl' | 'default'}
   opf.spine.content = opf.itemref+
   
   
   opf.itemref = element itemref { opf.itemref.attlist }
   opf.itemref.attlist &= opf.itemref.idref.attr & opf.itemref.linear.attr? & opf.id.attr? & opf.properties.attr?
   opf.itemref.idref.attr = attribute idref { datatype.IDREF }
   opf.itemref.linear.attr = attribute linear { 'yes' | 'no' }
   
    
   opf.guide = element guide { opf.reference+ }
   opf.reference = element reference { opf.href.attr & attribute type { datatype.text } & attribute title { datatype.text }?}
   
   opf.bindings = element bindings { opf.bindings.mediaType+ }
   opf.bindings.mediaType = element mediaType { opf.bindings.mediaType.attlist }
   opf.bindings.mediaType.attlist &= opf.media-type.attr & attribute handler { datatype.IDREF }
   
   opf.collection = element collection { opf.collection.attlist, opf.collection.content }
   opf.collection.attlist &= opf.id.attr? & opf.dir.attr? & opf.xml.lang.attr? & opf.collection.role.attr
   opf.collection.role.attr = attribute role { datatype.space.separated.tokens }
   opf.collection.content = opf.collection.metadata?, (opf.collection+ | (opf.collection*, opf.collection.link+))
   opf.collection.metadata = element metadata { opf.id.attr? & opf.i18n.attrs & opf.collection.metadata.content }
   opf.collection.metadata.content = opf.collection.dc.elems & opf.collection.meta* & opf.link*
   opf.collection.dc.elems = opf.dc.identifier*
                           & opf.dc.title*
                           & opf.dc.language*
                           & opf.dc.date*
                           & opf.dc.source*
                           & opf.dc.type* 
                           & opf.dc.format* 
                           & opf.dc.creator*
                           & opf.dc.subject*
                           & opf.dc.description*
                           & opf.dc.publisher*
                           & opf.dc.contributor*
                           & opf.dc.relation*
                           & opf.dc.coverage*
                           & opf.dc.rights*
   opf.collection.meta = element meta { opf.epub3.meta.content }
   opf.collection.link = element link { opf.href.attr & opf.rel.attr? & opf.id.attr? & opf.media-type.attr? }
   
   opf.media-type.attr = attribute media-type { datatype.mimetype }
   opf.href.attr = attribute href { datatype.URI }
   opf.id.attr = attribute id { datatype.ID }
   opf.i18n.attrs = opf.xml.lang.attr? & opf.dir.attr?
   opf.xml.lang.attr = attribute xml:lang { datatype.languagecode }
   opf.dir.attr = attribute dir { 'ltr' | 'rtl' }