Moving xmlclass and docutils into plcopeneditor
authorlaurent
Fri, 30 Sep 2011 17:16:02 +0200
changeset 565 94c11207aa6f
parent 564 5024d42e1050
child 566 6014ef82a98a
child 569 4ce166451816
Moving xmlclass and docutils into plcopeneditor
.hgignore
debian/control
docutils/__init__.py
docutils/dochtml.py
docutils/docpdf.py
docutils/docsvg.py
xmlclass/__init__.py
xmlclass/po.xml
xmlclass/test.xsd
xmlclass/xmlclass.py
xmlclass/xsdschema.py
--- a/.hgignore	Fri Sep 23 20:07:40 2011 +0200
+++ b/.hgignore	Fri Sep 30 17:16:02 2011 +0200
@@ -3,6 +3,4 @@
 syntax: regexp
 \.pyc$
 syntax: regexp
-^xmlclass$
-syntax: regexp
 ^\.settings.*$
--- a/debian/control	Fri Sep 23 20:07:40 2011 +0200
+++ b/debian/control	Fri Sep 30 17:16:02 2011 +0200
@@ -7,7 +7,7 @@
 
 Package: plcopeneditor
 Architecture: any
-Depends: libwxgtk2.8-0, libwxbase2.8-0, xmlclass, docutils
+Depends: libwxgtk2.8-0, libwxbase2.8-0
 Description: The PLCopen Editor saves and loads XML projects accordingly to PLCopen TC6-XML Schemes.
  Edits all 5 of the IEC-61131-3 languages :
      - FBD -> Function Block Diagram
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docutils/__init__.py	Fri Sep 30 17:16:02 2011 +0200
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+from dochtml import *
+from docpdf import *
+from docsvg import *
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docutils/dochtml.py	Fri Sep 30 17:16:02 2011 +0200
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import wx, os, wx.html, subprocess
+
+HtmlFrameOpened = []
+
+def OpenHtmlFrame(self, title, file, size):
+        if title not in HtmlFrameOpened:
+            HtmlFrameOpened.append(title)
+            window = HtmlFrame(self, HtmlFrameOpened)
+            window.SetTitle(title)
+            window.SetHtmlPage(file)
+            window.SetClientSize(size)
+            window.Show()
+
+[ID_HTMLFRAME, ID_HTMLFRAMEHTMLCONTENT] = [wx.NewId() for _init_ctrls in range(2)]
+EVT_HTML_URL_CLICK = wx.NewId()
+
+class HtmlWindowUrlClick(wx.PyEvent):
+    def __init__(self, linkinfo):
+        wx.PyEvent.__init__(self)
+        self.SetEventType(EVT_HTML_URL_CLICK)
+        self.linkinfo = (linkinfo.GetHref(), linkinfo.GetTarget())
+        
+class UrlClickHtmlWindow(wx.html.HtmlWindow):
+    """ HTML window that generates and OnLinkClicked event.
+
+    Use this to avoid having to override HTMLWindow
+    """
+    def OnLinkClicked(self, linkinfo):
+        wx.PostEvent(self, HtmlWindowUrlClick(linkinfo))
+    
+    def Bind(self, event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY):
+        if event == HtmlWindowUrlClick:
+            self.Connect(-1, -1, EVT_HTML_URL_CLICK, handler)
+        else:
+            wx.html.HtmlWindow.Bind(event, handler, source=source, id=id, id2=id2)
+
+class HtmlFrame(wx.Frame):
+        def _init_ctrls(self, prnt):
+            wx.Frame.__init__(self, id=ID_HTMLFRAME, name='HtmlFrame',
+                  parent=prnt, pos=wx.Point(320, 231), size=wx.Size(853, 616),
+                  style=wx.DEFAULT_FRAME_STYLE, title='')
+            self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
+            
+            self.HtmlContent = UrlClickHtmlWindow(id=ID_HTMLFRAMEHTMLCONTENT,
+                  name='HtmlContent', parent=self, pos=wx.Point(0, 0),
+                  size=wx.Size(-1, -1), style=wx.html.HW_SCROLLBAR_AUTO|wx.html.HW_NO_SELECTION)
+            self.HtmlContent.Bind(HtmlWindowUrlClick, self.OnLinkClick)
+
+        def __init__(self, parent, opened):
+            self._init_ctrls(parent)
+            self.HtmlFrameOpened = opened
+            
+        def SetHtmlCode(self, htmlcode):
+            self.HtmlContent.SetPage(htmlcode)
+            
+        def SetHtmlPage(self, htmlpage):
+            self.HtmlContent.LoadPage(htmlpage)
+            
+        def OnCloseFrame(self, event):
+            self.HtmlFrameOpened.remove(self.GetTitle())
+            event.Skip()
+        
+        def OnLinkClick(self, event):
+            url = event.linkinfo[0]
+            try:
+                if wx.Platform == '__WXMSW__':
+                    import webbrowser
+                    webbrowser.open(url)
+                elif subprocess.call("firefox %s"%url, shell=True) != 0:
+                    wx.MessageBox("""Firefox browser not found.\nPlease point your browser at :\n%s""" % url)
+            except ImportError:
+                wx.MessageBox('Please point your browser at: %s' % url)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docutils/docpdf.py	Fri Sep 30 17:16:02 2011 +0200
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import wx, os
+
+readerexepath = None
+    
+def get_acroversion():
+    " Return version of Adobe Acrobat executable or None"
+    import _winreg
+    adobesoft = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r'Software\Adobe')
+    for index in range(_winreg.QueryInfoKey(adobesoft)[0]):
+        key = _winreg.EnumKey(adobesoft, index)
+        if "acrobat" in key.lower():
+            acrokey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'Software\\Adobe\\%s' % key)
+            for index in range(_winreg.QueryInfoKey(acrokey)[0]):
+                numver = _winreg.EnumKey(acrokey, index)
+                try:
+                    res = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE, 'Software\\Adobe\\%s\\%s\\InstallPath' % (key, numver))
+                    return res
+                except:
+                    pass
+    return None
+
+def open_win_pdf(readerexepath, pdffile, pagenum = None):
+    if pagenum != None :
+        os.spawnl(os.P_DETACH, readerexepath, "AcroRd32.exe", "/A", "page=%d=OpenActions" % pagenum, '"%s"'%pdffile)
+    else:
+        os.spawnl(os.P_DETACH, readerexepath, "AcroRd32.exe", '"%s"'%pdffile)
+
+def open_lin_pdf(readerexepath, pdffile, pagenum = None):
+    if pagenum == None :
+        os.system("%s -remote DS301 %s &"%(readerexepath, pdffile))
+    else:
+    	print "Open pdf %s at page %d"%(pdffile, pagenum)
+        os.system("%s -remote DS301 %s %d &"%(readerexepath, pdffile, pagenum))
+
+def open_pdf(pdffile, pagenum = None):
+    if wx.Platform == '__WXMSW__' :
+        try:
+            readerpath = get_acroversion()
+        except:
+            wx.MessageBox("Acrobat Reader is not found or installed !")
+            return None
+        
+        readerexepath = os.path.join(readerpath, "AcroRd32.exe")
+        if(os.path.isfile(readerexepath)):
+            open_win_pdf(readerexepath, pdffile, pagenum)
+        else:
+            return None
+    else:
+        readerexepath = os.path.join("/usr/bin","xpdf")
+        if(os.path.isfile(readerexepath)):
+            open_lin_pdf(readerexepath, pdffile, pagenum)
+        else:
+            wx.MessageBox("xpdf is not found or installed !")
+            return None
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docutils/docsvg.py	Fri Sep 30 17:16:02 2011 +0200
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import wx, os, subprocess
+
+def get_inkscape_path():
+    """ Return the Inkscape path """
+    import _winreg
+    svgexepath = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE,
+                 'Software\\Classes\\svgfile\\shell\\Inkscape\\command')
+    svgexepath = svgexepath.replace('"%1"', '')
+    return svgexepath.replace('"', '')
+
+def open_win_svg(svgexepath, svgfile):
+    """ Open Inkscape on Windows platform """
+    popenargs = [svgexepath]
+    if svgfile is not None :
+        popenargs.append(svgfile)
+    subprocess.Popen(popenargs).pid
+
+def open_lin_svg(svgexepath, svgfile):
+    """ Open Inkscape on Linux platform """
+    if os.path.isfile("/usr/bin/inkscape"):
+        os.system("%s %s &"%(svgexepath , svgfile))
+    
+def open_svg(svgfile):
+    """ Generic function to open SVG file """
+    if wx.Platform == '__WXMSW__' :
+        svgexepath = get_inkscape_path()
+        try:
+            open_win_svg(svgexepath , svgfile)
+        except:
+            wx.MessageBox("Inkscape is not found or installed !")
+            return None
+    else:
+        svgexepath = os.path.join("/usr/bin","inkscape")
+        if(os.path.isfile(svgexepath)):
+            open_lin_svg(svgexepath, svgfile)
+        else:
+            wx.MessageBox("Inkscape is not found or installed !")
+            return None
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlclass/__init__.py	Fri Sep 30 17:16:02 2011 +0200
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# Package initialisation
+
+from xmlclass import ClassFactory, GenerateClasses, GetAttributeValue, time_model, CreateNode, NodeSetAttr, NodeRenameAttr
+from xsdschema import XSDClassFactory, GenerateClassesFromXSD, GenerateClassesFromXSDstring
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlclass/po.xml	Fri Sep 30 17:16:02 2011 +0200
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<purchaseOrder orderDate="1999-10-20">
+  <shipTo country="US">
+    <name>Alice Smith</name>
+    <street>123 Maple Street</street>
+    <city>Mill Valley</city>
+    <state>CA</state>
+    <zip>90952</zip>
+  </shipTo>
+  <billTo country="US">
+    <name>Robert Smith</name>
+    <street>8 Oak Avenue</street>
+    <city>Old Town</city>
+    <state>PA</state>
+    <zip>95819</zip>
+  </billTo>
+  <comment>Hurry, my lawn is going wild!</comment>
+  <items>
+    <item partNum="872-AA">
+      <productName>Lawnmower</productName>
+      <quantity>1</quantity>
+      <USPrice>148.95</USPrice>
+      <comment>Confirm this is electric</comment>
+    </item>
+    <item partNum="926-AA">
+      <productName>Baby Monitor</productName>
+      <quantity>1</quantity>
+      <USPrice>39.98</USPrice>
+      <shipDate>1999-05-21</shipDate>
+    </item>
+  </items>
+</purchaseOrder>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlclass/test.xsd	Fri Sep 30 17:16:02 2011 +0200
@@ -0,0 +1,66 @@
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+  <xsd:annotation>
+    <xsd:documentation xml:lang="en">
+      Purchase order schema for Example.com.
+      Copyright 2000 Example.com. All rights reserved.
+    </xsd:documentation>
+  </xsd:annotation>
+
+  <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
+
+  <xsd:element name="comment" type="xsd:string"/>
+
+  <xsd:complexType name="PurchaseOrderType">
+    <xsd:sequence>
+      <xsd:element name="shipTo" type="USAddress"/>
+      <xsd:element name="billTo" type="USAddress"/>
+      <xsd:element ref="comment" minOccurs="0"/>
+      <xsd:element name="items"  type="Items"/>
+    </xsd:sequence>
+    <xsd:attribute name="orderDate" type="xsd:date"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="USAddress">
+    <xsd:sequence>
+      <xsd:element name="name"   type="xsd:string"/>
+      <xsd:element name="street" type="xsd:string"/>
+      <xsd:element name="city"   type="xsd:string"/>
+      <xsd:element name="state"  type="xsd:string"/>
+      <xsd:element name="zip"    type="xsd:decimal"/>
+    </xsd:sequence>
+    <xsd:attribute name="country" type="xsd:NMTOKEN"
+                   fixed="US"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="Items">
+    <xsd:sequence>
+      <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
+        <xsd:complexType>
+          <xsd:sequence>
+            <xsd:element name="productName" type="xsd:string"/>
+            <xsd:element name="quantity">
+              <xsd:simpleType>
+                <xsd:restriction base="xsd:positiveInteger">
+                  <xsd:maxExclusive value="100"/>
+                </xsd:restriction>
+              </xsd:simpleType>
+            </xsd:element>
+            <xsd:element name="USPrice"  type="xsd:decimal"/>
+            <xsd:element ref="comment"   minOccurs="0"/>
+            <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
+          </xsd:sequence>
+          <xsd:attribute name="partNum" type="SKU" use="required"/>
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <!-- Stock Keeping Unit, a code for identifying products -->
+  <xsd:simpleType name="SKU">
+    <xsd:restriction base="xsd:string">
+      <xsd:pattern value="\d{3}-[A-Z]{2}"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+
+</xsd:schema>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlclass/xmlclass.py	Fri Sep 30 17:16:02 2011 +0200
@@ -0,0 +1,1670 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import sys
+import re
+import datetime
+from types import *
+from xml.dom import minidom
+from xml.sax.saxutils import escape, unescape, quoteattr
+from new import classobj
+
+def CreateNode(name):
+    node = minidom.Node()
+    node.nodeName = name
+    node._attrs = {}
+    node.childNodes = []
+    return node
+
+def NodeRenameAttr(node, old_name, new_name):
+    node._attrs[new_name] = node._attrs.pop(old_name)
+
+def NodeSetAttr(node, name, value):
+    attr = minidom.Attr(name)
+    text = minidom.Text()
+    text.data = value
+    attr.childNodes[0] = text
+    node._attrs[name] = attr
+
+"""
+Regular expression models for checking all kind of string values defined in XML
+standard
+"""
+Name_model = re.compile('([a-zA-Z_\:][\w\.\-\:]*)$')
+Names_model = re.compile('([a-zA-Z_\:][\w\.\-\:]*(?: [a-zA-Z_\:][\w\.\-\:]*)*)$')
+NMToken_model = re.compile('([\w\.\-\:]*)$')
+NMTokens_model = re.compile('([\w\.\-\:]*(?: [\w\.\-\:]*)*)$')
+QName_model = re.compile('((?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*)$')
+QNames_model = re.compile('((?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*(?: (?:[a-zA-Z_][\w]*:)?[a-zA-Z_][\w]*)*)$')
+NCName_model = re.compile('([a-zA-Z_][\w]*)$')
+URI_model = re.compile('((?:http://|/)?(?:[\w.-]*/?)*)$')
+LANGUAGE_model = re.compile('([a-zA-Z]{1,8}(?:-[a-zA-Z0-9]{1,8})*)$')
+
+ONLY_ANNOTATION = re.compile("((?:annotation )?)")
+
+"""
+Regular expression models for extracting dates and times from a string
+"""
+time_model = re.compile('([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)(?:Z)?$')
+date_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$')
+datetime_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})[ T]([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$')
+
+class xml_timezone(datetime.tzinfo):
+
+    def SetOffset(self, offset):
+        if offset == "Z":
+            self.__offset = timedelta(minutes = 0)
+            self.__name = "UTC"
+        else:
+            sign = {"-" : -1, "+" : 1}[offset[0]]
+            hours, minutes = [int(val) for val in offset[1:].split(":")]
+            self.__offset = timedelta(minutes=sign * (hours * 60 + minutes))
+            self.__name = ""
+
+    def utcoffset(self, dt):
+        return self.__offset
+
+    def tzname(self, dt):
+        return self.__name
+
+    def dst(self, dt):
+        return ZERO
+
+[SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE, 
+ ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG
+] = range(12)
+
+def NotSupportedYet(type):
+    """
+    Function that generates a function that point out to user that datatype
+    used is not supported by xmlclass yet
+    @param type: data type
+    @return: function generated
+    """
+    def GetUnknownValue(attr):
+        raise ValueError("\"%s\" type isn't supported by \"xmlclass\" yet!" % \
+                         type)
+    return GetUnknownValue
+
+"""
+This function calculates the number of whitespace for indentation
+"""
+def getIndent(indent, balise):
+    first = indent * 2
+    second = first + len(balise) + 1
+    return u'\t'.expandtabs(first), u'\t'.expandtabs(second)
+
+
+def GetAttributeValue(attr, extract=True):
+    """
+    Function that extracts data from a tree node
+    @param attr: tree node containing data to extract
+    @param extract: attr is a tree node or not
+    @return: data extracted as string
+    """
+    if not extract:
+        return attr
+    if len(attr.childNodes) == 1:
+        return unescape(attr.childNodes[0].data.encode())
+    else:
+        # content is a CDATA
+        text = ""
+        for node in attr.childNodes:
+            if node.nodeName != "#text":
+                text += node.data.encode()
+        return text
+
+
+def GetNormalizedString(attr, extract=True):
+    """
+    Function that normalizes a string according to XML 1.0. Replace  
+    tabulations, line feed and carriage return by white space
+    @param attr: tree node containing data to extract or data to normalize
+    @param extract: attr is a tree node or not
+    @return: data normalized as string
+    """
+    if extract:
+        value = GetAttributeValue(attr)
+    else:
+        value = attr
+    return value.replace("\t", " ").replace("\r", " ").replace("\n", " ")
+
+
+def GetToken(attr, extract=True):
+    """
+    Function that tokenizes a string according to XML 1.0. Remove any leading  
+    and trailing white space and replace internal sequence of two or more 
+    spaces by only one white space
+    @param attr: tree node containing data to extract or data to tokenize
+    @param extract: attr is a tree node or not
+    @return: data tokenized as string
+    """
+    return " ".join([part for part in 
+                     GetNormalizedString(attr, extract).split(" ")
+                     if part])
+
+
+def GetHexInteger(attr, extract=True):
+    """
+    Function that extracts an hexadecimal integer from a tree node or a string
+    @param attr: tree node containing data to extract or data as a string
+    @param extract: attr is a tree node or not
+    @return: data as an integer
+    """
+    if extract:
+        value = GetAttributeValue(attr)
+    else:
+        value = attr
+    if len(value) % 2 != 0:
+        raise ValueError("\"%s\" isn't a valid hexadecimal integer!" % value)
+    try:
+        return int(value, 16)
+    except:
+        raise ValueError("\"%s\" isn't a valid hexadecimal integer!" % value)
+
+
+def GenerateIntegerExtraction(minInclusive=None, maxInclusive=None, 
+                              minExclusive=None, maxExclusive=None):
+    """
+    Function that generates an extraction function for integer defining min and
+    max of integer value
+    @param minInclusive: inclusive minimum
+    @param maxInclusive: inclusive maximum
+    @param minExclusive: exclusive minimum
+    @param maxExclusive: exclusive maximum
+    @return: function generated
+    """
+    def GetInteger(attr, extract=True):
+        """
+        Function that extracts an integer from a tree node or a string
+        @param attr: tree node containing data to extract or data as a string
+        @param extract: attr is a tree node or not
+        @return: data as an integer
+        """
+
+        if extract:
+            value = GetAttributeValue(attr)
+        else:
+            value = attr
+        try:
+            # TODO: permit to write value like 1E2
+            value = int(value)
+        except:
+            raise ValueError("\"%s\" isn't a valid integer!" % value)
+        if minInclusive is not None and value < minInclusive:
+            raise ValueError("\"%d\" isn't greater or equal to %d!" % \
+                             (value, minInclusive))
+        if maxInclusive is not None and value > maxInclusive:
+            raise ValueError("\"%d\" isn't lesser or equal to %d!" % \
+                             (value, maxInclusive))
+        if minExclusive is not None and value <= minExclusive:
+            raise ValueError("\"%d\" isn't greater than %d!" % \
+                             (value, minExclusive))
+        if maxExclusive is not None and value >= maxExclusive:
+            raise ValueError("\"%d\" isn't lesser than %d!" % \
+                             (value, maxExclusive))
+        return value
+    return GetInteger
+
+
+def GenerateFloatExtraction(type, extra_values=[]):
+    """
+    Function that generates an extraction function for float
+    @param type: name of the type of float
+    @return: function generated
+    """
+    def GetFloat(attr, extract = True):
+        """
+        Function that extracts a float from a tree node or a string
+        @param attr: tree node containing data to extract or data as a string
+        @param extract: attr is a tree node or not
+        @return: data as a float
+        """
+        if extract:
+            value = GetAttributeValue(attr)
+        else:
+            value = attr
+        if value in extra_values:
+            return value
+        try:
+            return float(value)
+        except:
+            raise ValueError("\"%s\" isn't a valid %s!" % (value, type))
+    return GetFloat
+
+
+def GetBoolean(attr, extract=True):
+    """
+    Function that extracts a boolean from a tree node or a string
+    @param attr: tree node containing data to extract or data as a string
+    @param extract: attr is a tree node or not
+    @return: data as a boolean
+    """
+    if extract:
+        value = GetAttributeValue(attr)
+    else:
+        value = attr
+    if value == "true" or value == "1":
+        return True
+    elif value == "false" or value == "0":
+        return False
+    else:
+        raise ValueError("\"%s\" isn't a valid boolean!" % value)
+
+
+def GetTime(attr, extract=True):
+    """
+    Function that extracts a time from a tree node or a string
+    @param attr: tree node containing data to extract or data as a string
+    @param extract: attr is a tree node or not
+    @return: data as a time
+    """
+    if extract:
+        value = GetAttributeValue(attr)
+    else:
+        value = attr
+    result = time_model.match(value)
+    if result:
+        values = result.groups()
+        time_values = [int(v) for v in values[:2]]
+        seconds = float(values[2])
+        time_values.extend([int(seconds), int((seconds % 1) * 1000000)])
+        return datetime.time(*time_values)
+    else:
+        raise ValueError("\"%s\" isn't a valid time!" % value)
+
+
+def GetDate(attr, extract=True):
+    """
+    Function that extracts a date from a tree node or a string
+    @param attr: tree node containing data to extract or data as a string
+    @param extract: attr is a tree node or not
+    @return: data as a date
+    """
+    if extract:
+        value = GetAttributeValue(attr)
+    else:
+        value = attr
+    result = date_model.match(value)
+    if result:
+        values = result.groups()
+        date_values = [int(v) for v in values[:3]]
+        if values[3] is not None:
+            tz = xml_timezone()
+            tz.SetOffset(values[3])
+            date_values.append(tz)
+        return datetime.date(*date_values)
+    else:
+        raise ValueError("\"%s\" isn't a valid date!" % value)
+
+
+def GetDateTime(attr, extract=True):
+    """
+    Function that extracts date and time from a tree node or a string
+    @param attr: tree node containing data to extract or data as a string
+    @param extract: attr is a tree node or not
+    @return: data as date and time
+    """
+    if extract:
+        value = GetAttributeValue(attr)
+    else:
+        value = attr
+    result = datetime_model.match(value)
+    if result:
+        values = result.groups()
+        datetime_values = [int(v) for v in values[:5]]
+        seconds = float(values[5])
+        datetime_values.extend([int(seconds), int((seconds % 1) * 1000000)])
+        if values[6] is not None:
+            tz = xml_timezone()
+            tz.SetOffset(values[6])
+            datetime_values.append(tz)
+        return datetime.datetime(*datetime_values)
+    else:
+        raise ValueError("\"%s\" isn't a valid datetime!" % value)
+
+
+def GenerateModelNameExtraction(type, model):
+    """
+    Function that generates an extraction function for string matching a model
+    @param type: name of the data type
+    @param model: model that data must match
+    @return: function generated
+    """
+    def GetModelName(attr, extract=True):
+        """
+        Function that extracts a string from a tree node or not and check that
+        string extracted or given match the model
+        @param attr: tree node containing data to extract or data as a string
+        @param extract: attr is a tree node or not
+        @return: data as a string if matching
+        """
+        if extract:
+            value = GetAttributeValue(attr)
+        else:
+            value = attr
+        result = model.match(value)
+        if not result:
+            raise ValueError("\"%s\" isn't a valid %s!" % (value, type))
+        return value
+    return GetModelName
+
+
+def GenerateLimitExtraction(min=None, max=None, unbounded=True):
+    """
+    Function that generates an extraction function for integer defining min and
+    max of integer value
+    @param min: minimum limit value
+    @param max: maximum limit value
+    @param unbounded: value can be "unbounded" or not
+    @return: function generated
+    """
+    def GetLimit(attr, extract=True):
+        """
+        Function that extracts a string from a tree node or not and check that
+        string extracted or given is in a list of values
+        @param attr: tree node containing data to extract or data as a string
+        @param extract: attr is a tree node or not
+        @return: data as a string
+        """
+        if extract:
+            value = GetAttributeValue(attr)
+        else:
+            value = attr
+        if value == "unbounded":
+            if unbounded:
+                return value
+            else:
+                raise ValueError("Member limit can't be defined to \"unbounded\"!")
+        try:
+            limit = int(value)
+        except:
+            raise ValueError("\"%s\" isn't a valid value for this member limit!" % value)
+        if limit < 0:
+            raise ValueError("Member limit can't be negative!")
+        elif min is not None and limit < min:
+            raise ValueError("Member limit can't be lower than \"%d\"!" % min)
+        elif max is not None and limit > max:
+            raise ValueError("Member limit can't be upper than \"%d\"!" % max)
+        return limit
+    return GetLimit
+
+
+def GenerateEnumeratedExtraction(type, list):
+    """
+    Function that generates an extraction function for enumerated values
+    @param type: name of the data type
+    @param list: list of possible values
+    @return: function generated
+    """
+    def GetEnumerated(attr, extract=True):
+        """
+        Function that extracts a string from a tree node or not and check that
+        string extracted or given is in a list of values
+        @param attr: tree node containing data to extract or data as a string
+        @param extract: attr is a tree node or not
+        @return: data as a string
+        """
+        if extract:
+            value = GetAttributeValue(attr)
+        else:
+            value = attr
+        if value in list:
+            return value
+        else:
+            raise ValueError("\"%s\" isn't a valid value for %s!" % \
+                             (value, type))
+    return GetEnumerated
+
+
+def GetNamespaces(attr, extract=True):
+    """
+    Function that extracts a list of namespaces from a tree node or a string
+    @param attr: tree node containing data to extract or data as a string
+    @param extract: attr is a tree node or not
+    @return: list of namespaces
+    """
+    if extract:
+        value = GetAttributeValue(attr)
+    else:
+        value = attr
+    if value == "":
+        return []
+    elif value == "##any" or value == "##other":
+        namespaces = [value]
+    else:
+        namespaces = []
+        for item in value.split(" "):
+            if item == "##targetNamespace" or item == "##local":
+                namespaces.append(item)
+            else:
+                result = URI_model.match(item)
+                if result is not None:
+                    namespaces.append(item)
+                else:
+                    raise ValueError("\"%s\" isn't a valid value for namespace!" % value)
+    return namespaces
+
+
+def GenerateGetList(type, list):
+    """
+    Function that generates an extraction function for a list of values
+    @param type: name of the data type
+    @param list: list of possible values
+    @return: function generated
+    """
+    def GetLists(attr, extract=True):
+        """
+        Function that extracts a list of values from a tree node or a string
+        @param attr: tree node containing data to extract or data as a string
+        @param extract: attr is a tree node or not
+        @return: list of values
+        """
+        if extract:
+            value = GetAttributeValue(attr)
+        else:
+            value = attr
+        if value == "":
+            return []
+        elif value == "#all":
+            return [value]
+        else:
+            values = []
+            for item in value.split(" "):
+                if item in list:
+                    values.append(item)
+                else:
+                    raise ValueError("\"%s\" isn't a valid value for %s!" % \
+                                     (value, type))
+            return values
+    return GetLists
+
+
+def GenerateModelNameListExtraction(type, model):
+    """
+    Function that generates an extraction function for list of string matching
+    a model
+    @param type: name of the data type
+    @param model: model that list elements must match
+    @return: function generated
+    """
+    def GetModelNameList(attr, extract=True):
+        """
+        Function that extracts a list of string from a tree node or not and
+        check that all extracted items match the model
+        @param attr: tree node containing data to extract or data as a string
+        @param extract: attr is a tree node or not
+        @return: data as a list of string if matching 
+        """
+        if extract:
+            value = GetAttributeValue(attr)
+        else:
+            value = attr
+        values = []
+        for item in value.split(" "):
+            result = model.match(item)
+            if result is not None:
+                values.append(item)
+            else:
+                raise ValueError("\"%s\" isn't a valid value for %s!" % \
+                                 (value, type))
+        return values
+    return GetModelNameList
+
+def GenerateAnyInfos():
+    def ExtractAny(tree):
+        return tree.data.encode("utf-8")
+    
+    def GenerateAny(value, name=None, indent=0):
+        try:
+            value = value.decode("utf-8")
+        except:
+            pass
+        return u'<![CDATA[%s]]>\n' % value
+        
+    return {
+        "type": COMPLEXTYPE, 
+        "extract": ExtractAny,
+        "generate": GenerateAny,
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    }
+
+def GenerateTagInfos(name):
+    def ExtractTag(tree):
+        if len(tree._attrs) > 0:
+            raise ValueError("\"%s\" musn't have attributes!" % name)
+        if len(tree.childNodes) > 0:
+            raise ValueError("\"%s\" musn't have children!" % name)
+        return None
+    
+    def GenerateTag(value, name=None, indent=0):
+        if name is not None:
+            ind1, ind2 = getIndent(indent, name)
+            return ind1 + "<%s/>\n" % name
+        else:
+            return ""
+    
+    return {
+        "type": TAG, 
+        "extract": ExtractTag,
+        "generate": GenerateTag,
+        "initial": lambda: None,
+        "check": lambda x: x == None
+    }
+    
+def GenerateContentInfos(factory, choices):
+    def GetContentInitial():
+        content_name, infos = choices[0]
+        if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
+            namespace, name = DecomposeQualifiedName(infos["elmt_type"])
+            infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+        if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
+            return {"name": content_name, 
+                    "value": map(infos["elmt_type"]["initial"], 
+                                 range(infos["minOccurs"]))}
+        else:
+            return {"name": content_name, 
+                    "value": infos["elmt_type"]["initial"]()}
+    
+    def CheckContent(value):
+        for content_name, infos in choices:
+            if content_name == value["name"]:
+                if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
+                    namespace, name = DecomposeQualifiedName(infos["elmt_type"])
+                    infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+                if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
+                    if isinstance(value["value"], ListType) and \
+                       infos["minOccurs"] <= len(value["value"]) <= infos["maxOccurs"]:
+                        return reduce(lambda x, y: x and y, 
+                                      map(infos["elmt_type"]["check"], 
+                                          value["value"]), 
+                                      True)
+                else:
+                    return infos["elmt_type"]["check"](value["value"])
+        return False
+        
+    def ExtractContent(tree, content):
+        for content_name, infos in choices:
+            if content_name == tree.nodeName:
+                if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
+                    namespace, name = DecomposeQualifiedName(infos["elmt_type"])
+                    infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+                if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
+                    if isinstance(content, ListType) and len(content) > 0 and \
+                       content[-1]["name"] == content_name:
+                        content_item = content.pop(-1)
+                        content_item["value"].append(infos["elmt_type"]["extract"](tree))
+                        return content_item
+                    elif not isinstance(content, ListType) and \
+                         content is not None and \
+                         content["name"] == content_name:
+                        return {"name": content_name, 
+                                "value": content["value"] + \
+                                         [infos["elmt_type"]["extract"](tree)]}
+                    else:
+                        return {"name": content_name, 
+                                "value": [infos["elmt_type"]["extract"](tree)]}
+                else:
+                    return {"name": content_name, 
+                            "value": infos["elmt_type"]["extract"](tree)}
+        raise ValueError("Invalid element \"%s\" for content!" % tree.nodeName)
+    
+    def GenerateContent(value, name=None, indent=0):
+        for content_name, infos in choices:
+            if content_name == value["name"]:
+                if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
+                    namespace, name = DecomposeQualifiedName(infos["elmt_type"])
+                    infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+                if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
+                    text = ""
+                    for item in value["value"]:
+                        text += infos["elmt_type"]["generate"](item, content_name, indent)
+                    return text
+                else:
+                    return infos["elmt_type"]["generate"](value["value"], content_name, indent)
+        return ""
+        
+    return {
+        "initial": GetContentInitial,
+        "check": CheckContent,
+        "extract": ExtractContent,
+        "generate": GenerateContent
+    }
+
+#-------------------------------------------------------------------------------
+#                           Structure extraction functions
+#-------------------------------------------------------------------------------
+
+
+def DecomposeQualifiedName(name):
+    result = QName_model.match(name)
+    if not result:
+        raise ValueError("\"%s\" isn't a valid QName value!" % name) 
+    parts = result.groups()[0].split(':')
+    if len(parts) == 1:
+        return None, parts[0]
+    return parts
+    
+def GenerateElement(element_name, attributes, elements_model, 
+                    accept_text=False):
+    def ExtractElement(factory, node):
+        attrs = factory.ExtractNodeAttrs(element_name, node, attributes)
+        children_structure = ""
+        children_infos = []
+        children = []
+        for child in node.childNodes:
+            if child.nodeName not in ["#comment", "#text"]:
+                namespace, childname = DecomposeQualifiedName(child.nodeName)
+                children_structure += "%s "%childname
+        result = elements_model.match(children_structure)
+        if not result:
+            raise ValueError("Invalid structure for \"%s\" children!. First element invalid." % node.nodeName)
+        valid = result.groups()[0]
+        if len(valid) < len(children_structure):
+            raise ValueError("Invalid structure for \"%s\" children!. Element number %d invalid." % (node.nodeName, len(valid.split(" ")) - 1))
+        for child in node.childNodes:
+            if child.nodeName != "#comment" and \
+               (accept_text or child.nodeName != "#text"):
+                if child.nodeName == "#text":
+                    children.append(GetAttributeValue(node))
+                else:
+                    namespace, childname = DecomposeQualifiedName(child.nodeName)
+                    infos = factory.GetQualifiedNameInfos(childname, namespace)
+                    if infos["type"] != SYNTAXELEMENT:
+                        raise ValueError("\"%s\" can't be a member child!" % name)
+                    if infos["extract"].has_key(element_name):
+                        children.append(infos["extract"][element_name](factory, child))
+                    else:
+                        children.append(infos["extract"]["default"](factory, child))
+        return node.nodeName, attrs, children
+    return ExtractElement
+
+
+"""
+Class that generate class from an XML Tree
+"""
+class ClassFactory:
+
+    def __init__(self, document, debug=False):
+        self.Document = document
+        self.Debug = debug
+        
+        # Dictionary for stocking Classes and Types definitions created from
+        # the XML tree
+        self.XMLClassDefinitions = {}
+        
+        self.DefinedNamespaces = {}
+        self.Namespaces = {}
+        self.SchemaNamespace = None
+        self.TargetNamespace = None
+        
+        self.CurrentCompilations = []
+        
+        # Dictionaries for stocking Classes and Types generated
+        self.ComputeAfter = []
+        self.ComputedClasses = {}
+        self.ComputedClassesInfos = {}
+        self.AlreadyComputed = {}
+
+    def GetQualifiedNameInfos(self, name, namespace=None, canbenone=False):
+        if namespace is None:
+            if self.Namespaces[self.SchemaNamespace].has_key(name):
+                return self.Namespaces[self.SchemaNamespace][name]
+            for space, elements in self.Namespaces.items():
+                if space != self.SchemaNamespace and elements.has_key(name):
+                    return elements[name]
+            parts = name.split("_", 1)
+            if len(parts) > 1:
+                group = self.GetQualifiedNameInfos(parts[0], namespace)
+                if group is not None and group["type"] == ELEMENTSGROUP:
+                    elements = []
+                    if group.has_key("elements"):
+                        elements = group["elements"]
+                    elif group.has_key("choices"):
+                        elements = group["choices"]
+                    for element in elements:
+                        if element["name"] == parts[1]:
+                            return element
+            if not canbenone:
+                raise ValueError("Unknown element \"%s\" for any defined namespaces!" % name)
+        elif self.Namespaces.has_key(namespace):
+            if self.Namespaces[namespace].has_key(name):
+                return self.Namespaces[namespace][name]
+            parts = name.split("_", 1)
+            if len(parts) > 1:
+                group = self.GetQualifiedNameInfos(parts[0], namespace)
+                if group is not None and group["type"] == ELEMENTSGROUP:
+                    elements = []
+                    if group.has_key("elements"):
+                        elements = group["elements"]
+                    elif group.has_key("choices"):
+                        elements = group["choices"]
+                    for element in elements:
+                        if element["name"] == parts[1]:
+                            return element
+            if not canbenone:
+                raise ValueError("Unknown element \"%s\" for namespace \"%s\"!" % (name, namespace))
+        elif not canbenone:
+            raise ValueError("Unknown namespace \"%s\"!" % namespace)
+        return None
+
+    def SplitQualifiedName(self, name, namespace=None, canbenone=False):
+        if namespace is None:
+            if self.Namespaces[self.SchemaNamespace].has_key(name):
+                return name, None
+            for space, elements in self.Namespaces.items():
+                if space != self.SchemaNamespace and elements.has_key(name):
+                    return name, None
+            parts = name.split("_", 1)
+            if len(parts) > 1:
+                group = self.GetQualifiedNameInfos(parts[0], namespace)
+                if group is not None and group["type"] == ELEMENTSGROUP:
+                    elements = []
+                    if group.has_key("elements"):
+                        elements = group["elements"]
+                    elif group.has_key("choices"):
+                        elements = group["choices"]
+                    for element in elements:
+                        if element["name"] == parts[1]:
+                            return part[1], part[0]
+            if not canbenone:
+                raise ValueError("Unknown element \"%s\" for any defined namespaces!" % name)
+        elif self.Namespaces.has_key(namespace):
+            if self.Namespaces[namespace].has_key(name):
+                return name, None
+            parts = name.split("_", 1)
+            if len(parts) > 1:
+                group = self.GetQualifiedNameInfos(parts[0], namespace)
+                if group is not None and group["type"] == ELEMENTSGROUP:
+                    elements = []
+                    if group.has_key("elements"):
+                        elements = group["elements"]
+                    elif group.has_key("choices"):
+                        elements = group["choices"]
+                    for element in elements:
+                        if element["name"] == parts[1]:
+                            return parts[1], parts[0]
+            if not canbenone:
+                raise ValueError("Unknown element \"%s\" for namespace \"%s\"!" % (name, namespace))
+        elif not canbenone:
+            raise ValueError("Unknown namespace \"%s\"!" % namespace)
+        return None, None
+
+    def ExtractNodeAttrs(self, element_name, node, valid_attrs):
+        attrs = {}
+        for qualified_name, attr in node._attrs.items():
+            namespace, name =  DecomposeQualifiedName(qualified_name)
+            if name in valid_attrs:
+                infos = self.GetQualifiedNameInfos(name, namespace)
+                if infos["type"] != SYNTAXATTRIBUTE:
+                    raise ValueError("\"%s\" can't be a member attribute!" % name)
+                elif name in attrs:
+                    raise ValueError("\"%s\" attribute has been twice!" % name)
+                elif element_name in infos["extract"]:
+                    attrs[name] = infos["extract"][element_name](attr)
+                else:
+                    attrs[name] = infos["extract"]["default"](attr)
+            elif namespace == "xmlns":
+                infos = self.GetQualifiedNameInfos("anyURI", self.SchemaNamespace)
+                self.DefinedNamespaces[infos["extract"](attr)] = name
+            else:
+                raise ValueError("Invalid attribute \"%s\" for member \"%s\"!" % (qualified_name, node.nodeName))
+        for attr in valid_attrs:
+            if attr not in attrs and \
+               self.Namespaces[self.SchemaNamespace].has_key(attr) and \
+               self.Namespaces[self.SchemaNamespace][attr].has_key("default"):
+                if self.Namespaces[self.SchemaNamespace][attr]["default"].has_key(element_name):
+                    default = self.Namespaces[self.SchemaNamespace][attr]["default"][element_name]
+                else:
+                    default = self.Namespaces[self.SchemaNamespace][attr]["default"]["default"]
+                if default is not None:
+                    attrs[attr] = default
+        return attrs
+
+    def ReduceElements(self, elements, schema=False):
+        result = []
+        for child_infos in elements:
+            if child_infos[1].has_key("name") and schema:
+                self.CurrentCompilations.append(child_infos[1]["name"])
+            namespace, name = DecomposeQualifiedName(child_infos[0])
+            infos = self.GetQualifiedNameInfos(name, namespace)
+            if infos["type"] != SYNTAXELEMENT:
+                raise ValueError("\"%s\" can't be a member child!" % name)
+            result.append(infos["reduce"](self, child_infos[1], child_infos[2]))
+            if child_infos[1].has_key("name") and schema:
+                self.CurrentCompilations.pop(-1)
+        annotations = []
+        children = []
+        for element in result:
+            if element["type"] == "annotation":
+                annotations.append(element)
+            else:
+                children.append(element)
+        return annotations, children
+
+    def AddComplexType(self, typename, infos):
+        if not self.XMLClassDefinitions.has_key(typename):
+            self.XMLClassDefinitions[typename] = infos
+        else:
+            raise ValueError("\"%s\" class already defined. Choose another name!" % typename)
+
+    def ParseSchema(self):
+        pass
+
+    def ExtractTypeInfos(self, name, parent, typeinfos):
+        if isinstance(typeinfos, (StringType, UnicodeType)):
+            namespace, name = DecomposeQualifiedName(typeinfos)
+            infos = self.GetQualifiedNameInfos(name, namespace)
+            if infos["type"] == COMPLEXTYPE:
+                name, parent = self.SplitQualifiedName(name, namespace)
+                result = self.CreateClass(name, parent, infos)
+                if result is not None and not isinstance(result, (UnicodeType, StringType)):
+                    self.Namespaces[self.TargetNamespace][result["name"]] = result
+                return result
+            elif infos["type"] == ELEMENT and infos["elmt_type"]["type"] == COMPLEXTYPE:
+                name, parent = self.SplitQualifiedName(name, namespace)
+                result = self.CreateClass(name, parent, infos["elmt_type"])
+                if result is not None and not isinstance(result, (UnicodeType, StringType)):
+                    self.Namespaces[self.TargetNamespace][result["name"]] = result
+                return result
+            else:
+                return infos
+        elif typeinfos["type"] == COMPLEXTYPE:
+            return self.CreateClass(name, parent, typeinfos)
+        elif typeinfos["type"] == SIMPLETYPE:
+            return typeinfos
+            
+    """
+    Methods that generates the classes
+    """
+    def CreateClasses(self):
+        self.ParseSchema()
+        for name, infos in self.Namespaces[self.TargetNamespace].items():
+            if infos["type"] == ELEMENT:
+                if not isinstance(infos["elmt_type"], (UnicodeType, StringType)) and \
+                   infos["elmt_type"]["type"] == COMPLEXTYPE:
+                    self.ComputeAfter.append((name, None, infos["elmt_type"], True))
+                    while len(self.ComputeAfter) > 0:
+                        result = self.CreateClass(*self.ComputeAfter.pop(0))
+                        if result is not None and not isinstance(result, (UnicodeType, StringType)):
+                            self.Namespaces[self.TargetNamespace][result["name"]] = result
+            elif infos["type"] == COMPLEXTYPE:
+                self.ComputeAfter.append((name, None, infos))
+                while len(self.ComputeAfter) > 0:
+                    result = self.CreateClass(*self.ComputeAfter.pop(0))
+                    if result is not None and \
+                       not isinstance(result, (UnicodeType, StringType)):
+                        self.Namespaces[self.TargetNamespace][result["name"]] = result
+            elif infos["type"] == ELEMENTSGROUP:
+                elements = []
+                if infos.has_key("elements"):
+                    elements = infos["elements"]
+                elif infos.has_key("choices"):
+                    elements = infos["choices"]
+                for element in elements:
+                    if not isinstance(element["elmt_type"], (UnicodeType, StringType)) and \
+                       element["elmt_type"]["type"] == COMPLEXTYPE:
+                        self.ComputeAfter.append((element["name"], infos["name"], element["elmt_type"]))
+                        while len(self.ComputeAfter) > 0:
+                            result = self.CreateClass(*self.ComputeAfter.pop(0))
+                            if result is not None and \
+                               not isinstance(result, (UnicodeType, StringType)):
+                                self.Namespaces[self.TargetNamespace][result["name"]] = result
+        return self.ComputedClasses
+
+    def CreateClass(self, name, parent, classinfos, baseclass = False):
+        if parent is not None:
+            classname = "%s_%s" % (parent, name)
+        else:
+            classname = name
+        
+        # Checks that classe haven't been generated yet
+        if self.AlreadyComputed.get(classname, False):
+            if baseclass:
+                self.AlreadyComputed[classname].IsBaseClass = baseclass
+            return self.ComputedClassesInfos.get(classname, None)
+        
+        # If base classes haven't been generated
+        bases = []
+        if classinfos.has_key("base"):
+            result = self.ExtractTypeInfos("base", name, classinfos["base"])
+            if result is None:
+                namespace, base_name = DecomposeQualifiedName(classinfos["base"])                
+                if self.AlreadyComputed.get(base_name, False):
+                    self.ComputeAfter.append((name, parent, classinfos))
+                    if self.TargetNamespace is not None:
+                        return "%s:%s" % (self.TargetNamespace, classname)
+                    else:
+                        return classname
+            elif result is not None:
+                classinfos["base"] = self.ComputedClasses[result["name"]]
+                bases.append(self.ComputedClasses[result["name"]])
+        bases.append(object)
+        bases = tuple(bases)
+        classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass}
+        
+        self.AlreadyComputed[classname] = True
+        
+        for attribute in classinfos["attributes"]:
+            infos = self.ExtractTypeInfos(attribute["name"], name, attribute["attr_type"])
+            if infos is not None:                    
+                if infos["type"] != SIMPLETYPE:
+                    raise ValueError("\"%s\" type is not a simple type!" % attribute["attr_type"])
+                attrname = attribute["name"]
+                if attribute["use"] == "optional":
+                    classmembers[attrname] = None
+                    classmembers["add%s"%attrname] = generateAddMethod(attrname, self, attribute)
+                    classmembers["delete%s"%attrname] = generateDeleteMethod(attrname)
+                else:
+                    classmembers[attrname] = infos["initial"]()
+                classmembers["set%s"%attrname] = generateSetMethod(attrname)
+                classmembers["get%s"%attrname] = generateGetMethod(attrname)
+            else:
+                raise ValueError("\"%s\" type unrecognized!" % attribute["attr_type"])
+            attribute["attr_type"] = infos
+            
+        for element in classinfos["elements"]:
+            if element["type"] == CHOICE:
+                elmtname = element["name"]
+                choices = []
+                for choice in element["choices"]:
+                    if choice["elmt_type"] == "tag":
+                        choice["elmt_type"] = GenerateTagInfos(choice["name"])
+                    else:
+                        infos = self.ExtractTypeInfos(choice["name"], name, choice["elmt_type"])
+                        if infos is not None:
+                            choice["elmt_type"] = infos
+                    choices.append((choice["name"], choice))
+                classmembers["get%schoices"%elmtname] = generateGetChoicesMethod(element["choices"])
+                if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1:
+                    classmembers["append%sbytype" % elmtname] = generateAppendChoiceByTypeMethod(element["maxOccurs"], self, element["choices"])
+                    classmembers["insert%sbytype" % elmtname] = generateInsertChoiceByTypeMethod(element["maxOccurs"], self, element["choices"])
+                else:
+                    classmembers["set%sbytype" % elmtname] = generateSetChoiceByTypeMethod(self, element["choices"])
+                infos = GenerateContentInfos(self, choices)
+            elif element["type"] == ANY:
+                elmtname = element["name"] = "text"
+                element["minOccurs"] = element["maxOccurs"] = 1
+                infos = GenerateAnyInfos()
+            else:
+                elmtname = element["name"]
+                infos = self.ExtractTypeInfos(element["name"], name, element["elmt_type"])
+            if infos is not None:
+                element["elmt_type"] = infos
+            if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1:
+                classmembers[elmtname] = []
+                classmembers["append%s" % elmtname] = generateAppendMethod(elmtname, element["maxOccurs"], self, element)
+                classmembers["insert%s" % elmtname] = generateInsertMethod(elmtname, element["maxOccurs"], self, element)
+                classmembers["remove%s" % elmtname] = generateRemoveMethod(elmtname, element["minOccurs"])
+                classmembers["count%s" % elmtname] = generateCountMethod(elmtname)
+            else:
+                if element["minOccurs"] == 0:
+                    classmembers[elmtname] = None
+                    classmembers["add%s" % elmtname] = generateAddMethod(elmtname, self, element)
+                    classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname)
+                elif not isinstance(element["elmt_type"], (UnicodeType, StringType)):
+                    classmembers[elmtname] = element["elmt_type"]["initial"]()
+                else:
+                    classmembers[elmtname] = None
+            classmembers["set%s" % elmtname] = generateSetMethod(elmtname)
+            classmembers["get%s" % elmtname] = generateGetMethod(elmtname)
+            
+        classmembers["__init__"] = generateInitMethod(self, classinfos)
+        classmembers["__setattr__"] = generateSetattrMethod(self, classinfos)
+        classmembers["getStructure"] = generateStructureMethod(classinfos)
+        classmembers["loadXMLTree"] = generateLoadXMLTree(self, classinfos)
+        classmembers["generateXMLText"] = generateGenerateXMLText(self, classinfos)
+        classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos)
+        classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos)
+        classmembers["setElementValue"] = generateSetElementValue(self, classinfos)
+        classmembers["singleLineAttributes"] = True
+        classmembers["compatibility"] = lambda x, y: None
+        
+        class_definition = classobj(str(classname), bases, classmembers)
+        class_infos = {"type": COMPILEDCOMPLEXTYPE,
+                "name": classname,
+                "check": generateClassCheckFunction(class_definition),
+                "initial": generateClassCreateFunction(class_definition),
+                "extract": generateClassExtractFunction(class_definition),
+                "generate": class_definition.generateXMLText}
+        
+        self.ComputedClasses[classname] = class_definition
+        self.ComputedClassesInfos[classname] = class_infos
+        
+        return class_infos
+
+    """
+    Methods that print the classes generated
+    """
+    def PrintClasses(self):
+        items = self.ComputedClasses.items()
+        items.sort()
+        for classname, xmlclass in items:
+            print "%s : %s" % (classname, str(xmlclass))
+        
+    def PrintClassNames(self):
+        classnames = self.XMLClassDefinitions.keys()
+        classnames.sort()
+        for classname in classnames:
+            print classname
+
+"""
+Method that generate the method for checking a class instance
+"""
+def generateClassCheckFunction(class_definition):
+    def classCheckfunction(instance):
+        return isinstance(instance, class_definition)
+    return classCheckfunction
+
+"""
+Method that generate the method for creating a class instance
+"""
+def generateClassCreateFunction(class_definition):
+    def classCreatefunction():
+        return class_definition()
+    return classCreatefunction
+
+"""
+Method that generate the method for extracting a class instance
+"""
+def generateClassExtractFunction(class_definition):
+    def classExtractfunction(node):
+        instance = class_definition()
+        instance.loadXMLTree(node)
+        return instance
+    return classExtractfunction
+
+"""
+Method that generate the method for loading an xml tree by following the
+attributes list defined
+"""
+def generateSetattrMethod(factory, classinfos):
+    attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
+    optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
+    elements = dict([(element["name"], element) for element in classinfos["elements"]])
+    
+    def setattrMethod(self, name, value):
+        if attributes.has_key(name):
+            if isinstance(attributes[name]["attr_type"], (UnicodeType, StringType)):
+                namespace, name = DecomposeQualifiedName(infos)
+                attributes[name]["attr_type"] = factory.GetQualifiedNameInfos(name, namespace)
+            if value is None:
+                if optional_attributes.get(name, False):
+                    return object.__setattr__(self, name, None)
+                else:
+                    raise ValueError("Attribute '%s' isn't optional." % name)
+            elif attributes[name].has_key("fixed") and value != attributes[name]["fixed"]:
+                raise ValueError, "Value of attribute '%s' can only be '%s'."%(name, str(attributes[name]["fixed"]))
+            elif attributes[name]["attr_type"]["check"](value):
+                return object.__setattr__(self, name, value)
+            else:
+                raise ValueError("Invalid value for attribute '%s'." % (name))
+        elif elements.has_key(name):
+            if isinstance(elements[name]["elmt_type"], (UnicodeType, StringType)):
+                namespace, name = DecomposeQualifiedName(infos)
+                elements[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+            if value is None:
+                if elements[name]["minOccurs"] == 0 and elements[name]["maxOccurs"] == 1:
+                    return object.__setattr__(self, name, None)
+                else:
+                    raise ValueError("Attribute '%s' isn't optional." % name)
+            elif elements[name]["maxOccurs"] == "unbounded" or elements[name]["maxOccurs"] > 1:
+                if isinstance(value, ListType) and elements[name]["minOccurs"] <= len(value) <= elements[name]["maxOccurs"]:
+                    if reduce(lambda x, y: x and y, map(elements[name]["elmt_type"]["check"], value), True):
+                        return object.__setattr__(self, name, value)
+                raise ValueError, "Attribute '%s' must be a list of valid elements."%name
+            elif elements[name].has_key("fixed") and value != elements[name]["fixed"]:
+                raise ValueError("Value of attribute '%s' can only be '%s'." % (name, str(elements[name]["fixed"])))
+            elif elements[name]["elmt_type"]["check"](value):
+                return object.__setattr__(self, name, value)
+            else:
+                raise ValueError("Invalid value for attribute '%s'." % (name))
+        elif classinfos.has_key("base"):
+            return classinfos["base"].__setattr__(self, name, value)
+        elif self.__class__.__dict__.has_key(name):
+            return object.__setattr__(self, name, value)
+        else:
+            raise AttributeError("'%s' can't have an attribute '%s'." % (self.__class__.__name__, name))
+        
+    return setattrMethod
+
+"""
+Method that generate the method for generating the xml tree structure model by 
+following the attributes list defined
+"""
+def ComputeMultiplicity(name, infos):
+    if infos["minOccurs"] == 0:
+        if infos["maxOccurs"] == "unbounded":
+            return "(?:%s)*" % name
+        elif infos["maxOccurs"] == 1:
+            return "(?:%s)?" % name
+        else:
+            return "(?:%s){,%d}" % (name, infos["maxOccurs"])
+    elif infos["minOccurs"] == 1:
+        if infos["maxOccurs"] == "unbounded":
+            return "(?:%s)+" % name
+        elif infos["maxOccurs"] == 1:
+            return name
+        else:
+            return "(?:%s){1,%d}" % (name, infos["maxOccurs"])
+    else:
+        if infos["maxOccurs"] == "unbounded":
+            return "(?:%s){%d,}" % (name, infos["minOccurs"], name)
+        else:
+            return "(?:%s){%d,%d}" % (name, infos["minOccurs"], 
+                                       infos["maxOccurs"])
+
+def generateStructureMethod(classinfos):
+    elements = []
+    for element in classinfos["elements"]:
+        if element["type"] == ANY:
+            elements.append(ComputeMultiplicity("(?:#cdata-section )?", element))
+        elif element["type"] == CHOICE:
+            elements.append(ComputeMultiplicity(
+                "|".join([ComputeMultiplicity("%s " % infos["name"], infos) for infos in element["choices"]]), 
+                element))
+        else:
+            elements.append(ComputeMultiplicity("%s " % element["name"], element))
+    if classinfos.get("order", True) or len(elements) == 0:
+        structure = "".join(elements)
+    else:
+        raise ValueError("XSD structure not yet supported!")
+    
+    def getStructureMethod(self):
+        if classinfos.has_key("base"):
+            return classinfos["base"].getStructure(self) + structure
+        return structure
+    return getStructureMethod
+
+"""
+Method that generate the method for loading an xml tree by following the
+attributes list defined
+"""
+def generateLoadXMLTree(factory, classinfos):
+    attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
+    elements = dict([(element["name"], element) for element in classinfos["elements"]])
+    
+    def loadXMLTreeMethod(self, tree, extras=[], derived=False):
+        self.compatibility(tree)
+        if not derived:
+            children_structure = ""
+            for node in tree.childNodes:
+                if node.nodeName not in ["#comment", "#text"]:
+                    children_structure += "%s " % node.nodeName
+            structure_model = re.compile("(%s)$" % self.getStructure())
+            result = structure_model.match(children_structure)
+            if not result:
+                raise ValueError("Invalid structure for \"%s\" children!." % tree.nodeName)
+        required_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "required"])
+        if classinfos.has_key("base"):
+            extras.extend([attr["name"] for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
+            classinfos["base"].loadXMLTree(self, tree, extras, True)
+        for attrname, attr in tree._attrs.iteritems():
+            if attributes.has_key(attrname):
+                if isinstance(attributes[attrname]["attr_type"], (UnicodeType, StringType)):
+                    namespace, name = DecomposeQualifiedName(infos)
+                    attributes[attrname]["attr_type"] = factory.GetQualifiedNameInfos(name, namespace)
+                setattr(self, attrname, attributes[attrname]["attr_type"]["extract"](attr))
+            elif not classinfos.has_key("base") and attrname not in extras:
+                raise ValueError("Invalid attribute \"%s\" for \"%s\" element!" % (attrname, tree.nodeName))
+            required_attributes.pop(attrname, None)
+        if len(required_attributes) > 0:
+            raise ValueError("Required attributes %s missing for \"%s\" element!" % (", ".join(["\"%s\""%name for name in required_attributes]), tree.nodeName))
+        first = {}
+        for node in tree.childNodes:
+            name = node.nodeName
+            if name in ["#text", "#comment"]:
+                continue
+            if elements.has_key(name):
+                if isinstance(elements[name]["elmt_type"], (UnicodeType, StringType)):
+                    namespace, name = DecomposeQualifiedName(infos)
+                    elements[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+                if elements[name]["maxOccurs"] == "unbounded" or elements[name]["maxOccurs"] > 1:
+                    if first.get(name, True):
+                        setattr(self, name, [elements[name]["elmt_type"]["extract"](node)])
+                        first[name] = False
+                    else:
+                        getattr(self, name).append(elements[name]["elmt_type"]["extract"](node))
+                else:
+                    setattr(self, name, elements[name]["elmt_type"]["extract"](node))
+            elif name == "#cdata-section" and elements.has_key("text"):
+                if elements["text"]["maxOccurs"] == "unbounded" or elements["text"]["maxOccurs"] > 1:
+                    if first.get("text", True):
+                        setattr(self, "text", [elements["text"]["elmt_type"]["extract"](node)])
+                        first["text"] = False
+                    else:
+                        getattr(self, "text").append(elements["text"]["elmt_type"]["extract"](node))
+                else:
+                    setattr(self, "text", elements["text"]["elmt_type"]["extract"](node))
+            elif elements.has_key("content"):
+                content = getattr(self, "content")
+                if elements["content"]["maxOccurs"] == "unbounded" or elements["content"]["maxOccurs"] > 1:
+                    if first.get("content", True):
+                        setattr(self, "content", [elements["content"]["elmt_type"]["extract"](node, None)])
+                        first["content"] = False
+                    else:
+                        content.append(elements["content"]["elmt_type"]["extract"](node, content))
+                else:
+                    setattr(self, "content", elements["content"]["elmt_type"]["extract"](node, content))
+    return loadXMLTreeMethod
+        
+
+"""
+Method that generates the method for generating an xml text by following the
+attributes list defined
+"""
+def generateGenerateXMLText(factory, classinfos):
+    def generateXMLTextMethod(self, name, indent=0, extras={}, derived=False):
+        ind1, ind2 = getIndent(indent, name)
+        if not derived:
+            text = ind1 + u'<%s' % name
+        else:
+            text = u''
+        
+        first = True
+        if not classinfos.has_key("base"):
+            for attr, value in extras.items():
+                if not first and not self.singleLineAttributes:
+                    text += u'\n%s' % (ind2)
+                text += u' %s=%s' % (attr, quoteattr(value))
+                first = False
+            extras.clear()
+        for attr in classinfos["attributes"]:
+            if attr["use"] != "prohibited":
+                if isinstance(attr["attr_type"], (UnicodeType, StringType)):
+                    namespace, name = DecomposeQualifiedName(infos)
+                    attr["attr_type"] = factory.GetQualifiedNameInfos(name, namespace)
+                value = getattr(self, attr["name"], None)
+                if value != None:
+                    computed_value = attr["attr_type"]["generate"](value)
+                else:
+                    computed_value = None
+                if attr["use"] != "optional" or (value != None and \
+                   computed_value != attr.get("default", attr["attr_type"]["generate"](attr["attr_type"]["initial"]()))):
+                    if classinfos.has_key("base"):
+                        extras[attr["name"]] = computed_value
+                    else:
+                        if not first and not self.singleLineAttributes:
+                            text += u'\n%s' % (ind2)
+                        text += ' %s=%s' % (attr["name"], quoteattr(computed_value))
+                    first = False
+        if classinfos.has_key("base"):
+            first, new_text = classinfos["base"].generateXMLText(self, name, indent, extras, True)
+            text += new_text
+        else:
+            first = True
+        for element in classinfos["elements"]:
+            if isinstance(element["elmt_type"], (UnicodeType, StringType)):
+                namespace, name = DecomposeQualifiedName(infos)
+                element["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+            value = getattr(self, element["name"], None)
+            if element["minOccurs"] == 0 and element["maxOccurs"] == 1:
+                if value is not None:
+                    if first:
+                        text += u'>\n'
+                        first = False
+                    text += element["elmt_type"]["generate"](value, element["name"], indent + 1)
+            elif element["minOccurs"] == 1 and element["maxOccurs"] == 1:
+                if first:
+                    text += u'>\n'
+                    first = False
+                text += element["elmt_type"]["generate"](value, element["name"], indent + 1)
+            else:
+                if first and len(value) > 0:
+                    text += u'>\n'
+                    first = False
+                for item in value:
+                    text += element["elmt_type"]["generate"](item, element["name"], indent + 1)
+        if not derived:
+            if first:
+                text += u'/>\n'
+            else:
+                text += ind1 + u'</%s>\n' % (name)
+            return text
+        else:
+            return first, text
+    return generateXMLTextMethod
+
+def gettypeinfos(name, facets):
+    if facets.has_key("enumeration") and facets["enumeration"][0] is not None:
+        return facets["enumeration"][0]
+    elif facets.has_key("maxInclusive"):
+        limits = {"max" : None, "min" : None}
+        if facets["maxInclusive"][0] is not None:
+            limits["max"] = facets["maxInclusive"][0]
+        elif facets["maxExclusive"][0] is not None:
+            limits["max"] = facets["maxExclusive"][0] - 1
+        if facets["minInclusive"][0] is not None:
+            limits["min"] = facets["minInclusive"][0]
+        elif facets["minExclusive"][0] is not None:
+            limits["min"] = facets["minExclusive"][0] + 1
+        if limits["max"] is not None or limits["min"] is not None:
+            return limits
+    return name
+
+def generateGetElementAttributes(factory, classinfos):
+    def getElementAttributes(self):
+        attr_list = []
+        if classinfos.has_key("base"):
+            attr_list.extend(classinfos["base"].getElementAttributes(self))
+        for attr in classinfos["attributes"]:
+            if attr["use"] != "prohibited":
+                attr_params = {"name" : attr["name"], "use" : attr["use"], 
+                    "type" : gettypeinfos(attr["attr_type"]["basename"], attr["attr_type"]["facets"]),
+                    "value" : getattr(self, attr["name"], "")}
+                attr_list.append(attr_params)
+        return attr_list
+    return getElementAttributes
+
+def generateGetElementInfos(factory, classinfos):
+    attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
+    elements = dict([(element["name"], element) for element in classinfos["elements"]])
+    
+    def getElementInfos(self, name, path=None, derived=False):
+        attr_type = "element"
+        value = None
+        use = "required"
+        children = []
+        if path is not None:
+            parts = path.split(".", 1)
+            if attributes.has_key(parts[0]):
+                if len(parts) != 0:
+                    raise ValueError("Wrong path!")
+                attr_type = gettypeinfos(attributes[parts[0]]["attr_type"]["basename"], 
+                                         attributes[parts[0]]["attr_type"]["facets"])
+                value = getattr(self, parts[0], "")
+            elif elements.has_key(parts[0]):
+                if elements[parts[0]]["elmt_type"]["type"] == SIMPLETYPE:
+                    if len(parts) != 0:
+                        raise ValueError("Wrong path!")
+                    attr_type = gettypeinfos(elements[parts[0]]["elmt_type"]["basename"], 
+                                             elements[parts[0]]["elmt_type"]["facets"])
+                    value = getattr(self, parts[0], "")
+                elif parts[0] == "content":
+                    return self.content["value"].getElementInfos(self.content["name"], path)
+                else:
+                    attr = getattr(self, parts[0], None)
+                    if attr is None:
+                        raise ValueError("Wrong path!")
+                    if len(parts) == 1:
+                        return attr.getElementInfos(parts[0])
+                    else:
+                        return attr.getElementInfos(parts[0], parts[1])
+            else:
+                raise ValueError("Wrong path!")
+        else:
+            if not derived:
+                children.extend(self.getElementAttributes())
+            if classinfos.has_key("base"):
+                children.extend(classinfos["base"].getElementInfos(self, name, derived=True)["children"])
+            for element_name, element in elements.items():
+                if element["minOccurs"] == 0:
+                    use = "optional"
+                if element_name == "content":
+                    attr_type = [(choice["name"], None) for choice in element["choices"]]
+                    if self.content is None:
+                        value = ""
+                    else:
+                        value = self.content["name"]
+                        if self.content["value"] is not None:
+                            children.extend(self.content["value"].getElementInfos(self.content["name"])["children"])
+                elif element["elmt_type"]["type"] == SIMPLETYPE:
+                    children.append({"name": element_name, "require": element["minOccurs"] != 0, 
+                        "type": gettypeinfos(element["elmt_type"]["basename"], 
+                                              element["elmt_type"]["facets"]),
+                        "value": getattr(self, element_name, None)})
+                else:
+                    instance = getattr(self, element_name, None)
+                    if instance is None:
+                        instance = element["elmt_type"]["initial"]()
+                    children.append(instance.getElementInfos(element_name))
+        return {"name": name, "type": attr_type, "value": value, "use": use, "children": children}
+    return getElementInfos
+
+def generateSetElementValue(factory, classinfos):
+    attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
+    elements = dict([(element["name"], element) for element in classinfos["elements"]])
+    
+    def setElementValue(self, path, value):
+        if path is not None:
+            parts = path.split(".", 1)
+            if attributes.has_key(parts[0]):
+                if len(parts) != 1:
+                    raise ValueError("Wrong path!")
+                if attributes[parts[0]]["attr_type"]["basename"] == "boolean":
+                    setattr(self, parts[0], value)
+                else:
+                    setattr(self, parts[0], attributes[parts[0]]["attr_type"]["extract"](value, False))
+            elif elements.has_key(parts[0]):
+                if elements[parts[0]]["elmt_type"]["type"] == SIMPLETYPE:
+                    if len(parts) != 1:
+                        raise ValueError("Wrong path!")
+                    if elements[parts[0]]["elmt_type"]["basename"] == "boolean":
+                        setattr(self, parts[0], value)
+                    else:
+                        setattr(self, parts[0], elements[parts[0]]["elmt_type"]["extract"](value, False))
+                else:
+                    instance = getattr(self, parts[0], None)
+                    if instance != None:
+                        if len(parts) > 1:
+                            instance.setElementValue(parts[1], value)
+                        else:
+                            instance.setElementValue(None, value)
+            elif elements.has_key("content"):
+                if len(parts) > 0:
+                    self.content["value"].setElementValue(path, value)
+            elif classinfos.has_key("base"):
+                classinfos["base"].setElementValue(self, path, value)
+        elif elements.has_key("content"):
+            if value == "":
+                if elements["content"]["minOccurs"] == 0:
+                    self.setcontent(None)
+                else:
+                    raise ValueError("\"content\" element is required!")
+            else:
+                self.setcontentbytype(value)
+    return setElementValue
+
+"""
+Methods that generates the different methods for setting and getting the attributes
+"""
+def generateInitMethod(factory, classinfos):
+    def initMethod(self):
+        if classinfos.has_key("base"):
+            classinfos["base"].__init__(self)
+        for attribute in classinfos["attributes"]:
+            if isinstance(attribute["attr_type"], (UnicodeType, StringType)):
+                namespace, name = DecomposeQualifiedName(attribute["attr_type"])
+                attribute["attr_type"] = factory.GetQualifiedNameInfos(name, namespace)
+            if attribute["use"] == "required":
+                setattr(self, attribute["name"], attribute["attr_type"]["initial"]())
+            elif attribute["use"] == "optional":
+                if attribute.has_key("default"):
+                    setattr(self, attribute["name"], attribute["attr_type"]["extract"](attribute["default"], False))
+                else:
+                    setattr(self, attribute["name"], None)
+        for element in classinfos["elements"]:
+            if isinstance(element["elmt_type"], (UnicodeType, StringType)):
+                namespace, name = DecomposeQualifiedName(element["elmt_type"])
+                element["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+            if element["minOccurs"] == 0 and element["maxOccurs"] == 1:
+                if "default" in element:
+                    setattr(self, element["name"], element["elmt_type"]["extract"](element["default"], False))
+                else:
+                    setattr(self, element["name"], None)
+            elif element["minOccurs"] == 1 and element["maxOccurs"] == 1:
+                setattr(self, element["name"], element["elmt_type"]["initial"]())
+            else:
+                value = []
+                for i in xrange(element["minOccurs"]):
+                    value.append(element["elmt_type"]["initial"]())
+                setattr(self, element["name"], value)
+    return initMethod
+
+def generateSetMethod(attr):
+    def setMethod(self, value):
+        setattr(self, attr, value)
+    return setMethod
+
+def generateGetMethod(attr):
+    def getMethod(self):
+        return getattr(self, attr, None)
+    return getMethod
+
+def generateAddMethod(attr, factory, infos):
+    def addMethod(self):
+        if infos["type"] == ATTRIBUTE:
+            if isinstance(infos["attr_type"], (UnicodeType, StringType)):
+                namespace, name = DecomposeQualifiedName(infos)
+                infos["attr_type"] = factory.GetQualifiedNameInfos(name, namespace)
+            initial = infos["attr_type"]["initial"]
+            extract = infos["attr_type"]["extract"]
+        elif infos["type"] == ELEMENT:
+            if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
+                namespace, name = DecomposeQualifiedName(infos)
+                infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+            initial = infos["elmt_type"]["initial"]
+            extract = infos["elmt_type"]["extract"]
+        else:
+            raise ValueError("Invalid class attribute!")
+        if infos.has_key("default"):
+            setattr(self, attr, extract(infos["default"], False))
+        else:
+            setattr(self, attr, initial())
+    return addMethod
+
+def generateDeleteMethod(attr):
+    def deleteMethod(self):
+        setattr(self, attr, None)
+    return deleteMethod
+
+def generateAppendMethod(attr, maxOccurs, factory, infos):
+    def appendMethod(self, value):
+        if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
+            namespace, name = DecomposeQualifiedName(infos)
+            infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+        attr_list = getattr(self, attr)
+        if maxOccurs == "unbounded" or len(attr_list) < maxOccurs:
+            if infos["elmt_type"]["check"](value):
+                attr_list.append(value)
+            else:
+                raise ValueError("\"%s\" value isn't valid!" % attr)
+        else:
+            raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr))
+    return appendMethod
+
+def generateInsertMethod(attr, maxOccurs, factory, infos):
+    def insertMethod(self, index, value):
+        if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
+            namespace, name = DecomposeQualifiedName(infos)
+            infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+        attr_list = getattr(self, attr)
+        if maxOccurs == "unbounded" or len(attr_list) < maxOccurs:
+            if infos["elmt_type"]["check"](value):
+                attr_list.insert(index, value)
+            else:
+                raise ValueError("\"%s\" value isn't valid!" % attr)
+        else:
+            raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr))
+    return insertMethod
+
+def generateGetChoicesMethod(choice_types):
+    def getChoicesMethod(self):
+        return [choice["name"] for choice in choice_types]
+    return getChoicesMethod
+
+def generateSetChoiceByTypeMethod(factory, choice_types):
+    choices = dict([(choice["name"], choice) for choice in choice_types])
+    def setChoiceMethod(self, type):
+        if not choices.has_key(type):
+            raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
+        if isinstance(choices[type]["elmt_type"], (UnicodeType, StringType)):
+            namespace, name = DecomposeQualifiedName(choices[type]["elmt_type"])
+            choices[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+        new_element = choices[type]["elmt_type"]["initial"]()
+        self.content = {"name": type, "value": new_element}
+        return new_element
+    return setChoiceMethod
+
+def generateAppendChoiceByTypeMethod(maxOccurs, factory, choice_types):
+    choices = dict([(choice["name"], choice) for choice in choice_types])
+    def appendChoiceMethod(self, type):
+        if not choices.has_key(type):
+            raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
+        if isinstance(choices[type]["elmt_type"], (UnicodeType, StringType)):
+            namespace, name = DecomposeQualifiedName(choices[type]["elmt_type"])
+            choices[type]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+        if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
+            new_element = choices[type]["elmt_type"]["initial"]()
+            self.content.append({"name": type, "value": new_element})
+            return new_element
+        else:
+            raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs)
+    return appendChoiceMethod
+
+def generateInsertChoiceByTypeMethod(maxOccurs, factory, choice_types):
+    choices = dict([(choice["name"], choice) for choice in choice_types])
+    def insertChoiceMethod(self, index, type):
+        if not choices.has_key(type):
+            raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
+        if isinstance(choices[type]["elmt_type"], (UnicodeType, StringType)):
+            namespace, name = DecomposeQualifiedName(choices[type]["elmt_type"])
+            choices[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+        if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
+            new_element = choices[type]["elmt_type"]["initial"]()
+            self.content.insert(index, {"name" : type, "value" : new_element})
+            return new_element
+        else:
+            raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs)
+    return insertChoiceMethod
+
+def generateRemoveMethod(attr, minOccurs):
+    def removeMethod(self, index):
+        attr_list = getattr(self, attr)
+        if len(attr_list) > minOccurs:
+            getattr(self, attr).pop(index)
+        else:
+            raise ValueError("There can't be less than %d values in \"%s\"!" % (minOccurs, attr))
+    return removeMethod
+
+def generateCountMethod(attr):
+    def countMethod(self):
+        return len(getattr(self, attr))
+    return countMethod
+
+"""
+This function generate the classes from a class factory
+"""
+def GenerateClasses(factory, declare=False):
+    ComputedClasses = factory.CreateClasses()
+    #factory.PrintClasses()
+    if declare:
+        for ClassName, Class in pluginClasses.items():
+            sys._getframe(1).f_locals[ClassName] = Class
+        for TypeName, Type in pluginTypes.items():
+            sys._getframe(1).f_locals[TypeName] = Type
+    globals().update(ComputedClasses)
+    return ComputedClasses
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlclass/xsdschema.py	Fri Sep 30 17:16:02 2011 +0200
@@ -0,0 +1,2456 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import re
+import datetime
+from xml.dom import minidom
+from types import *
+
+from xmlclass import *
+
+def GenerateDictFacets(facets):
+    return dict([(name, (None, False)) for name in facets])
+
+def GenerateSimpleTypeXMLText(function):
+    def generateXMLTextMethod(value, name=None, indent=0):
+        text = ""
+        if name is not None:
+            ind1, ind2 = getIndent(indent, name)
+            text += ind1 + "<%s>" % name
+        text += function(value)
+        if name is not None:
+            text += "</%s>\n" % name
+        return text
+    return generateXMLTextMethod
+
+def GenerateFloatXMLText(extra_values=[]):
+    def generateXMLTextMethod(value, name=None, indent=0):
+        text = ""
+        if name is not None:
+            ind1, ind2 = getIndent(indent, name)
+            text += ind1 + "<%s>" % name
+        if value in extra_values or value % 1 != 0 or isinstance(value, IntType):
+            text += str(value)
+        else:
+            text += "%.0f" % value
+        if name is not None:
+            text += "</%s>\n" % name
+        return text
+    return generateXMLTextMethod
+        
+DEFAULT_FACETS = GenerateDictFacets(["pattern", "whiteSpace", "enumeration"])
+NUMBER_FACETS = GenerateDictFacets(DEFAULT_FACETS.keys() + ["maxInclusive", "maxExclusive", "minInclusive", "minExclusive"])
+DECIMAL_FACETS = GenerateDictFacets(NUMBER_FACETS.keys() + ["totalDigits", "fractionDigits"])
+STRING_FACETS = GenerateDictFacets(DEFAULT_FACETS.keys() + ["length", "minLength", "maxLength"])
+
+ALL_FACETS = ["pattern", "whiteSpace", "enumeration", "maxInclusive", 
+    "maxExclusive", "minInclusive", "minExclusive", "totalDigits", 
+    "fractionDigits", "length", "minLength", "maxLength"]
+
+
+#-------------------------------------------------------------------------------
+#                           Structure reducing functions
+#-------------------------------------------------------------------------------
+
+
+# Documentation elements
+
+def ReduceAppInfo(factory, attributes, elements):
+    return {"type": "appinfo", "source": attributes.get("source", None), 
+            "content": "\n".join(elements)}
+
+
+def ReduceDocumentation(factory, attributes, elements):
+    return {"type": "documentation", "source": attributes.get("source", None), 
+            "language": attributes.get("lang", "any"), "content": "\n".join(elements)}
+
+
+def ReduceAnnotation(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    annotation = {"type": "annotation", "appinfo": [], "documentation": {}}
+    for child in children:
+        if child["type"] == "appinfo":
+            annotation["appinfo"].append((child["source"], child["content"]))
+        elif child["type"] == "documentation":
+            if child["source"] is not None:
+                text = "(source: %(source)s):\n%(content)s\n\n"%child
+            else:
+                text = child["content"] + "\n\n"
+            if not annotation["documentation"].has_key(child["language"]):
+                annotation["documentation"] = text
+            else:
+                annotation["documentation"] += text
+    return annotation
+
+# Simple type elements
+
+def GenerateFacetReducing(facetname, canbefixed):
+    def ReduceFacet(factory, attributes, elements):
+        annotations, children = factory.ReduceElements(elements)
+        if attributes.has_key("value"):
+            facet = {"type": facetname, "value": attributes["value"], "doc": annotations}
+            if canbefixed:
+                facet["fixed"] = attributes.get("fixed", False)
+            return facet
+        raise ValueError("A value must be defined for the \"%s\" facet!" % facetname)
+    return ReduceFacet
+
+
+def ReduceList(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    list = {"type": "list", "itemType": attributes.get("itemType", None), "doc": annotations}
+    
+    if len(children) > 0 and children[0]["type"] == SIMPLETYPE:
+        if list["itemType"] is None:
+            list["itemType"] = children[0]
+        else:
+            raise ValueError("Only one base type can be defined for restriction!")
+    if list["itemType"] is None:
+        raise ValueError("No base type has been defined for list!")
+    return list
+
+
+def ReduceUnion(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    union = {"type": "union", "memberTypes": attributes.get("memberTypes", []), "doc": annotations}
+    
+    for child in children:
+        if child["type"] == SIMPLETYPE:
+            union["memberTypes"].appendchild
+    if len(union["memberTypes"]) == 0:
+        raise ValueError("No base type has been defined for union!")
+    return union
+
+
+def ReduceSimpleType(factory, attributes, elements):
+    # Reduce all the simple type children
+    annotations, children = factory.ReduceElements(elements)
+    
+    typeinfos = children[0]
+    
+    # Initialize type informations
+    facets = {}
+    simpleType = {"type": SIMPLETYPE, "final": attributes.get("final", []), "doc": annotations}
+    if attributes.has_key("name"):
+        simpleType["name"] = attributes["name"]
+    
+    if typeinfos["type"] == "restriction":
+        # Search for base type definition
+        if isinstance(typeinfos["base"], (StringType, UnicodeType)):
+            basetypeinfos = factory.FindSchemaElement(typeinfos["base"], SIMPLETYPE)
+            if basetypeinfos is None:
+                raise "\"%s\" isn't defined!" % typeinfos["base"] 
+        else:
+            basetypeinfos = typeinfos["base"]
+        
+        # Check that base type is a simple type
+        if basetypeinfos["type"] != SIMPLETYPE:
+            raise ValueError("Base type given isn't a simpleType!")
+        
+        simpleType["basename"] = basetypeinfos["basename"]
+        
+        # Check that derivation is allowed
+        if basetypeinfos.has_key("final"):
+            if basetypeinfos["final"].has_key("#all"):
+                raise ValueError("Base type can't be derivated!")
+            if basetypeinfos["final"].has_key("restriction"):
+                raise ValueError("Base type can't be derivated by restriction!")
+        
+        # Extract simple type facets
+        for facet in typeinfos["facets"]:
+            facettype = facet["type"]
+            if not basetypeinfos["facets"].has_key(facettype):
+                raise ValueError("\"%s\" facet can't be defined for \"%s\" type!" % (facettype, type))
+            elif basetypeinfos["facets"][facettype][1]:
+                raise ValueError("\"%s\" facet is fixed on base type!" % facettype)
+            value = facet["value"]
+            basevalue = basetypeinfos["facets"][facettype][0]
+            if facettype == "enumeration":
+                value = basetypeinfos["extract"](value, False)
+                if len(facets) == 0:
+                    facets["enumeration"] = ([value], False)
+                    continue
+                elif facets.keys() == ["enumeration"]:
+                    facets["enumeration"][0].append(value)
+                    continue
+                else:
+                    raise ValueError("\"enumeration\" facet can't be defined with another facet type!")
+            elif facets.has_key("enumeration"):
+                raise ValueError("\"enumeration\" facet can't be defined with another facet type!")
+            elif facets.has_key(facettype):
+                raise ValueError("\"%s\" facet can't be defined two times!" % facettype)
+            elif facettype == "length":
+                if facets.has_key("minLength"):
+                    raise ValueError("\"length\" and \"minLength\" facets can't be defined at the same time!")
+                if facets.has_key("maxLength"):
+                    raise ValueError("\"length\" and \"maxLength\" facets can't be defined at the same time!")
+                try:
+                    value = int(value)
+                except:
+                    raise ValueError("\"length\" must be an integer!")
+                if value < 0:
+                    raise ValueError("\"length\" can't be negative!")
+                elif basevalue is not None and basevalue != value:
+                    raise ValueError("\"length\" can't be different from \"length\" defined in base type!")
+            elif facettype == "minLength":
+                if facets.has_key("length"):
+                    raise ValueError("\"length\" and \"minLength\" facets can't be defined at the same time!")
+                try:
+                    value = int(value)
+                except:
+                    raise ValueError("\"minLength\" must be an integer!")
+                if value < 0:
+                    raise ValueError("\"minLength\" can't be negative!")
+                elif facets.has_key("maxLength") and value > facets["maxLength"]:
+                    raise ValueError("\"minLength\" must be lesser than or equal to \"maxLength\"!")
+                elif basevalue is not None and basevalue < value:
+                    raise ValueError("\"minLength\" can't be lesser than \"minLength\" defined in base type!")
+            elif facettype == "maxLength":
+                if facets.has_key("length"):
+                    raise ValueError("\"length\" and \"maxLength\" facets can't be defined at the same time!")
+                try:
+                    value = int(value)
+                except:
+                    raise ValueError("\"maxLength\" must be an integer!")
+                if value < 0:
+                    raise ValueError("\"maxLength\" can't be negative!")
+                elif facets.has_key("minLength") and value < facets["minLength"]:
+                    raise ValueError("\"minLength\" must be lesser than or equal to \"maxLength\"!")
+                elif basevalue is not None and basevalue > value:
+                    raise ValueError("\"maxLength\" can't be greater than \"maxLength\" defined in base type!")
+            elif facettype == "minInclusive":
+                if facets.has_key("minExclusive"):
+                    raise ValueError("\"minExclusive\" and \"minInclusive\" facets can't be defined at the same time!")
+                value = basetypeinfos["extract"](facet["value"], False)
+                if facets.has_key("maxInclusive") and value > facets["maxInclusive"][0]:
+                    raise ValueError("\"minInclusive\" must be lesser than or equal to \"maxInclusive\"!")
+                elif facets.has_key("maxExclusive") and value >= facets["maxExclusive"][0]:
+                    raise ValueError("\"minInclusive\" must be lesser than \"maxExclusive\"!")
+            elif facettype == "minExclusive":
+                if facets.has_key("minInclusive"):
+                    raise ValueError("\"minExclusive\" and \"minInclusive\" facets can't be defined at the same time!")
+                value = basetypeinfos["extract"](facet["value"], False)
+                if facets.has_key("maxInclusive") and value >= facets["maxInclusive"][0]:
+                    raise ValueError("\"minExclusive\" must be lesser than \"maxInclusive\"!")
+                elif facets.has_key("maxExclusive") and value >= facets["maxExclusive"][0]:
+                    raise ValueError("\"minExclusive\" must be lesser than \"maxExclusive\"!")
+            elif facettype == "maxInclusive":
+                if facets.has_key("maxExclusive"):
+                    raise ValueError("\"maxExclusive\" and \"maxInclusive\" facets can't be defined at the same time!")
+                value = basetypeinfos["extract"](facet["value"], False)
+                if facets.has_key("minInclusive") and value < facets["minInclusive"][0]:
+                    raise ValueError("\"minInclusive\" must be lesser than or equal to \"maxInclusive\"!")
+                elif facets.has_key("minExclusive") and value <= facets["minExclusive"][0]:
+                    raise ValueError("\"minExclusive\" must be lesser than \"maxInclusive\"!")
+            elif facettype == "maxExclusive":
+                if facets.has_key("maxInclusive"):
+                    raise ValueError("\"maxExclusive\" and \"maxInclusive\" facets can't be defined at the same time!")
+                value = basetypeinfos["extract"](facet["value"], False)
+                if facets.has_key("minInclusive") and value <= facets["minInclusive"][0]:
+                    raise ValueError("\"minInclusive\" must be lesser than \"maxExclusive\"!")
+                elif facets.has_key("minExclusive") and value <= facets["minExclusive"][0]:
+                    raise ValueError("\"minExclusive\" must be lesser than \"maxExclusive\"!")
+            elif facettype == "whiteSpace":
+                if basevalue == "collapse" and value in ["preserve", "replace"] or basevalue == "replace" and value == "preserve":
+                   raise ValueError("\"whiteSpace\" is incompatible with \"whiteSpace\" defined in base type!")
+            elif facettype == "totalDigits":
+                if facets.has_key("fractionDigits") and value <= facets["fractionDigits"][0]:
+                    raise ValueError("\"fractionDigits\" must be lesser than or equal to \"totalDigits\"!")
+                elif basevalue is not None and value > basevalue:
+                    raise ValueError("\"totalDigits\" can't be greater than \"totalDigits\" defined in base type!")
+            elif facettype == "fractionDigits":
+                if facets.has_key("totalDigits") and value <= facets["totalDigits"][0]:
+                    raise ValueError("\"fractionDigits\" must be lesser than or equal to \"totalDigits\"!")
+                elif basevalue is not None and value > basevalue:
+                    raise ValueError("\"totalDigits\" can't be greater than \"totalDigits\" defined in base type!")
+            facets[facettype] = (value, facet.get("fixed", False))
+        
+        # Report not redefined facet from base type to new created type 
+        for facettype, facetvalue in basetypeinfos["facets"].items():
+            if not facets.has_key(facettype):
+                facets[facettype] = facetvalue
+        
+        # Generate extract value for new created type
+        def ExtractSimpleTypeValue(attr, extract=True):
+            value = basetypeinfos["extract"](attr, extract)
+            for facetname, (facetvalue, facetfixed) in facets.items():
+                if facetvalue is not None:
+                    if facetname == "enumeration" and value not in facetvalue:
+                        raise ValueError("\"%s\" not in enumerated values" % value)
+                    elif facetname == "length" and len(value) != facetvalue:
+                        raise ValueError("value must have a length of %d" % facetvalue)
+                    elif facetname == "minLength" and len(value) < facetvalue:
+                        raise ValueError("value must have a length of %d at least" % facetvalue)
+                    elif facetname == "maxLength" and len(value) > facetvalue:
+                        raise ValueError("value must have a length of %d at most" % facetvalue)
+                    elif facetname == "minInclusive" and value < facetvalue:
+                        raise ValueError("value must be greater than or equal to %s" % str(facetvalue))
+                    elif facetname == "minExclusive" and value <= facetvalue:
+                        raise ValueError("value must be greater than %s" % str(facetvalue))
+                    elif facetname == "maxInclusive" and value > facetvalue:
+                        raise ValueError("value must be lesser than or equal to %s" % str(facetvalue))
+                    elif facetname == "maxExclusive"  and value >= facetvalue:
+                        raise ValueError("value must be lesser than %s" % str(facetvalue))
+                    elif facetname == "pattern":
+                        model = re.compile("(?:%s)?$" % facetvalue)
+                        result = model.match(value)
+                        if result is None:
+                            raise ValueError("value doesn't follow the pattern %s" % facetvalue)
+                    elif facetname == "whiteSpace":
+                        if facetvalue == "replace":
+                            value = GetNormalizedString(value, False)
+                        elif facetvalue == "collapse":
+                            value = GetToken(value, False)
+            return value
+        
+        def CheckSimpleTypeValue(value):
+            for facetname, (facetvalue, facetfixed) in facets.items():
+                if facetvalue is not None:
+                    if facetname == "enumeration" and value not in facetvalue:
+                        return False
+                    elif facetname == "length" and len(value) != facetvalue:
+                        return False
+                    elif facetname == "minLength" and len(value) < facetvalue:
+                        return False
+                    elif facetname == "maxLength" and len(value) > facetvalue:
+                        return False
+                    elif facetname == "minInclusive" and value < facetvalue:
+                        return False
+                    elif facetname == "minExclusive" and value <= facetvalue:
+                        return False
+                    elif facetname == "maxInclusive" and value > facetvalue:
+                        return False
+                    elif facetname == "maxExclusive"  and value >= facetvalue:
+                        return False
+                    elif facetname == "pattern":
+                        model = re.compile("(?:%s)?$" % facetvalue)
+                        result = model.match(value)
+                        if result is None:
+                            raise ValueError("value doesn't follow the pattern %s" % facetvalue)
+            return True
+        
+        def SimpleTypeInitialValue():
+            for facetname, (facetvalue, facetfixed) in facets.items():
+                if facetvalue is not None:
+                    if facetname == "enumeration":
+                        return facetvalue[0]
+                    elif facetname == "length":
+                        return " "*facetvalue
+                    elif facetname == "minLength":
+                        return " "*minLength
+                    elif facetname == "minInclusive" and facetvalue > 0:
+                        return facetvalue
+                    elif facetname == "minExclusive" and facetvalue >= 0:
+                        return facetvalue + 1
+                    elif facetname == "maxInclusive" and facetvalue < 0:
+                        return facetvalue
+                    elif facetname == "maxExclusive"  and facetvalue <= 0:
+                        return facetvalue - 1
+            return basetypeinfos["initial"]()
+        
+        GenerateSimpleType = basetypeinfos["generate"]
+        
+    elif typeinfos["type"] == "list":
+        # Search for item type definition
+        if isinstance(typeinfos["itemType"], (StringType, UnicodeType)):
+            itemtypeinfos = factory.FindSchemaElement(typeinfos["itemType"], SIMPLETYPE)
+            if itemtypeinfos is None:
+                raise "\"%s\" isn't defined!" % typeinfos["itemType"]
+        else:
+            itemtypeinfos = typeinfos["itemType"]
+        
+        # Check that item type is a simple type
+        if itemtypeinfos["type"] != SIMPLETYPE:
+            raise ValueError, "Item type given isn't a simpleType!"
+        
+        simpleType["basename"] = "list"
+        
+        # Check that derivation is allowed
+        if itemtypeinfos.has_key("final"):
+            if itemtypeinfos["final"].has_key("#all"):
+                raise ValueError("Item type can't be derivated!")
+            if itemtypeinfos["final"].has_key("list"):
+                raise ValueError("Item type can't be derivated by list!")
+        
+        # Generate extract value for new created type
+        def ExtractSimpleTypeValue(attr, extract = True):
+            values = []
+            for value in GetToken(attr, extract).split(" "):
+                values.append(itemtypeinfos["extract"](value, False))
+            return values
+        
+        def CheckSimpleTypeValue(value):
+            for item in value:
+                result = itemtypeinfos["check"](item)
+                if not result:
+                    return result
+            return True
+        
+        SimpleTypeInitialValue = lambda: []
+        
+        GenerateSimpleType = GenerateSimpleTypeXMLText(lambda x: " ".join(map(itemtypeinfos["generate"], x)))
+        
+        facets = GenerateDictFacets(["length", "maxLength", "minLength", "enumeration", "pattern"])
+        facets["whiteSpace"] = ("collapse", False)
+    
+    elif typeinfos["type"] == "union":
+        # Search for member types definition
+        membertypesinfos = []
+        for membertype in typeinfos["memberTypes"]:
+            if isinstance(membertype, (StringType, UnicodeType)):
+                infos = factory.FindSchemaElement(membertype, SIMPLETYPE)
+                if infos is None:
+                    raise ValueError("\"%s\" isn't defined!" % membertype)
+            else:
+                infos = membertype
+            
+            # Check that member type is a simple type
+            if infos["type"] != SIMPLETYPE:
+                raise ValueError("Member type given isn't a simpleType!")
+            
+            # Check that derivation is allowed
+            if infos.has_key("final"):
+                if infos["final"].has_key("#all"):
+                    raise ValueError("Item type can't be derivated!")
+                if infos["final"].has_key("union"):
+                    raise ValueError("Member type can't be derivated by union!")
+            
+            membertypesinfos.append(infos)
+        
+        simpleType["basename"] = "union"
+        
+        # Generate extract value for new created type
+        def ExtractSimpleTypeValue(attr, extract = True):
+            if extract:
+                value = GetAttributeValue(attr)
+            else:
+                value = attr
+            for infos in membertypesinfos:
+                try:
+                    return infos["extract"](attr, False)
+                except:
+                    pass
+            raise ValueError("\"%s\" isn't valid for type defined for union!")
+        
+        def CheckSimpleTypeValue(value):
+            for infos in membertypesinfos:
+                result = infos["check"](value)
+                if result:
+                    return result
+            return False
+        
+        SimpleTypeInitialValue = membertypesinfos[0]["initial"]
+        
+        def GenerateSimpleTypeFunction(value):
+            if isinstance(value, BooleanType):
+                return {True: "true", False: "false"}[value]
+            else:
+                return str(value)
+        GenerateSimpleType = GenerateSimpleTypeXMLText(GenerateSimpleTypeFunction)
+        
+        facets = GenerateDictFacets(["pattern", "enumeration"])
+    
+    simpleType["facets"] = facets
+    simpleType["extract"] = ExtractSimpleTypeValue
+    simpleType["initial"] = SimpleTypeInitialValue
+    simpleType["check"] = CheckSimpleTypeValue
+    simpleType["generate"] = GenerateSimpleType
+    return simpleType
+
+
+# Complex type
+
+def ExtractAttributes(factory, elements, base = None):
+    if base is not None:
+        basetypeinfos = factory.FindSchemaElement(base, COMPLEXTYPE)
+        if isinstance(basetypeinfos, (UnicodeType, StringType)):
+            attrnames = {}
+        else:
+            attrnames = dict(map(lambda x:(x["name"], True), basetypeinfos["attributes"]))
+    else:
+        attrnames = {}
+    attrs = []
+    for element in elements:
+        if element["type"] == ATTRIBUTE:
+            if attrnames.get(element["name"], False):
+                raise ValueError("\"%s\" attribute has been defined two times!" % element["name"])
+            else:
+                attrnames[element["name"]] = True
+                attrs.append(element)
+        elif element["type"] == "attributeGroup":
+            attrgroup = factory.FindSchemaElement(element["ref"], ATTRIBUTESGROUP)
+            for attr in attrgroup["attributes"]:
+                if attrnames.get(attr["name"], False):
+                    raise ValueError("\"%s\" attribute has been defined two times!" % attr["name"])
+                else:
+                    attrnames[attr["name"]] = True
+                    attrs.append(attr)
+        elif element["type"] == "anyAttribute":
+            raise ValueError("\"anyAttribute\" element isn't supported yet!")
+    return attrs
+
+
+def ReduceRestriction(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    restriction = {"type": "restriction", "base": attributes.get("base", None), "facets": [], "doc": annotations}
+    if len(children) > 0 and children[0]["type"] == SIMPLETYPE:
+        if restriction["base"] is None:
+            restriction["base"] = children.pop(0)
+        else:
+            raise ValueError("Only one base type can be defined for restriction!")
+    if restriction["base"] is None:
+        raise ValueError("No base type has been defined for restriction!")
+    
+    while len(children) > 0 and children[0]["type"] in ALL_FACETS:
+        restriction["facets"].append(children.pop(0))
+    restriction["attributes"] = ExtractAttributes(factory, children)
+    return restriction
+
+
+def ReduceExtension(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    extension = {"type": "extension", "attributes": [], "elements": [], "base": attributes.get("base", None), "doc": annotations}
+    if len(children) > 0:
+        if children[0]["type"] in ["group", "all", CHOICE, "sequence"]:
+            group = children.pop(0)
+            if group["type"] in ["all", "sequence"]:
+                extension["elements"] = group["elements"]
+                extension["order"] = group["order"]
+            elif group["type"] == CHOICE:
+                content = group.copy()
+                content["name"] = "content"
+                extension["elements"].append(content)
+            elif group["type"] == "group":
+                elmtgroup = factory.FindSchemaElement(child["ref"], ELEMENTSGROUP)
+                if elmtgroup.has_key("elements"):
+                    extension["elements"] = elmtgroup["elements"]
+                    extension["order"] = elmtgroup["order"]
+                else:
+                    content = elmtgroup.copy()
+                    content["name"] = "content"
+                    extension["elements"].append(content)
+        extension["attributes"] = ExtractAttributes(factory, children, extension["base"])
+    return extension
+
+
+def ReduceSimpleContent(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    simpleContent = children[0].copy()
+    simpleContent["type"] = "simpleContent"
+    return simpleContent
+
+
+def ReduceComplexContent(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    complexContent = children[0].copy()
+    complexContent["type"] = "complexContent"
+    return complexContent
+
+
+def ReduceComplexType(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+        
+    if len(children) > 0:
+        if children[0]["type"] in ["simpleContent", "complexContent"]:
+            complexType = children[0].copy()
+            complexType.update(attributes)
+            complexType["type"] = COMPLEXTYPE
+            return complexType
+        elif children[0]["type"] in ["group", "all", CHOICE, "sequence"]:
+            complexType = {"type": COMPLEXTYPE, "elements": [], "order": True, "doc": annotations}
+            complexType.update(attributes)
+            group = children.pop(0)
+            if group["type"] in ["all", "sequence"]:
+                if group["minOccurs"] == 0 or group["maxOccurs"] != 1:
+                    if len(group["elements"]) > 1:
+                        raise ValueError("Not supported yet!")
+                    if group["minOccurs"] == 0:
+                        group["elements"][0]["minOccurs"] = group["minOccurs"]
+                    if group["maxOccurs"] != 1:
+                        group["elements"][0]["maxOccurs"] = group["maxOccurs"]
+                complexType["elements"] = group["elements"]
+                complexType["order"] = group["order"]
+            elif group["type"] == CHOICE:
+                content = group.copy()
+                content["name"] = "content"
+                complexType["elements"].append(content)
+            elif group["type"] == "group":
+                elmtgroup = factory.FindSchemaElement(child["ref"], ELEMENTSGROUP)
+                if elmtgroup.has_key("elements"):
+                    complexType["elements"] = elmtgroup["elements"]
+                    complexType["order"] = elmtgroup["order"]
+                else:
+                    content = elmtgroup.copy()
+                    content["name"] = "content"
+                    complexType["elements"].append(content)
+        else:
+            complexType = {"elements": [], "order": True, "doc": annotations}
+            complexType.update(attributes)
+            complexType["type"] = COMPLEXTYPE
+        complexType["attributes"] = ExtractAttributes(factory, children)
+        return complexType
+    else:
+        raise ValueError("\"ComplexType\" can't be empty!")
+
+
+# Attribute elements
+
+def ReduceAnyAttribute(factory, attributes, elements):
+    return {"type" : "anyAttribute"}
+
+
+def ReduceAttribute(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    
+    if attributes.has_key("default"):
+        if attributes.has_key("fixed"):
+            raise ValueError("\"default\" and \"fixed\" can't be defined at the same time!")
+        elif attributes.get("use", "optional") != "optional":
+            raise ValueError("if \"default\" present, \"use\" can only have the value \"optional\"!")
+    
+    attribute = {"type": ATTRIBUTE, "attr_type": attributes.get("type", None), "doc": annotations}
+    if len(children) > 0:
+        if attribute["attr_type"] is None:
+            attribute["attr_type"] = children[0]
+        else:
+            raise ValueError("Only one type can be defined for attribute!")
+    
+    if attributes.has_key("ref"):
+        if attributes.has_key("name"):
+            raise ValueError("\"ref\" and \"name\" can't be defined at the same time!")
+        elif attributes.has_key("form"):
+            raise ValueError("\"ref\" and \"form\" can't be defined at the same time!")
+        elif attribute["attr_type"] is not None:
+            raise ValueError("if \"ref\" is present, no type can be defined!")
+    elif attribute["attr_type"] is None:
+        raise ValueError("No type has been defined for attribute \"%s\"!" % attributes["name"])
+    
+    if attributes.has_key("type"):
+        tmp_attrs = attributes.copy()
+        tmp_attrs.pop("type")
+        attribute.update(tmp_attrs)
+    else:
+        attribute.update(attributes)
+    return attribute
+
+
+def ReduceAttributeGroup(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    if attributes.has_key("ref"):
+        return {"type": "attributeGroup", "ref": attributes["ref"], "doc": annotations}
+    else:
+        return {"type": ATTRIBUTESGROUP, "attributes": ExtractAttributes(factory, children), "doc": annotations}
+
+
+# Elements groups
+
+def ReduceAny(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    
+    any = {"type": ANY, "doc": annotations}
+    any.update(attributes)
+    return any
+
+def ReduceElement(factory, attributes, elements):
+    if attributes.has_key("default") and attributes.has_key("fixed"):
+        raise ValueError("\"default\" and \"fixed\" can't be defined at the same time!")
+    
+    if attributes.has_key("ref"):
+        annotations, children = factory.ReduceElements(elements)
+        
+        for attr in ["name", "default", "fixed", "form", "block", "type"]:
+            if attributes.has_key(attr):
+                raise ValueError("\"ref\" and \"%s\" can't be defined at the same time!" % attr)
+        if attributes.has_key("nillable"):
+            raise ValueError("\"ref\" and \"nillable\" can't be defined at the same time!")
+        if len(children) > 0:
+            raise ValueError("No type and no constraints can be defined where \"ref\" is defined!")
+    
+        infos = factory.FindSchemaElement(attributes["ref"], ELEMENT)
+        if infos is not None:
+            element = infos.copy()
+            element["minOccurs"] = attributes["minOccurs"]
+            element["maxOccurs"] = attributes["maxOccurs"]
+            return element
+        else:
+            raise ValueError("\"%s\" base type isn't defined or circular referenced!" % name)
+    
+    elif attributes.has_key("name"):
+        annotations, children = factory.ReduceElements(elements)
+        
+        element = {"type": ELEMENT, "elmt_type": attributes.get("type", None), "doc": annotations}
+        if len(children) > 0:
+            if element["elmt_type"] is None:
+                element["elmt_type"] = children[0]
+            else:
+                raise ValueError("Only one type can be defined for attribute!")
+        elif element["elmt_type"] is None:
+            element["elmt_type"] = "tag"
+            element["type"] = TAG
+        
+        if attributes.has_key("type"):
+            tmp_attrs = attributes.copy()
+            tmp_attrs.pop("type")
+            element.update(tmp_attrs)
+        else:
+            element.update(attributes)
+        return element
+    else:
+        raise ValueError("\"Element\" must have at least a \"ref\" or a \"name\" defined!")
+
+def ReduceAll(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    
+    for child in children:
+        if children["maxOccurs"] == "unbounded" or children["maxOccurs"] > 1:
+            raise ValueError("\"all\" item can't have \"maxOccurs\" attribute greater than 1!")
+    
+    return {"type": "all", "elements": children, "minOccurs": attributes["minOccurs"],
+            "maxOccurs": attributes["maxOccurs"], "order": False, "doc": annotations}
+
+
+def ReduceChoice(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    
+    choices = []
+    for child in children:
+        if child["type"] in [ELEMENT, ANY, TAG]:
+            choices.append(child)
+        elif child["type"] == "sequence":
+            raise ValueError("\"sequence\" in \"choice\" is not supported. Create instead a new complex type!")
+        elif child["type"] == CHOICE:
+            choices.extend(child["choices"])
+        elif child["type"] == "group":
+            elmtgroup = factory.FindSchemaElement(child["ref"], ELEMENTSGROUP) 
+            if not elmtgroup.has_key("choices"):
+                raise ValueError("Only group composed of \"choice\" can be referenced in \"choice\" element!")
+            choices_tmp = []
+            for choice in elmtgroup["choices"]:
+                if not isinstance(choice["elmt_type"], (UnicodeType, StringType)) and choice["elmt_type"]["type"] == COMPLEXTYPE:
+                    elmt_type = "%s_%s" % (elmtgroup["name"], choice["name"])
+                    if factory.TargetNamespace is not None:
+                        elmt_type = "%s:%s" % (factory.TargetNamespace, elmt_type)
+                    new_choice = choice.copy()
+                    new_choice["elmt_type"] = elmt_type
+                    choices_tmp.append(new_choice)
+                else:
+                    choices_tmp.append(choice)
+            choices.extend(choices_tmp)
+    
+    return {"type": CHOICE, "choices": choices, "minOccurs": attributes["minOccurs"],
+            "maxOccurs": attributes["maxOccurs"], "doc": annotations}
+
+
+def ReduceSequence(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    
+    sequence = []
+    for child in children:
+        if child["type"] in [ELEMENT, ANY, TAG]:
+            sequence.append(child)
+        elif child["type"] == CHOICE:
+            content = child.copy()
+            content["name"] = "content"
+            sequence.append(content)
+        elif child["type"] == "sequence":
+            sequence.extend(child["elements"])
+        elif child["type"] == "group":
+            elmtgroup = factory.FindSchemaElement(child["ref"], ELEMENTSGROUP)
+            if not elmtgroup.has_key("elements") or not elmtgroup["order"]:
+                raise ValueError("Only group composed of \"sequence\" can be referenced in \"sequence\" element!")
+            elements_tmp = []
+            for element in elmtgroup["elements"]:
+                if not isinstance(element["elmt_type"], (UnicodeType, StringType)) and element["elmt_type"]["type"] == COMPLEXTYPE:
+                    elmt_type = "%s_%s"%(elmtgroup["name"], element["name"])
+                    if factory.TargetNamespace is not None:
+                        elmt_type = "%s:%s" % (factory.TargetNamespace, elmt_type)
+                    new_element = element.copy()
+                    new_element["elmt_type"] = elmt_type
+                    elements_tmp.append(new_element)
+                else:
+                    elements_tmp.append(element)
+            sequence.extend(elements_tmp)
+            
+    return {"type": "sequence", "elements": sequence, "minOccurs": attributes["minOccurs"],
+            "maxOccurs": attributes["maxOccurs"], "order": True, "doc": annotations}
+    
+    
+def ReduceGroup(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    
+    if attributes.has_key("ref"):
+        return {"type": "group", "ref": attributes["ref"], "doc": annotations}
+    else:
+        element = children[0]
+        group = {"type": ELEMENTSGROUP, "doc": annotations}
+        if element["type"] == CHOICE:
+            group["choices"] = element["choices"]
+        else:
+            group.update({"elements": element["elements"], "order": group["order"]})
+        group.update(attributes)
+        return group
+
+# Constraint elements
+
+def ReduceUnique(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    raise ValueError("\"unique\" element isn't supported yet!")
+
+def ReduceKey(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    raise ValueError("\"key\" element isn't supported yet!")
+    
+def ReduceKeyRef(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    raise ValueError("\"keyref\" element isn't supported yet!")
+    
+def ReduceSelector(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    raise ValueError("\"selector\" element isn't supported yet!")
+
+def ReduceField(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    raise ValueError("\"field\" element isn't supported yet!")
+    
+
+# Inclusion elements
+
+def ReduceImport(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    raise ValueError("\"import\" element isn't supported yet!")
+
+def ReduceInclude(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    raise ValueError("\"include\" element isn't supported yet!")
+    
+def ReduceRedefine(factory, attributes, elements):
+    annotations, children = factory.ReduceElements(elements)
+    raise ValueError("\"redefine\" element isn't supported yet!")
+
+
+# Schema element
+
+def ReduceSchema(factory, attributes, elements):
+    factory.AttributeFormDefault = attributes["attributeFormDefault"]
+    factory.ElementFormDefault = attributes["elementFormDefault"]
+    factory.BlockDefault = attributes["blockDefault"]
+    factory.FinalDefault = attributes["finalDefault"]
+    
+    if attributes.has_key("targetNamespace"):
+        factory.TargetNamespace = factory.DefinedNamespaces.get(attributes["targetNamespace"], None)
+    factory.Namespaces[factory.TargetNamespace] = {}
+    
+    annotations, children = factory.ReduceElements(elements, True)
+    
+    for child in children:
+        if child.has_key("name"):
+            infos = factory.GetQualifiedNameInfos(child["name"], factory.TargetNamespace, True)
+            if infos is None:
+                factory.Namespaces[factory.TargetNamespace][child["name"]] = child
+            elif not CompareSchema(infos, child):
+                raise ValueError("\"%s\" is defined twice in targetNamespace!" % child["name"])
+
+def CompareSchema(schema, reference):
+    if isinstance(schema, ListType):
+        if not isinstance(reference, ListType) or len(schema) != len(reference):
+            return False
+        for i, value in enumerate(schema):
+            result = CompareSchema(value, reference[i])
+            if not result:
+                return result
+        return True
+    elif isinstance(schema, DictType):
+        if not isinstance(reference, DictType) or len(schema) != len(reference):
+            return False
+        for name, value in schema.items():
+            ref_value = reference.get(name, None)
+            if ref_value is None:
+                return False
+            result = CompareSchema(value, ref_value)
+            if not result:
+                return result
+        return True
+    elif isinstance(schema, FunctionType):
+        if not isinstance(reference, FunctionType) or schema.__name__ != reference.__name__:
+            return False
+        else:
+            return True
+    return schema == reference
+    
+#-------------------------------------------------------------------------------
+#                       Base class for XSD schema extraction
+#-------------------------------------------------------------------------------
+
+
+class XSDClassFactory(ClassFactory):
+
+    def __init__(self, document, debug = False):
+        ClassFactory.__init__(self, document, debug)
+        self.Namespaces["xml"] = {
+            "lang": {
+                "type": SYNTAXATTRIBUTE, 
+                "extract": {
+                    "default": GenerateModelNameExtraction("lang", LANGUAGE_model)
+                }
+            }
+        }
+        self.Namespaces["xsi"] = {
+            "noNamespaceSchemaLocation": {
+                "type": SYNTAXATTRIBUTE, 
+                "extract": {
+                    "default": NotSupportedYet("noNamespaceSchemaLocation")
+                }
+            },
+            "nil": {
+                "type": SYNTAXATTRIBUTE, 
+                "extract": {
+                    "default": NotSupportedYet("nil")
+                }
+            },
+            "schemaLocation": {
+                "type": SYNTAXATTRIBUTE, 
+                "extract": {
+                    "default": NotSupportedYet("schemaLocation")
+                }
+            },
+            "type": {
+                "type": SYNTAXATTRIBUTE, 
+                "extract": {
+                    "default": NotSupportedYet("type")
+                }
+            }
+        }
+        
+    def ParseSchema(self):
+        schema = self.Document.childNodes[0]
+        for qualified_name, attr in schema._attrs.items():
+            value = GetAttributeValue(attr)
+            if value == "http://www.w3.org/2001/XMLSchema":
+                namespace, name = DecomposeQualifiedName(qualified_name)
+                if namespace == "xmlns":
+                    self.DefinedNamespaces["http://www.w3.org/2001/XMLSchema"] = name
+                    self.SchemaNamespace = name
+                else:
+                    self.DefinedNamespaces["http://www.w3.org/2001/XMLSchema"] = self.SchemaNamespace
+                self.Namespaces[self.SchemaNamespace] = XSD_NAMESPACE
+        self.Schema = XSD_NAMESPACE["schema"]["extract"]["default"](self, schema)
+        ReduceSchema(self, self.Schema[1], self.Schema[2])
+
+    def FindSchemaElement(self, element_name, element_type):
+        namespace, name = DecomposeQualifiedName(element_name)
+        element = self.GetQualifiedNameInfos(name, namespace, True)
+        if element is None and namespace == self.TargetNamespace and name not in self.CurrentCompilations:
+            self.CurrentCompilations.append(name)
+            element = self.CreateSchemaElement(name, element_type)
+            self.CurrentCompilations.pop(-1)
+            if element is not None:
+                self.Namespaces[self.TargetNamespace][name] = element
+        if element is None:
+            if name in self.CurrentCompilations:
+                if self.Debug:
+                    print "Warning : \"%s\" is circular referenced!" % element_name
+                return element_name
+            else:
+                raise ValueError("\"%s\" isn't defined!" % element_name)
+        if element["type"] != element_type:
+            raise ValueError("\"%s\" isn't a group!" % element_name)
+        return element
+    
+    def CreateSchemaElement(self, element_name, element_type):
+        for type, attributes, elements in self.Schema[2]:
+            namespace, name = DecomposeQualifiedName(type)
+            if attributes.has_key("name") and attributes["name"] == element_name:
+                element_infos = None
+                if element_type == ATTRIBUTE and name == "attribute":
+                    element_infos = ReduceAttribute(self, attributes, elements)
+                elif element_type == ELEMENT and name == "element":
+                    element_infos = ReduceElement(self, attributes, elements)
+                elif element_type == ATTRIBUTESGROUP and name == "attributeGroup":
+                    element_infos = ReduceAttributeGroup(self, attributes, elements)
+                elif element_type == ELEMENTSGROUP and name == "group":
+                    element_infos = ReduceGroup(self, attributes, elements)
+                elif element_type == SIMPLETYPE and name == "simpleType":
+                    element_infos = ReduceSimpleType(self, attributes, elements)
+                elif element_type == COMPLEXTYPE and name == "complexType":
+                    element_infos = ReduceComplexType(self, attributes, elements)
+                if element_infos is not None:
+                    self.Namespaces[self.TargetNamespace][element_name] = element_infos
+                    return element_infos
+        return None
+
+"""
+This function opens the xsd file and generate the classes from the xml tree
+"""
+def GenerateClassesFromXSD(filename, declare = False):
+    xsdfile = open(filename, 'r')
+    factory = XSDClassFactory(minidom.parse(xsdfile))
+    xsdfile.close()
+    factory.ParseSchema()
+    return GenerateClasses(factory, declare)
+
+"""
+This function generate the classes from the xsd given as a string
+"""
+def GenerateClassesFromXSDstring(xsdstring, declare = False):
+    factory = XSDClassFactory(minidom.parseString(xsdstring))
+    factory.ParseSchema()
+    return GenerateClasses(factory, declare)
+
+
+#-------------------------------------------------------------------------------
+#                           XSD schema syntax elements
+#-------------------------------------------------------------------------------
+
+XSD_NAMESPACE = {
+
+#-------------------------------------------------------------------------------
+#                           Syntax elements definition
+#-------------------------------------------------------------------------------
+
+    "all": {"struct": """
+        <all
+          id = ID
+          maxOccurs = 1 : 1
+          minOccurs = (0 | 1) : 1
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, element*)
+        </all>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("all", ["id", "maxOccurs", "minOccurs"], 
+                re.compile("((?:annotation )?(?:element )*)"))
+        },
+        "reduce": ReduceAll
+    },
+
+    "annotation": {"struct": """
+        <annotation
+          id = ID
+          {any attributes with non-schema namespace . . .}>
+          Content: (appinfo | documentation)*
+        </annotation>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("annotation", ["id"], 
+                re.compile("((?:app_info |documentation )*)"))
+        },
+        "reduce": ReduceAnnotation
+    },
+
+    "any": {"struct": """
+        <any
+          id = ID
+          maxOccurs = (nonNegativeInteger | unbounded)  : 1
+          minOccurs = nonNegativeInteger : 1
+          namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )  : ##any
+          processContents = (lax | skip | strict) : strict
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </any>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("any", 
+                ["id", "maxOccurs", "minOccurs", "namespace", "processContents"], 
+                re.compile("((?:annotation )?(?:simpleType )*)"))
+        },
+        "reduce": ReduceAny
+    },
+
+    "anyAttribute": {"struct": """
+        <anyAttribute
+          id = ID
+          namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )  : ##any
+          processContents = (lax | skip | strict) : strict
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </anyAttribute>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("anyAttribute",
+                ["id", "namespace", "processContents"], ONLY_ANNOTATION)
+        },
+        "reduce": ReduceAnyAttribute
+    },
+
+    "appinfo": {"struct": """
+        <appinfo
+          source = anyURI
+          {any attributes with non-schema namespace . . .}>
+          Content: ({any})*
+        </appinfo>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("appinfo", ["source"], re.compile("(.*)"), True)
+        },
+        "reduce": ReduceAppInfo
+    },
+
+    "attribute": {"struct": """
+        <attribute
+          default = string
+          fixed = string
+          form = (qualified | unqualified)
+          id = ID
+          name = NCName
+          ref = QName
+          type = QName
+          use = (optional | prohibited | required) : optional
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, simpleType?)
+        </attribute>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("attribute", 
+                ["default", "fixed", "form", "id", "name", "ref", "type", "use"], 
+                re.compile("((?:annotation )?(?:simpleType )?)")),
+            "schema": GenerateElement("attribute", 
+                ["default", "fixed", "form", "id", "name", "type"], 
+                re.compile("((?:annotation )?(?:simpleType )?)"))
+        },
+        "reduce": ReduceAttribute
+    },
+
+    "attributeGroup": {"struct": """
+        <attributeGroup
+          id = ID
+          name = NCName
+          ref = QName
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, ((attribute | attributeGroup)*, anyAttribute?))
+        </attributeGroup>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("attributeGroup", 
+                ["id", "ref"], ONLY_ANNOTATION),
+            "schema": GenerateElement("attributeGroup",
+                ["id", "name"], 
+                re.compile("((?:annotation )?(?:(?:attribute |attributeGroup )*(?:anyAttribute )?))"))
+        },
+        "reduce": ReduceAttributeGroup
+    },
+
+    "choice": {"struct": """
+        <choice
+          id = ID
+          maxOccurs = (nonNegativeInteger | unbounded)  : 1
+          minOccurs = nonNegativeInteger : 1
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (element | group | choice | sequence | any)*)
+        </choice>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("choice", ["id", "maxOccurs", "minOccurs"], 
+                re.compile("((?:annotation )?(?:element |group |choice |sequence |any )*)"))
+        },
+        "reduce": ReduceChoice
+    },
+
+    "complexContent": {"struct": """
+        <complexContent
+          id = ID
+          mixed = boolean
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (restriction | extension))
+        </complexContent>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("complexContent", ["id", "mixed"], 
+                re.compile("((?:annotation )?(?:restriction |extension ))"))
+        },
+        "reduce": ReduceComplexContent
+    },
+
+    "complexType": {"struct": """
+        <complexType
+          abstract = boolean : false
+          block = (#all | List of (extension | restriction))
+          final = (#all | List of (extension | restriction))
+          id = ID
+          mixed = boolean : false
+          name = NCName
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
+        </complexType>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("complexType", 
+                ["abstract", "block", "final", "id", "mixed", "name"], 
+                re.compile("((?:annotation )?(?:simpleContent |complexContent |(?:(?:group |all |choice |sequence )?(?:(?:attribute |attributeGroup )*(?:anyAttribute )?))))"))
+        },
+        "reduce": ReduceComplexType
+    },
+
+    "documentation": {"struct" : """
+        <documentation
+          source = anyURI
+          xml:lang = language
+          {any attributes with non-schema namespace . . .}>
+          Content: ({any})*
+        </documentation>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("documentation", 
+                ["source", "lang"], re.compile("(.*)"), True)
+        },
+        "reduce": ReduceDocumentation
+    },
+
+    "element": {"struct": """
+        <element
+          abstract = boolean : false
+          block = (#all | List of (extension | restriction | substitution))
+          default = string
+          final = (#all | List of (extension | restriction))
+          fixed = string
+          form = (qualified | unqualified)
+          id = ID
+          maxOccurs = (nonNegativeInteger | unbounded)  : 1
+          minOccurs = nonNegativeInteger : 1
+          name = NCName
+          nillable = boolean : false
+          ref = QName
+          substitutionGroup = QName
+          type = QName
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
+        </element>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("element", 
+                ["abstract", "block", "default", "final", "fixed", "form", "id", "maxOccurs", "minOccurs", "name", "nillable", "ref", "substitutionGroup", "type"], 
+                re.compile("((?:annotation )?(?:simpleType |complexType )?(?:unique |key |keyref )*)")),
+            "schema": GenerateElement("element", 
+                ["abstract", "block", "default", "final", "fixed", "form", "id", "name", "nillable", "substitutionGroup", "type"], 
+                re.compile("((?:annotation )?(?:simpleType |complexType )?(?:unique |key |keyref )*)"))
+        },
+        "reduce": ReduceElement
+    },
+
+    "enumeration": {"struct": """
+        <enumeration
+          id = ID
+          value = anySimpleType
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </enumeration>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("enumeration", ["id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("enumeration", False)
+    },
+
+    "extension": {"struct": """
+        <extension
+          base = QName
+          id = ID
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?)))
+        </extension>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("extension", ["base", "id"], 
+                re.compile("((?:annotation )?(?:(?:attribute |attributeGroup )*(?:anyAttribute )?))")),
+            "complexContent": GenerateElement("extension", ["base", "id"], 
+                re.compile("((?:annotation )?(?:group |all |choice |sequence )?(?:(?:attribute |attributeGroup )*(?:anyAttribute )?))"))
+        },
+        "reduce": ReduceExtension
+    },
+
+    "field": {"struct": """
+        <field
+          id = ID
+          xpath = a subset of XPath expression, see below
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </field>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("field", ["id", "xpath"], ONLY_ANNOTATION)
+        },
+        "reduce": ReduceField
+    },
+
+    "fractionDigits": {"struct": """
+        <fractionDigits
+          fixed = boolean : false
+          id = ID
+          value = nonNegativeInteger
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </fractionDigits>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("fractionDigits", 
+                ["fixed", "id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("fractionDigits", True)
+    },
+
+    "group": {"struct": """
+        <group
+          id = ID
+          maxOccurs = (nonNegativeInteger | unbounded)  : 1
+          minOccurs = nonNegativeInteger : 1
+          name = NCName
+          ref = QName
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (all | choice | sequence)?)
+        </group>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("group",
+                ["id", "maxOccurs", "minOccurs", "ref"], 
+                re.compile("((?:annotation )?(?:all |choice |sequence )?)")),
+            "schema": GenerateElement("group",
+                ["id", "name"], 
+                re.compile("((?:annotation )?(?:all |choice |sequence )?)"))
+        },
+        "reduce": ReduceGroup
+    },
+
+    "import": {"struct": """
+        <import
+          id = ID
+          namespace = anyURI
+          schemaLocation = anyURI
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </import>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("import",
+                ["id", "namespace", "schemaLocation"], ONLY_ANNOTATION)
+        },
+        "reduce": ReduceImport
+    },
+
+    "include": {"struct": """
+        <include
+          id = ID
+          schemaLocation = anyURI
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </include>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("include",
+                ["id", "schemaLocation"], ONLY_ANNOTATION)
+        },
+        "reduce": ReduceInclude
+    },
+
+    "key": {"struct": """
+        <key
+          id = ID
+          name = NCName
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (selector, field+))
+        </key>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("key", ["id", "name"], 
+                re.compile("((?:annotation )?(?:selector |(?:field )+))"))
+        },
+        "reduce": ReduceKey
+    },
+
+    "keyref": {"struct": """
+        <keyref
+          id = ID
+          name = NCName
+          refer = QName
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (selector, field+))
+        </keyref>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("keyref", ["id", "name", "refer"], 
+                re.compile("((?:annotation )?(?:selector |(?:field )+))"))
+        },
+        "reduce": ReduceKeyRef
+    },
+
+    "length": {"struct" : """
+        <length
+          fixed = boolean : false
+          id = ID
+          value = nonNegativeInteger
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </length>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("length", 
+                ["fixed", "id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("length", True)
+    },
+
+    "list": {"struct": """
+        <list
+          id = ID
+          itemType = QName
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, simpleType?)
+        </list>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("list", ["id", "itemType"], 
+                re.compile("((?:annotation )?(?:simpleType )?)$"))
+        },
+        "reduce": ReduceList
+    },
+
+    "maxExclusive": {"struct": """
+        <maxInclusive
+          fixed = boolean : false
+          id = ID
+          value = anySimpleType
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </maxInclusive>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("maxExclusive",
+                ["fixed", "id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("maxExclusive", True)
+    },
+
+    "maxInclusive": {"struct": """
+        <maxExclusive
+          fixed = boolean : false
+          id = ID
+          value = anySimpleType
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </maxExclusive>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("maxInclusive", 
+                ["fixed", "id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("maxInclusive", True)
+    },
+
+    "maxLength": {"struct": """
+        <maxLength
+          fixed = boolean : false
+          id = ID
+          value = nonNegativeInteger
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </maxLength>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("maxLength", 
+                ["fixed", "id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("maxLength", True)
+    },
+
+    "minExclusive": {"struct": """
+        <minExclusive
+          fixed = boolean : false
+          id = ID
+          value = anySimpleType
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </minExclusive>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("minExclusive", 
+                ["fixed", "id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("minExclusive", True)
+    },
+
+    "minInclusive": {"struct": """
+        <minInclusive
+          fixed = boolean : false
+          id = ID
+          value = anySimpleType
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </minInclusive>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("minInclusive", 
+                ["fixed", "id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("minInclusive", True)
+    },
+
+    "minLength": {"struct": """
+        <minLength
+          fixed = boolean : false
+          id = ID
+          value = nonNegativeInteger
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </minLength>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("minLength",
+                ["fixed", "id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("minLength", True)
+    },
+
+    "pattern": {"struct": """
+        <pattern
+          id = ID
+          value = string
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </pattern>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("pattern", ["id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("pattern", False)
+    },
+
+    "redefine": {"struct": """
+        <redefine
+          id = ID
+          schemaLocation = anyURI
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation | (simpleType | complexType | group | attributeGroup))*
+        </redefine>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("refine", ["id", "schemaLocation"], 
+                re.compile("((?:annotation |(?:simpleType |complexType |group |attributeGroup ))*)"))
+        },
+        "reduce": ReduceRedefine
+    },
+
+    "restriction": {"struct": """
+        <restriction
+          base = QName
+          id = ID
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))
+        </restriction>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("restriction", ["base", "id"], 
+                re.compile("((?:annotation )?(?:(?:simpleType )?(?:(?:minExclusive |minInclusive |maxExclusive |maxInclusive |totalDigits |fractionDigits |length |minLength |maxLength |enumeration |whiteSpace |pattern )*)))")),
+            "simpleContent": GenerateElement("restriction", ["base", "id"], 
+                re.compile("((?:annotation )?(?:(?:simpleType )?(?:(?:minExclusive |minInclusive |maxExclusive |maxInclusive |totalDigits |fractionDigits |length |minLength |maxLength |enumeration |whiteSpace |pattern )*)?(?:(?:attribute |attributeGroup )*(?:anyAttribute )?)))")),
+            "complexContent": GenerateElement("restriction", ["base", "id"], 
+                re.compile("((?:annotation )?(?:(?:simpleType )?(?:group |all |choice |sequence )?(?:(?:attribute |attributeGroup )*(?:anyAttribute )?)))")),
+        },
+        "reduce": ReduceRestriction
+    },
+
+    "schema": {"struct": """
+        <schema
+          attributeFormDefault = (qualified | unqualified) : unqualified
+          blockDefault = (#all | List of (extension | restriction | substitution))  : ''
+          elementFormDefault = (qualified | unqualified) : unqualified
+          finalDefault = (#all | List of (extension | restriction | list | union))  : ''
+          id = ID
+          targetNamespace = anyURI
+          version = token
+          xml:lang = language
+          {any attributes with non-schema namespace . . .}>
+          Content: ((include | import | redefine | annotation)*, (((simpleType | complexType | group | attributeGroup) | element | attribute | notation), annotation*)*)
+        </schema>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("schema",
+                ["attributeFormDefault", "blockDefault", "elementFormDefault", "finalDefault", "id", "targetNamespace", "version", "lang"], 
+                re.compile("((?:include |import |redefine |annotation )*(?:(?:(?:simpleType |complexType |group |attributeGroup )|element |attribute |annotation )(?:annotation )*)*)"))
+        }
+    },
+
+    "selector": {"struct": """
+        <selector
+          id = ID
+          xpath = a subset of XPath expression, see below
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </selector>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("selector", ["id", "xpath"], ONLY_ANNOTATION)
+        },
+        "reduce": ReduceSelector
+    },
+
+    "sequence": {"struct": """
+        <sequence
+          id = ID
+          maxOccurs = (nonNegativeInteger | unbounded)  : 1
+          minOccurs = nonNegativeInteger : 1
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (element | group | choice | sequence | any)*)
+        </sequence>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("sequence", ["id", "maxOccurs", "minOccurs"], 
+                re.compile("((?:annotation )?(?:element |group |choice |sequence |any )*)"))
+        },
+        "reduce": ReduceSequence
+    },
+
+    "simpleContent": {"struct" : """
+        <simpleContent
+          id = ID
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (restriction | extension))
+        </simpleContent>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("simpleContent", ["id"], 
+                re.compile("((?:annotation )?(?:restriction |extension ))"))
+        },
+        "reduce": ReduceSimpleContent
+    },
+
+    "simpleType": {"struct" : """
+        <simpleType
+          final = (#all | List of (list | union | restriction))
+          id = ID
+          name = NCName
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (restriction | list | union))
+        </simpleType>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("simpleType", ["final", "id", "name"], 
+                re.compile("((?:annotation )?(?:restriction |list |union ))"))
+        },
+        "reduce": ReduceSimpleType
+    },
+
+    "totalDigits": {"struct" : """
+        <totalDigits
+          fixed = boolean : false
+          id = ID
+          value = positiveInteger
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </totalDigits>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("totalDigits", 
+                ["fixed", "id", "value"], ONLY_ANNOTATION),
+        },
+        "reduce": GenerateFacetReducing("totalDigits", True)
+    },
+
+    "union": {"struct": """
+        <union
+          id = ID
+          memberTypes = List of QName
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, simpleType*)
+        </union>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("union", ["id", "memberTypes"], 
+                re.compile("((?:annotation )?(?:simpleType )*)"))
+        },
+        "reduce": ReduceUnion
+    },
+
+    "unique": {"struct": """
+        <unique
+          id = ID
+          name = NCName
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?, (selector, field+))
+        </unique>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("unique", ["id", "name"], 
+                re.compile("((?:annotation )?(?:selector |(?:field )+))"))
+        },
+        "reduce": ReduceUnique
+    },
+    
+    "whiteSpace": {"struct" : """
+        <whiteSpace
+          fixed = boolean : false
+          id = ID
+          value = (collapse | preserve | replace)
+          {any attributes with non-schema namespace . . .}>
+          Content: (annotation?)
+        </whiteSpace>""",
+        "type": SYNTAXELEMENT, 
+        "extract": {
+            "default": GenerateElement("whiteSpace", 
+                ["fixed", "id", "value"], ONLY_ANNOTATION)
+        },
+        "reduce": GenerateFacetReducing("whiteSpace", True)
+    },
+
+#-------------------------------------------------------------------------------
+#                       Syntax attributes definition
+#-------------------------------------------------------------------------------
+
+    "abstract": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GetBoolean
+        },
+        "default": {
+            "default": False
+        }
+    },
+
+    "attributeFormDefault": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateEnumeratedExtraction("member attributeFormDefault", ["qualified", "unqualified"])
+        },
+        "default": {
+            "default": "unqualified"
+        }
+    },
+    
+    "base": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameExtraction("member base", QName_model)
+        }
+    },
+    
+    "block": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateGetList("block", ["restriction", "extension", "substitution"])
+        }
+    },
+    
+    "blockDefault": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateGetList("block", ["restriction", "extension", "substitution"])
+        },
+        "default": {
+            "default": ""
+        }
+    },
+    
+    "default": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GetAttributeValue
+        }
+    },
+
+    "elementFormDefault": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateEnumeratedExtraction("member elementFormDefault", ["qualified", "unqualified"])
+        },
+        "default": {
+            "default": "unqualified"
+        }
+    },
+    
+    "final": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateGetList("final", ["restriction", "extension", "substitution"]),
+            "simpleType": GenerateGetList("final", ["list", "union", "restriction"])
+        }
+    },
+
+    "finalDefault": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateGetList("finalDefault", ["restriction", "extension", "list", "union"])
+        },
+        "default": {
+            "default": ""
+        }
+    },
+    
+    "fixed": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GetBoolean,
+            "attribute": GetAttributeValue,
+            "element": GetAttributeValue
+        },
+        "default": {
+            "default": False,
+            "attribute": None,
+            "element": None
+        }
+    },
+
+    "form": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateEnumeratedExtraction("member form", ["qualified", "unqualified"])
+        }
+    },
+
+    "id": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameExtraction("member id", NCName_model)
+        }
+    },
+    
+    "itemType": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameExtraction("member itemType", QName_model)
+        }
+    },
+
+    "memberTypes": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameListExtraction("member memberTypes", QNames_model)
+        },
+    },
+    
+    "maxOccurs": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateLimitExtraction(),
+            "all": GenerateLimitExtraction(1, 1, False)
+        },
+        "default": {
+            "default": 1
+        }
+    },
+
+    "minOccurs": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateLimitExtraction(unbounded = False),
+            "all": GenerateLimitExtraction(0, 1, False)
+        },
+        "default": {
+            "default": 1
+        }
+    },
+
+    "mixed": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GetBoolean
+        },
+        "default": {
+            "default": None,
+            "complexType": False
+        }
+    },
+    
+    "name": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameExtraction("member name", NCName_model)
+        }
+    },
+    
+    "namespace": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameExtraction("member namespace", URI_model),
+            "any": GetNamespaces
+        },
+        "default": {
+            "default": None,
+            "any": "##any"
+        }
+    },
+
+    "nillable": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GetBoolean
+        },
+    },
+    
+    "processContents": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateEnumeratedExtraction("member processContents", ["lax", "skip", "strict"])
+        },
+        "default": {
+            "default": "strict"
+        }
+    },
+    
+    "ref": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameExtraction("member ref", QName_model)
+        }
+    },
+
+    "refer": {
+        "type": SYNTAXATTRIBUTE,
+        "extract": {
+            "default": GenerateModelNameExtraction("member refer", QName_model)
+        }
+    },
+    
+    "schemaLocation": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameExtraction("member schemaLocation", URI_model)
+        }
+    },
+    
+    "source": {
+        "type": SYNTAXATTRIBUTE,
+        "extract": {
+            "default": GenerateModelNameExtraction("member source", URI_model)
+        }
+    },
+    
+    "substitutionGroup": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameExtraction("member substitutionGroup", QName_model)
+        }
+    },
+
+    "targetNamespace": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameExtraction("member targetNamespace", URI_model)
+        }
+    },
+    
+    "type": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateModelNameExtraction("member type", QName_model)
+        }
+    },
+
+    "use": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GenerateEnumeratedExtraction("member usage", ["required", "optional", "prohibited"])
+        },
+        "default": {
+            "default": "optional"
+        }
+    },
+
+    "value": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": GetAttributeValue,
+            "fractionDigits": GenerateIntegerExtraction(minInclusive=0),
+            "length": GenerateIntegerExtraction(minInclusive=0),
+            "maxLength": GenerateIntegerExtraction(minInclusive=0),
+            "minLength": GenerateIntegerExtraction(minInclusive=0),
+            "totalDigits": GenerateIntegerExtraction(minExclusive=0),
+            "whiteSpace": GenerateEnumeratedExtraction("value", ["collapse", "preserve", "replace"])
+        }
+    },
+
+    "version": {
+        "type": SYNTAXATTRIBUTE,
+        "extract": {
+            "default": GetToken
+        }
+    },
+
+    "xpath": {
+        "type": SYNTAXATTRIBUTE, 
+        "extract": {
+            "default": NotSupportedYet("xpath")
+        }
+    },
+    
+#-------------------------------------------------------------------------------
+#                           Simple types definition
+#-------------------------------------------------------------------------------
+
+    "string": {
+        "type": SIMPLETYPE,
+        "basename": "string",
+        "extract": GetAttributeValue,
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x : x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "normalizedString": {
+        "type": SIMPLETYPE,
+        "basename": "normalizedString",
+        "extract": GetNormalizedString,
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x : x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "token": {
+        "type": SIMPLETYPE,
+        "basename": "token",  
+        "extract": GetToken,
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x : x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+    
+    "base64Binary": {
+        "type": SIMPLETYPE, 
+        "basename": "base64Binary", 
+        "extract": NotSupportedYet("base64Binary"),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+    
+    "hexBinary": {
+        "type": SIMPLETYPE,
+        "basename": "hexBinary", 
+        "extract": GetHexInteger,
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: ("%."+str(int(round(len("%X"%x)/2.)*2))+"X")%x),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+
+    "integer": {
+        "type": SIMPLETYPE,
+        "basename": "integer", 
+        "extract": GenerateIntegerExtraction(),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+    
+    "positiveInteger": {
+        "type": SIMPLETYPE,
+        "basename": "positiveInteger", 
+        "extract": GenerateIntegerExtraction(minExclusive=0),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+    
+    "negativeInteger": {
+        "type": SIMPLETYPE,
+        "basename": "negativeInteger",
+        "extract": GenerateIntegerExtraction(maxExclusive=0),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+    
+    "nonNegativeInteger": {
+        "type": SIMPLETYPE, 
+        "basename": "nonNegativeInteger", 
+        "extract": GenerateIntegerExtraction(minInclusive=0),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+    
+    "nonPositiveInteger": {
+        "type": SIMPLETYPE,
+        "basename": "nonPositiveInteger", 
+        "extract": GenerateIntegerExtraction(maxInclusive=0),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+    
+    "long": {
+        "type": SIMPLETYPE,
+        "basename": "long",
+        "extract": GenerateIntegerExtraction(minInclusive=-2**63,maxExclusive=2**63),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+    
+    "unsignedLong": {
+        "type": SIMPLETYPE,
+        "basename": "unsignedLong",
+        "extract": GenerateIntegerExtraction(minInclusive=0,maxExclusive=2**64),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+
+    "int": {
+        "type": SIMPLETYPE,
+        "basename": "int",
+        "extract": GenerateIntegerExtraction(minInclusive=-2**31,maxExclusive=2**31),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+
+    "unsignedInt": {
+        "type": SIMPLETYPE,
+        "basename": "unsignedInt",
+        "extract": GenerateIntegerExtraction(minInclusive=0,maxExclusive=2**32),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+
+    "short": {
+        "type": SIMPLETYPE,
+        "basename": "short",
+        "extract": GenerateIntegerExtraction(minInclusive=-2**15,maxExclusive=2**15),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+
+    "unsignedShort": {
+        "type": SIMPLETYPE,
+        "basename": "unsignedShort", 
+        "extract": GenerateIntegerExtraction(minInclusive=0,maxExclusive=2**16),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+
+    "byte": {
+        "type": SIMPLETYPE,
+        "basename": "byte",
+        "extract": GenerateIntegerExtraction(minInclusive=-2**7,maxExclusive=2**7),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+
+    "unsignedByte": {
+        "type": SIMPLETYPE,
+        "basename": "unsignedByte",
+        "extract": GenerateIntegerExtraction(minInclusive=0,maxExclusive=2**8),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: 0,
+        "check": lambda x: isinstance(x, IntType)
+    },
+
+    "decimal": {
+        "type": SIMPLETYPE,
+        "basename": "decimal",
+        "extract": GenerateFloatExtraction("decimal"),
+        "facets": DECIMAL_FACETS,
+        "generate": GenerateFloatXMLText(),
+        "initial": lambda: 0.,
+        "check": lambda x: isinstance(x, (IntType, FloatType))
+    },
+
+    "float": {
+        "type": SIMPLETYPE,
+        "basename": "float",
+        "extract": GenerateFloatExtraction("float", ["INF", "-INF", "NaN"]),
+        "facets": NUMBER_FACETS,
+        "generate": GenerateFloatXMLText(["INF", "-INF", "NaN"]),
+        "initial": lambda: 0.,
+        "check": lambda x: {"INF" : True, "-INF" : True, "NaN" : True}.get(x, isinstance(x, (IntType, FloatType)))
+    },
+
+    "double": {
+        "type": SIMPLETYPE,
+        "basename": "double",
+        "extract": GenerateFloatExtraction("double", ["INF", "-INF", "NaN"]),
+        "facets": NUMBER_FACETS,
+        "generate": GenerateFloatXMLText(["INF", "-INF", "NaN"]),
+        "initial": lambda: 0.,
+        "check": lambda x: {"INF" : True, "-INF" : True, "NaN" : True}.get(x, isinstance(x, (IntType, FloatType)))
+    },
+
+    "boolean": {
+        "type": SIMPLETYPE,
+        "basename": "boolean",
+        "extract": GetBoolean,
+        "facets": GenerateDictFacets(["pattern", "whiteSpace"]),
+        "generate": GenerateSimpleTypeXMLText(lambda x:{True : "true", False : "false"}[x]),
+        "initial": lambda: False,
+        "check": lambda x: isinstance(x, BooleanType)
+    },	
+
+    "duration": {
+        "type": SIMPLETYPE,
+        "basename": "duration",
+        "extract": NotSupportedYet("duration"),
+        "facets": NUMBER_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "dateTime": {
+        "type": SIMPLETYPE,
+        "basename": "dateTime",
+        "extract": GetDateTime,
+        "facets": NUMBER_FACETS,
+        "generate": GenerateSimpleTypeXMLText(datetime.datetime.isoformat),
+        "initial": lambda: datetime.datetime(1,1,1,0,0,0,0),
+        "check": lambda x: isinstance(x, datetime.datetime)
+    },
+
+    "date": {
+        "type": SIMPLETYPE,
+        "basename": "date",
+        "extract": GetDate,
+        "facets": NUMBER_FACETS,
+        "generate": GenerateSimpleTypeXMLText(datetime.date.isoformat),
+        "initial": lambda: datetime.date(1,1,1),
+        "check": lambda x: isinstance(x, datetime.date)
+    },
+    
+    "time": {
+        "type": SIMPLETYPE,
+        "basename": "time",
+        "extract": GetTime,
+        "facets": NUMBER_FACETS,
+        "generate": GenerateSimpleTypeXMLText(datetime.time.isoformat),
+        "initial": lambda: datetime.time(0,0,0,0),
+        "check": lambda x: isinstance(x, datetime.time)
+    },
+
+    "gYear": {
+        "type": SIMPLETYPE,
+        "basename": "gYear",
+        "extract": NotSupportedYet("gYear"),
+        "facets": NUMBER_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "gYearMonth": {
+        "type": SIMPLETYPE,
+        "basename": "gYearMonth",
+        "extract": NotSupportedYet("gYearMonth"),
+        "facets": NUMBER_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "gMonth": {
+        "type": SIMPLETYPE,
+        "basename": "gMonth",
+        "extract": NotSupportedYet("gMonth"),
+        "facets": NUMBER_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "gMonthDay": {
+        "type": SIMPLETYPE,
+        "basename": "gMonthDay",
+        "extract": NotSupportedYet("gMonthDay"),
+        "facets": NUMBER_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "gDay": {
+        "type": SIMPLETYPE,
+        "basename": "gDay",
+        "extract": NotSupportedYet("gDay"),
+        "facets": NUMBER_FACETS,
+        "generate": GenerateSimpleTypeXMLText(str),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "Name": {
+        "type": SIMPLETYPE,
+        "basename": "Name",
+        "extract": GenerateModelNameExtraction("Name", Name_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+    
+    "QName": {
+        "type": SIMPLETYPE,
+        "basename": "QName",
+        "extract": GenerateModelNameExtraction("QName", QName_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "NCName": {
+        "type": SIMPLETYPE,
+        "basename": "NCName",
+        "extract": GenerateModelNameExtraction("NCName", NCName_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "anyURI": {
+        "type": SIMPLETYPE,
+        "basename": "anyURI",
+        "extract": GenerateModelNameExtraction("anyURI", URI_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "language": {
+        "type": SIMPLETYPE,
+        "basename": "language",
+        "extract": GenerateModelNameExtraction("language", LANGUAGE_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "en",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "ID": {
+        "type": SIMPLETYPE,
+        "basename": "ID",
+        "extract": GenerateModelNameExtraction("ID", Name_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "IDREF": {
+        "type": SIMPLETYPE,
+        "basename": "IDREF",
+        "extract": GenerateModelNameExtraction("IDREF", Name_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "IDREFS": {
+        "type": SIMPLETYPE,
+        "basename": "IDREFS",
+        "extract": GenerateModelNameExtraction("IDREFS", Names_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "ENTITY": {
+        "type": SIMPLETYPE,
+        "basename": "ENTITY",
+        "extract": GenerateModelNameExtraction("ENTITY", Name_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "ENTITIES": {
+        "type": SIMPLETYPE,
+        "basename": "ENTITIES",
+        "extract": GenerateModelNameExtraction("ENTITIES", Names_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "NOTATION": {
+        "type": SIMPLETYPE,
+        "basename": "NOTATION",
+        "extract": GenerateModelNameExtraction("NOTATION", Name_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "NMTOKEN": {
+        "type": SIMPLETYPE,
+        "basename": "NMTOKEN",
+        "extract": GenerateModelNameExtraction("NMTOKEN", NMToken_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    "NMTOKENS": {
+        "type": SIMPLETYPE,
+        "basename": "NMTOKENS",
+        "extract": GenerateModelNameExtraction("NMTOKENS", NMTokens_model),
+        "facets": STRING_FACETS,
+        "generate": GenerateSimpleTypeXMLText(lambda x: x),
+        "initial": lambda: "",
+        "check": lambda x: isinstance(x, (StringType, UnicodeType))
+    },
+
+    # Complex Types
+    "anyType": {"type": COMPLEXTYPE, "extract": lambda x:None},
+}
+
+if __name__ == '__main__':
+    classes = GenerateClassesFromXSD("test.xsd")
+    
+    # Code for test of test.xsd
+    xmlfile = open("po.xml", 'r')
+    tree = minidom.parse(xmlfile)
+    xmlfile.close()
+    test = classes["PurchaseOrderType"]()
+    for child in tree.childNodes:
+        if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "purchaseOrder":
+            test.loadXMLTree(child)
+    test.items.item[0].setquantity(2)
+    testfile = open("test.xml", 'w')
+    testfile.write(u'<?xml version=\"1.0\"?>\n')
+    testfile.write(test.generateXMLText("purchaseOrder").encode("utf-8"))
+    testfile.close()