<?xml version="1.0" encoding="utf-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
  ns="http://infrae.com/ns/silva"
  xmlns:silva-content="http://infrae.com/namespaces/metadata/silva"
  xmlns:silva-extra="http://infrae.com/namespaces/metadata/silva-extra">
  <start>
    <element name="silva">
      <!-- The starting point for the export/import. Can be 
           a Silva Root, Publication, Folder or Document./-->
      <attribute name="url"><text /></attribute>
      <attribute name="path"><text /></attribute>
      <attribute name="datetime"><text /></attribute>
      <attribute name="silva_version"><text /></attribute>
      <choice>
        <ref name="SilvaRoot" />
        <ref name="SilvaPublication" />
        <ref name="SilvaFolder" />
        <ref name="SilvaDocument" />
      </choice>
     </element>
  </start>

  <define name="SilvaRoot">
    <!-- A Silva Root element. Can contain other Silva content/-->
    <element name="root">
      <attribute name="id"><text /></attribute>
      <ref name="metadata" /> 
      <ref name="contained" />
    </element>
  </define>

  <define name="SilvaFolder">
    <!-- A Silva Root element. Can contain other Silva content/-->
    <element name="folder">
      <attribute name="id"><text /></attribute>
      <ref name="metadata" />
      <ref name="contained" />
    </element>
  </define>

  <define name="SilvaPublication">
    <!-- A Silva Publiaction element. Can contain other Silva content/-->
    <element name="publication">
      <attribute name="id"><text /></attribute>
      <ref name="metadata" />
      <ref name="contained" />
    </element>
  </define>

  <!-- XXX may need to be moved to SilvaDocument/-->
  <define name="SilvaDocument">
    <!-- A Silva Document element./-->
    <element name="document">
      <attribute name="id"><text /></attribute>
      <optional>
        <ref name="workflow" />
      </optional>
      <oneOrMore>
        <ref name="SilvaDocumentVersion" />
      </oneOrMore>
    </element> 
  </define>

  <define name="SilvaDocumentVersion">
    <element name="content">
      <attribute name="version_id"><text /></attribute>
      <ref name="metadata" />
      <!-- XXX href needs to change once a stable silva document schema is on infrae.com /-->
	  <externalRef href="silva_document.rng"/>
    </element>
  </define>

  <define name="SilvaLink">
    <!-- A Silva Link element./-->
    <element name="link">
      <attribute name="id"><text /></attribute>
      <optional>
        <ref name="workflow" />
      </optional>
      <oneOrMore>
        <ref name="SilvaLinkVersion" />
      </oneOrMore>
    </element>
  </define>

  <define name="SilvaLinkVersion">
    <element name="content">
      <attribute name="version_id"><text /></attribute>
      <ref name="metadata" />
      <ref name="link" />
    </element>
  </define>

  <define name="SilvaGhost">
    <!-- A Silva Ghost element. Ghosts are really links to other content./-->
    <element name="ghost">
      <attribute name="id"><text /></attribute>
      <optional>
        <ref name="workflow" />
      </optional>
      <oneOrMore>
        <ref name="SilvaGhostVersion" />
      </oneOrMore>
    </element>
  </define>

  <define name="SilvaGhostVersion">
    <element name="content">
      <attribute name="version_id"><text /></attribute>
      <element name="metatype"><text /></element>
      <element name="haunted_url"><text /></element>
      <choice>
        <ref name="SilvaDocumentVersion" />
        <ref name="SilvaLinkVersion" />
      </choice>
    </element>
  </define>
    
  <define name="SilvaGhostFolder">
    <!-- A Silva Ghost Folder element. Ghost Folders are really links to other folders./-->
    <element name="ghost_folder">
      <attribute name="id"><text /></attribute>
      <element name="content">
        <element name="metatype"><text /></element>
        <element name="haunted_url"><text /></element>
        <ref name="contained" />
      </element>
    </element>
  </define>

  <define name="indexer">
    <element name="indexer">
      <attribute name="id"><text /></attribute>
      <ref name="metadata" />
    </element>
  </define>

  <define name="imageAsset">
    <element name="image_asset">
      <attribute name="id"><text /></attribute>
      <ref name="metadata" />
      <element name="asset_id"><text /></element>
    </element>
  </define>

  <define name="unknownContent">
    <element name="unknown_content">
      <attribute name="id"><text /></attribute>
      <element name="zexp_id"><text /></element>
    </element>
  </define>

  <define name="autoToc">
    <element name="auto_toc">
      <attribute name="id"><text /></attribute>
      <ref name="metadata" />
    </element>
  </define>
  
  <define name="contained">
    <element name="content">
      <optional>
        <element name="default">
          <choice>
            <ref name="SilvaDocument" />
            <ref name="autoToc" />
          </choice>
        </element>
      </optional>
      <zeroOrMore>
        <choice>
          <ref name="SilvaPublication" />
          <ref name="SilvaFolder" />
          <ref name="SilvaGhostFolder" />
          <ref name="SilvaDocument" />
          <ref name="SilvaLink" />
          <ref name="SilvaGhost" />
          <ref name="imageAsset" />
          <ref name="indexer" />
          <ref name="unknownContent" />
          <ref name="autoToc" />
        </choice>
      </zeroOrMore>
    </element>
  </define>

  <define name="metadata">
    <element name="metadata">
      <zeroOrMore>
        <ref name="set" />
      </zeroOrMore>
    </element>
  </define>

  <define name="workflow">
    <element name="workflow">
      <zeroOrMore>
        <element name="version">
          <attribute name="id"><text /></attribute>
          <element name="status"><text /></element>
          <element name="publication_datetime"><text /></element>
          <element name="expiration_datetime"><text /></element>
        </element>
      </zeroOrMore>
    </element>
  </define>
    
  <define name="set">
    <element name="set">
      <attribute name="id"><text /></attribute>
      <zeroOrMore>
        <ref name="anyElement" />
      </zeroOrMore>
    </element>
  </define>

  <define name="link">
    <element name="url"><text /></element>
  </define>

  <define name="anyElement">
    <element>
      <anyName/>
      <zeroOrMore>
        <attribute>
          <anyName/>
        </attribute>
      </zeroOrMore>
      <zeroOrMore>
        <choice>
          <text/>
          <ref name="anyElement"/>
        </choice>
      </zeroOrMore>
    </element>
  </define>

</grammar>
