<?xml version='1.0'?>
<!-- $Header$
Copyright J.M. Vanel 2001-2003 - under Lesser GNU Public Licence

From any XML, make a skeleton for an XML Schema. Doesn't record attributes.
In the 'oneTag' template we add an anonymous <complexType> wrapper, to achieve a real conforming XML Schema.
The "occurs=" parameter in <appinfo> records a global count of all elements.
-->
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
  version='1.1'
  xmlns:xsd  = "http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xsd" >

 <xsl:import href="unique.xslt" />
 <xsl:output indent='yes' />

 <!-- Here we group siblings by same tag name,  we call the 'oneTag' template on those groups, and we recurse on the rest.  -->
 <xsl:template name='anyTag'>
  <xsl:param name='siblings'/>
  <xsl:if test='$siblings' >
   <xsl:variable name='n' select='name($siblings)'/>

   <xsl:call-template name='oneTag'>
    <xsl:with-param name='homologs' select='$siblings[name()=$n]'/>
   </xsl:call-template>
   <xsl:variable name='otherTags' select='$siblings[name()!=$n]' />
   <xsl:if test='$otherTags' >
    <xsl:call-template name='anyTag'>
     <xsl:with-param name='siblings' select='$otherTags'/>
    </xsl:call-template>
   </xsl:if>
  </xsl:if>
 </xsl:template>

 <!-- Here we have a set of siblings having all the same tag name, we can output an element, and recurse on the children. -->
 <xsl:template name='oneTag'>
  <xsl:param name='homologs'/>
  <xsd:element >
   <xsl:variable name='rootElement' select="not ($homologs/../..)" />
   <xsl:if test='not($rootElement)'>
    <xsl:attribute name='minOccurs'>0</xsl:attribute>
   </xsl:if>
   <xsl:variable name='hasPrefix' select="contains(name($homologs),':')" />
   <xsl:choose>
   <xsl:when test="$hasPrefix and namespace-uri($homologs) != $targetNamespace"><!--  -->
    <xsl:attribute name='ref'><xsl:value-of select='name($homologs)'/></xsl:attribute>
   </xsl:when>
   <xsl:otherwise>
   <xsl:attribute name='name'>
    <xsl:value-of select='local-name($homologs)'/></xsl:attribute>
   <xsl:if test='$hasPrefix and not($rootElement)'>
    <xsl:attribute name='form'>qualified</xsl:attribute>
   </xsl:if>
   <xsd:annotation>
    <xsd:appinfo>
     <statistics>
      <xsl:attribute name='occurs'> <xsl:value-of select='count($homologs)'/></xsl:attribute>
     </statistics>
    </xsd:appinfo>
   </xsd:annotation>
   <xsd:complexType>
    <xsl:if test='$homologs/text()'>
     <xsl:attribute name='mixed'>true</xsl:attribute>
    </xsl:if>
    <!-- recurse on the children -->
    <xsl:if test='$homologs/*'>
     <xsd:sequence minOccurs="0" maxOccurs="unbounded">
      <xsl:call-template name='anyTag'>
       <xsl:with-param name='siblings' select='$homologs/*'/>
      </xsl:call-template>
     </xsd:sequence>
    </xsl:if>
   </xsd:complexType>
   </xsl:otherwise>
   </xsl:choose>
  </xsd:element>
 </xsl:template>

 <xsl:template match='text()'/>

 <xsl:variable name='targetNamespace' select='namespace-uri(/*)' />

 <xsl:variable name='allNamespaces' >
  <xsl:variable name='allNamespaces-duplicates' >
   <xsl:for-each select='/*//*' >
     <namespace prefix="{substring-before(name(),':')}">
      <xsl:value-of select='namespace-uri(.)' />
     </namespace>
   </xsl:for-each>
  </xsl:variable>
  <!-- not yet implemented in Saxon 7.3.1: <xsl:copy-of select='distinct-values($allNamespaces-duplicates/*)' /> -->
  <xsl:call-template name="make-unique">
    <xsl:with-param name="nodes" >
     <xsl:for-each select="$allNamespaces-duplicates/*" >
      <xsl:sort />
      <xsl:copy-of select="." />
     </xsl:for-each>
    </xsl:with-param>
  </xsl:call-template>
 </xsl:variable>

 <xsl:template match='/'>
  <xsl:message>$allNamespaces=
   <xsl:copy-of select='$allNamespaces' />
  </xsl:message>
  <xsd:schema elementFormDefault="unqualified" >
   <!-- TODO: multiple namespaces in different imported XSD -->
   <xsl:if test="$targetNamespace">
    <xsl:attribute name='targetNamespace'>
     <xsl:value-of select='$targetNamespace'/></xsl:attribute>
   </xsl:if>
   <xsl:for-each select="$allNamespaces/*" >
    <xsl:namespace name="{@prefix}"><xsl:value-of select="."/></xsl:namespace>
   </xsl:for-each>
   <xsd:annotation>
    <xsd:documentation> Generated from XML instance by example2Schema.xslt - 
                 See http://wwbota.free.fr/XSLT_models/README.html
    </xsd:documentation>
   </xsd:annotation>
   <xsl:for-each select="$allNamespaces/*" >
    <xsl:if test=". != $targetNamespace and . != '' ">
     <xsd:import namespace="{.}" />
    </xsl:if>
   </xsl:for-each>
   <xsl:call-template name='anyTag'>
    <xsl:with-param name='siblings' select='*'/>
   </xsl:call-template>
  </xsd:schema>
 </xsl:template>

</xsl:stylesheet>
