xmlclass/xmlclass.py
changeset 151 aaa80b48bead
parent 125 394d9f168258
child 153 f0e8e7f58a5a
--- a/xmlclass/xmlclass.py	Tue Jan 22 10:53:34 2008 +0100
+++ b/xmlclass/xmlclass.py	Tue Jan 22 10:57:41 2008 +0100
@@ -23,19 +23,34 @@
 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 from xml.dom import minidom
-import sys,re
+import sys, re, datetime
 from types import *
-from datetime import *
 from new import classobj
 
+LANGUAGES = ["en-US", "fr-FR", "en", "fr"]
+
+"""
+Regular expression models for check all kind of string
+"""
+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.]*/?)*)$')
+
+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(tzinfo):
+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":
@@ -56,11 +71,20 @@
     def dst(self, dt):
         return ZERO
 
-XSD_INTEGER_TYPES = ["integer","nonPositiveInteger","negativeInteger","long",
-    "int","short","byte","nonNegativeInteger","unsignedLong","unsignedInt",
-    "unsignedShort","unsignedByte","positiveInteger"]
-
-XSD_STRING_TYPES = ["string","normalizedString","token","anyURI","NMTOKEN","language"]
+[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 asked
+    are not yet supported by xmlclass
+    @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
@@ -70,529 +94,893 @@
     second = first + len(balise) + 1
     return "\t".expandtabs(first), "\t".expandtabs(second)
 
-"""
-Function that extracts data from a node
-"""
-def GetAttributeValue(attr):
+
+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 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
 
-"""
-Function that computes value from a python type (Only Boolean are critical because
-there is no uppercase in plcopen)
-"""
-def ComputeValue(value):
-    if type(value) == BooleanType:
-        if value:
-            return "true"
-        else:
-            return "false"
+
+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:
+        return GetAttributeValue(attr).replace("\n", " ").replace("\t", " ")
     else:
-        return str(value)
-
-"""
-Function that extracts a value from a string following the xsd type given
-"""
-def GetComputedValue(attr_type, value):
-    type_compute = attr_type[4:].replace("[]", "")
-    if type_compute == "boolean":
-         if value == "true":
-             return True
-         elif value == "false":
-             return False
-         else:
-            raise ValueError, "\"%s\" is not a valid boolean!"%value
-    elif type_compute in XSD_INTEGER_TYPES:
-        return int(value)
-    elif type_compute in ["decimal", "float", "double"]:
-        computed_value = float(value)
-        if computed_value % 1 == 0:
-            return int(computed_value)
-        return computed_value
-    elif type_compute in XSD_STRING_TYPES:
+        return attr.replace("\n", " ").replace("\t", " ")
+
+
+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
+    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
-    elif type_compute == "time":
-        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 time(*time_values)
-        else:
-            raise ValueError, "\"%s\" is not a valid time!"%value
-    elif type_compute == "date":
-        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 date(*date_values)
-        else:
-            raise ValueError, "\"%s\" is not a valid date!"%value
-    elif type_compute == "dateTime":
-        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_values)
-        else:
-            raise ValueError, "\"%s\" is not a valid datetime!"%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
+        try:
+            if value in extra_values:
+                return value
+            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:
-        print "Can't affect: %s"%type_compute
+        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:
+        result = time_model.match(GetAttributeValue(attr))
+    else:
+        result = time_model.match(attr)
+    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\" is not 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:
+        result = date_model.match(GetAttributeValue(attr))
+    else:
+        result = date_model.match(attr)
+    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\" is not 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:
+        result = datetime_model.match(GetAttributeValue(attr))
+    else:
+        result = datetime_model.match(attr)
+    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\" is not 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\" is not 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 "\"%s\" isn't a valid value for this member limit!"%value
+        try:
+            limit = int(value)
+        except:
+            raise "\"%s\" isn't a valid value for this member limit!"%value
+        if limit < 0:
+            raise "\"%s\" isn't a valid value for this member limit!"%value
+        elif min is not None and limit < min:
+            raise "\"%s\" isn't a valid value for this member limit!"%value
+        elif max is not None and limit > max:
+            raise "\"%s\" isn't a valid value for this member limit!"%value
+        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 the items extracted 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()
+    
+    def GenerateAny(value, name = None, indent = 0):
+        return "<![CDATA[%s]]>\n"%str(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 GetInitialValueFunction(value):
-    def GetInitialValue():
-        return value
-    return GetInitialValue
-
-"""
-Class that generate class from an XML Tree 
+    
+    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 element_name in infos["extract"]:
+                        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, xsd_tree):
-        self.XML_Tree = xsd_tree
+    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.ComputedTypes = {}
         self.AlreadyComputed = {}
 
-    """
-    This function recursively creates a definition of the classes and their attributes
-    for plcopen from the xsd file of plcopen opened in a DOM model
-    """
-    def GenerateXSDClasses(self, tree, parent, sequence = False):
-        attributes = {}
-        inheritance = []
-        if sequence:
-            order = []
-        # The lists of attributes and inheritance of the node are generated from the childrens 
-        for node in tree.childNodes:
-            # We make fun of #text elements and all other tags that don't are xsd tags
-            if node.nodeName != "#text" and node.nodeName.startswith("xsd:"):
-                recursion = False
-                name = node.nodeName[4:].encode()
-                
-                # This tags defines an attribute of the class
-                if name in ["element", "attribute"]:
-                    nodename = GetAttributeValue(node._attrs["name"])
-                    default = None
-                    if "type" in node._attrs:
-                        nodetype = GetAttributeValue(node._attrs["type"])
-                        if nodetype.startswith("xsd"):
-                            nodetype = nodetype.replace("xsd", "bse")
-                        elif nodetype.startswith("ppx"):
-                            nodetype = nodetype.replace("ppx", "cls")
+    def GetQualifiedNameInfos(self, name, namespace = None, canbenone = False):
+        if namespace is None:
+            if name in self.Namespaces[self.SchemaNamespace]:
+                return self.Namespaces[self.SchemaNamespace][name]
+            for space, elements in self.Namespaces.items():
+                if space != self.SchemaNamespace and name in elements:
+                    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 "elements" in group:
+                        elements = group["elements"]
+                    elif "choices" in group:
+                        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 namespace in self.Namespaces:
+            if name in self.Namespaces[namespace]:
+                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 "elements" in group:
+                        elements = group["elements"]
+                    elif "choices" in group:
+                        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 name in self.Namespaces[self.SchemaNamespace]:
+                return name, None
+            for space, elements in self.Namespaces.items():
+                if space != self.SchemaNamespace and name in elements:
+                    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 "elements" in group:
+                        elements = group["elements"]
+                    elif "choices" in group:
+                        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 namespace in self.Namespaces:
+            if name in self.Namespaces[namespace]:
+                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 "elements" in group:
+                        elements = group["elements"]
+                    elif "choices" in group:
+                        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 attr in self.Namespaces[self.SchemaNamespace] and "default" in self.Namespaces[self.SchemaNamespace][attr]:
+                if element_name in self.Namespaces[self.SchemaNamespace][attr]["default"]:
+                    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 "name" in child_infos[1] 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 "name" in child_infos[1] 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 typename not in self.XMLClassDefinitions:
+            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 "elements" in infos:
+                    elements = infos["elements"]
+                elif "choices" in infos:
+                    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 None
+        
+        # If base classes haven't been generated
+        bases = []
+        if "base" in classinfos:
+            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:
-                        # The type of attribute is defines in the child tree so we generate a new class
-                        # No name is defined so we create one from nodename and parent class name
-                        # (because some different nodes can have the same name)
-                        if parent:
-                            classname = "%s_%s"%(parent, nodename)
-                        else:
-                            classname = nodename
-                        if len(node.childNodes) > 0:
-                            self.GenerateXSDClasses(node, classname)
-                            nodetype = "cls:%s"%classname
-                        else:
-                            nodetype = classname
-                    if name == "attribute":
-                        if "use" in node._attrs:
-                            use = GetAttributeValue(node._attrs["use"])
-                        else:
-                            use = "optional"
-                        if "default" in node._attrs:
-                            default = GetAttributeValue(node._attrs["default"])
-                    elif name == "element":
-                        # If a tag can be written more than one time we define a list attribute
-                        if "maxOccurs" in node._attrs and GetAttributeValue(node._attrs["maxOccurs"]) == "unbounded":
-                            nodetype = "%s[]"%nodetype
-                        if "minOccurs" in node._attrs and GetAttributeValue(node._attrs["minOccurs"]) == "0":
-                            use = "optional"
-                        else:
-                            use = "required"
-                    attributes[nodename] = (nodetype, name, use, default)
-                    if sequence:
-                        order.append(nodename)
-                
-                # This tag defines a new class
-                elif name == "complexType" or name == "simpleType":
-                    if "name" in node._attrs:
-                        classname = GetAttributeValue(node._attrs["name"])
-                        super, attrs = self.GenerateXSDClasses(node, classname)
+                        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:
-                        classname = parent
-                        super, attrs = self.GenerateXSDClasses(node, classname.split("_")[-1])
-                    # When all attributes and inheritances have been extracted, the
-                    # values are added in the list of classes to create
-                    if self.XMLClassDefinitions.get(classname, None) == None:
-                        self.XMLClassDefinitions[classname] = (super, attrs)
-                    elif self.XMLClassDefinitions[classname] != (super, attrs):
-                        print "A different class has already got %s for name"%classname
-                
-                # This tag defines an attribute that can have different types
-                elif name == "choice":
-                    super, attrs = self.GenerateXSDClasses(node, parent)
-                    
-                    choices = {}
-                    for attr, values in attrs.items():
-                        if attr == "ref":
-                            choices[attr] = values
-                        else:
-                            choices[attr] = values[0]
-                    if "maxOccurs" in node._attrs and GetAttributeValue(node._attrs["maxOccurs"]) == "unbounded":
-                        attributes["multichoice_content"] = choices
-                        if sequence:
-                            order.append("multichoice_content")
-                    else:
-                        attributes["choice_content"] = choices
-                        if sequence:
-                            order.append("choice_content")
-                
-                # This tag defines the order in which class attributes must be written
-                # in plcopen xml file. We have to store this order like an attribute
-                elif name in "sequence":
-                    super, attrs, order = self.GenerateXSDClasses(node, parent, True)
-                    if "maxOccurs" in node._attrs and GetAttributeValue(node._attrs["maxOccurs"]) == "unbounded":
-                        for attr, (attr_type, xml_type, write_type, default) in attrs.items():
-                            attrs[attr] = ("%s[]"%attr_type, xml_type, write_type, default)
-                    if "minOccurs" in node._attrs and GetAttributeValue(node._attrs["minOccurs"]) == "0":
-                        for attr, (attr_type, xml_type, write_type, default) in attrs.items():
-                            attrs[attr] = (attr_type, xml_type, "optional", default)
-                    inheritance.extend(super)
-                    attributes.update(attrs)
-                    attributes["order"] = order
-                
-                # This tag defines of types
-                elif name == "group":
-                    if "name" in node._attrs:
-                        nodename = GetAttributeValue(node._attrs["name"])
-                        super, attrs = self.GenerateXSDClasses(node, None)
-                        self.XMLClassDefinitions[nodename] = (super, {"group":attrs["choice_content"]})
-                    elif "ref" in node._attrs:
-                        if "ref" not in attributes:
-                            attributes["ref"] = [GetAttributeValue(node._attrs["ref"])]
-                        else:
-                            attributes["ref"].append(GetAttributeValue(node._attrs["ref"]))
-                
-                # This tag define a base class for the node
-                elif name == "extension":
-                    super = GetAttributeValue(node._attrs["base"])
-                    if super.startswith("xsd"):
-                        super = super.replace("xsd", "bse")
-                    elif super.startswith("ppx"):
-                        super = super.replace("ppx", "cls")
-                    inheritance.append(super[4:])
-                    recursion = True
-                    
-                # This tag defines a restriction on the type of attribute
-                elif name == "restriction":
-                    basetype = GetAttributeValue(node._attrs["base"])
-                    if basetype.startswith("xsd"):
-                        basetype = basetype.replace("xsd", "bse")
-                    elif basetype.startswith("ppx"):
-                        basetype = basetype.replace("ppx", "cls")
-                    attributes["basetype"] = basetype
-                    recursion = True
-                
-                # This tag defines an enumerated type
-                elif name == "enumeration":
-                    if "enum" not in attributes:
-                        attributes["enum"] = [GetAttributeValue(node._attrs["value"])]
-                    else:
-                        attributes["enum"].append(GetAttributeValue(node._attrs["value"]))
-                
-                # This tags defines a restriction on a numerical value
-                elif name in ["minInclusive","maxInclusive"]:
-                    if "limit" not in attributes:
-                        attributes["limit"] = {}
-                    if name == "minInclusive":
-                        attributes["limit"]["min"] = eval(GetAttributeValue(node._attrs["value"]))
-                    elif name == "maxInclusive":
-                        attributes["limit"]["max"] = eval(GetAttributeValue(node._attrs["value"]))
-                
-                # This tag are not important but their childrens are. The childrens are then parsed. 
-                elif name in ["complexContent", "schema"]:
-                    recursion = True
-                
-                # We make fun of xsd documentation
-                elif name in ["annotation"]:
-                    pass
-                
-                else:
-                    # Unable this line to print XSD element that is not yet supported 
-                    #print name
-                    self.GenerateXSDClasses(node, parent)
-                
-                # Parse the childrens of node
-                if recursion:
-                    super, attrs = self.GenerateXSDClasses(node, parent)
-                    inheritance.extend(super)
-                    attributes.update(attrs)
-        
-        # if sequence tag have been found, order is returned
-        if sequence:
-            return inheritance, attributes, order
-        else:
-            return inheritance, attributes
-
-    """
-    Funtion that returns the Python type and default value for a given type
-    """
-    def GetTypeInitialValue(self, attr_type, default = None):
-        type_compute = attr_type[4:].replace("[]", "")
-        if attr_type.startswith("bse:"):
-            if type_compute == "boolean":
-                if default:
-                    def GetBooleanInitialValue():
-                        return default == "true"
-                    return BooleanType, GetBooleanInitialValue
-                else:
-                    return BooleanType, lambda:False
-            elif type_compute in ["unsignedLong","long","integer"]:
-                if default:
-                    def GetIntegerInitialValue():
-                        return int(default)
-                    return IntType, GetIntegerInitialValue
-                else:
-                    return IntType, lambda:0
-            elif type_compute == "decimal":
-                if default:
-                    def GetFloatInitialValue():
-                        return float(default)
-                    return FloatType, GetFloatInitialValue
-                else:
-                    return FloatType, lambda:0.
-            elif type_compute in ["string","anyURI","NMTOKEN"]:
-                if default:
-                    def GetStringInitialValue():
-                        return default
-                    return StringType, GetStringInitialValue
-                else:
-                    return StringType, lambda:""
-            elif type_compute == "time":
-                if default:
-                    def GetTimeInitialValue():
-                        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 time(*time_values)
-                        return time(0,0,0,0)
-                    return time, GetTimeInitialValue
-                else:
-                    return time, lambda:time(0,0,0,0)
-            elif type_compute == "date":
-                if default:
-                    def GetDateInitialValue():
-                        result = date_model.match(value)
-                        if result:
-                            date_values = [int(v) for v in result.groups()]
-                            return date(*date_values)
-                        return date(1,1,1)
-                    return date, GetDateInitialValue
-                else:
-                    return date, lambda:date(1,1,1)
-            elif type_compute == "dateTime":
-                if default:
-                    def GetDateTimeInitialValue():
-                        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)])
-                            return datetime(*datetime_values)
-                        return datetime(1,1,1,0,0,0,0)
-                    return datetime, GetDateTimeInitialValue
-                else:
-                    return datetime, lambda:datetime(1,1,1,0,0,0,0)
-            elif type_compute == "language":
-                if default:
-                    def GetStringInitialValue():
-                        return default
-                    return StringType, GetStringInitialValue
-                else:
-                    return StringType, lambda:"en-US"
-            else:
-                print "Can't affect: %s"%type_compute
-        elif attr_type.startswith("cls:"):
-            if self.XMLClassDefinitions.get(type_compute, None) != None:
-                def GetClassInitialValue():
-                    if self.XMLClassDefinitions.get(type_compute, None) != None:
-                        obj = self.ComputedClasses[type_compute]()
-                        if default:
-                            obj.setValue(default)
-                        return obj
-                    return None
-                return self.XMLClassDefinitions[type_compute], GetClassInitialValue
-        return None, lambda:None
-
-    """
-    Funtion that returns the Python type and default value for a given type
-    """
-    def GetInitialValues(self, value_types):
-        initial_values = {}
-        for name, value_type in value_types.items():
-            result = self.GetTypeInitialValue(value_type)
-            if result:
-                initial_values[name] = result[1]
-        return initial_values
-
-    """
-    Methods that generate the classes
-    """
-    def CreateClasses(self):
-        self.GenerateXSDClasses(self.XML_Tree, None)
-        for classname in self.XMLClassDefinitions.keys():
-            self.CreateClass(classname)
-        for classname in self.XMLClassDefinitions.keys():
-            self.MarkUsedClasses(classname)
-        return self.ComputedClasses, self.ComputedTypes
-
-    def CreateClass(self, classname):
-        # Checks that classe haven't been generated yet
-        if not self.AlreadyComputed.get(classname, False) and classname in self.XMLClassDefinitions:
-            self.AlreadyComputed[classname] = True
-            inheritance, attributes = self.XMLClassDefinitions[classname]
-            #print classname, inheritance, attributes
-            members = {}
-            bases = []
+                        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"])
+                classmembers["add%sbytype"%elmtname] = generateAddChoiceByTypeMethod(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)
             
-            # If inheritance classes haven't been generated
-            for base in inheritance:
-                self.CreateClass(base)
-                bases.append(self.ComputedClasses[base])
-            
-            # Checks that all attribute types are available 
-            for attribute, type_attribute in attributes.items():
-                if attribute == "group":
-                    self.ComputedTypes[classname] = type_attribute
-                elif attribute in ["choice_content","multichoice_content"]:
-                    element_types = {}
-                    for attr, value in type_attribute.items():
-                        if attr == "ref":
-                            for ref in value:
-                                self.CreateClass(ref[4:])
-                                element_types.update(self.ComputedTypes[ref[4:]])
-                        else:
-                            element_types[attr] = value
-                    members[attribute] = element_types
-                else:
-                    members[attribute] = type_attribute
-                    if attribute == "enum":
-                        self.ComputedTypes["%s_enum"%classname] = type_attribute
-                    elif attribute not in ["limit", "order"]:
-                        if type_attribute[0].startswith("cls:"):
-                            type_compute = type_attribute[0][4:].replace("[]","")
-                            self.CreateClass(type_compute)
-            if "group" not in attributes:
-                bases = tuple(bases)
-                classmembers = {"IsBaseClass" : True}
-                initialValues = {}
-                for attr, values in members.items():
-                    if attr in ["order", "basetype"]:
-                        pass
-                    
-                    # Class is a enumerated type
-                    elif attr == "enum":
-                        value_type, initial = self.GetTypeInitialValue(members["basetype"])
-                        initialValues["value"] = GetInitialValueFunction(values[0])
-                        classmembers["value"] = values[0]
-                        classmembers["setValue"] = generateSetEnumMethod(values, value_type)
-                        classmembers["getValue"] = generateGetMethod("value")
-                        classmembers["getValidValues"] = generateGetChoicesMethod(values)
-                    
-                    # Class is a limited type
-                    elif attr == "limit":
-                        value_type, initial = self.GetTypeInitialValue(members["basetype"])
-                        if "min" in values:
-                            initial = max(initial, values["min"])
-                        elif "max" in values:
-                            initial = min(initial, values["max"])
-                        initialValues["value"] = GetInitialValueFunction(initial)
-                        classmembers["value"] = initial
-                        classmembers["setValue"] = generateSetLimitMethod(values, value_type)
-                        classmembers["getValue"] = generateGetMethod("value")
-                    
-                    # Class has an attribute that can have different value types
-                    elif attr == "choice_content":
-                        classmembers["content"] = None
-                        initialValues["content"] = lambda:None
-                        classmembers["deleteContent"] = generateDeleteMethod("content")
-                        classmembers["addContent"] = generateAddChoiceMethod(values, self.GetInitialValues(values))
-                        classmembers["setContent"] = generateSetChoiceMethod(values)
-                        classmembers["getContent"] = generateGetMethod("content")
-                        classmembers["getChoices"] = generateGetChoicesMethod(values)
-                    elif attr == "multichoice_content":
-                        classmembers["content"] = []
-                        initialValues["content"] = lambda:[]
-                        classmembers["appendContent"] = generateAppendChoiceMethod(values)
-                        classmembers["appendContentByType"] = generateAppendChoiceByTypeMethod(values, self.GetInitialValues(values))
-                        classmembers["insertContent"] = generateInsertChoiceMethod(values)
-                        classmembers["removeContent"] = generateRemoveMethod("content")
-                        classmembers["countContent"] = generateCountMethod("content")
-                        classmembers["setContent"] = generateSetMethod("content", ListType)
-                        classmembers["getContent"] = generateGetMethod("content")
-                        classmembers["getChoices"] = generateGetChoicesMethod(values)
-                    
-                    # It's an attribute of the class
-                    else:
-                        attrname = attr[0].upper()+attr[1:]
-                        attr_type, xml_type, write_type, default = values
-                        value_type, initial = self.GetTypeInitialValue(attr_type, default)
-                        # Value of the attribute is a list
-                        if attr_type.endswith("[]"):
-                            classmembers[attr] = []
-                            initialValues[attr] = lambda:[]
-                            classmembers["append"+attrname] = generateAppendMethod(attr, value_type)
-                            classmembers["insert"+attrname] = generateInsertMethod(attr, value_type)
-                            classmembers["remove"+attrname] = generateRemoveMethod(attr)
-                            classmembers["count"+attrname] = generateCountMethod(attr)
-                            classmembers["set"+attrname] = generateSetMethod(attr, ListType)
-                        else:
-                            if write_type == "optional":
-                                classmembers[attr] = None
-                                initialValues[attr] = lambda:None
-                                classmembers["add"+attrname] = generateAddMethod(attr, initial)
-                                classmembers["delete"+attrname] = generateDeleteMethod(attr)
-                            else:
-                                classmembers[attr] = initial()
-                                initialValues[attr] = initial
-                            classmembers["set"+attrname] = generateSetMethod(attr, value_type)
-                        classmembers["get"+attrname] = generateGetMethod(attr)
-                classmembers["__init__"] = generateInitMethod(bases, initialValues)
-                classmembers["loadXMLTree"] = generateLoadXMLTree(bases, members, self.ComputedClasses)
-                classmembers["generateXMLText"] = generateGenerateXMLText(bases, members)
-                classmembers["getElementAttributes"] = generateGetElementAttributes(members, self.ComputedClasses)
-                classmembers["getElementInfos"] = generateGetElementInfos(members, self.ComputedClasses)
-                classmembers["setElementValue"] = generateSetElementValue(members)
-                classmembers["singleLineAttributes"] = True
-                
-                self.ComputedClasses[classname] = classobj(classname, bases, classmembers)
+        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
+        
+        class_definition = classobj(str(classname), bases, classmembers)
+        
+        self.ComputedClasses[classname] = class_definition
+        
+        return {"type" : COMPILEDCOMPLEXTYPE,
+                "name" : classname,
+                "check" : generateClassCheckFunction(class_definition),
+                "initial" : generateClassCreateFunction(class_definition),
+                "extract" : generateClassExtractFunction(class_definition),
+                "generate" : class_definition.generateXMLText}
 
     def MarkUsedClasses(self, classname):
         # Checks that classe haven't been generated yet
@@ -629,7 +1017,9 @@
     Methods that print the classes generated
     """
     def PrintClasses(self):
-        for classname, xmlclass in self.ComputedClasses.items():
+        items = self.ComputedClasses.items()
+        items.sort()
+        for classname, xmlclass in items:
             print "%s : %s"%(classname, str(xmlclass))
         
     def PrintClassNames(self):
@@ -639,211 +1029,268 @@
             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 generateLoadXMLTree(bases, members, classes):
-    def loadXMLTreeMethod(self, tree):
-        # If class is derived, values of inheritance classes are loaded
-        for base in bases:
-            base.loadXMLTree(self, tree)
-        # Class is a enumerated or limited value
-        if "enum" in members.keys() or "limit" in members.keys():
-            attr_value = GetAttributeValue(tree)
-            attr_type = members["basetype"]
-            val = GetComputedValue(attr_type, attr_value)
-            self.setValue(val)
-        else:
-            
-            # Load the node attributes if they are defined in the list
-            for attrname, attr in tree._attrs.items():
-                if attrname in members.keys():
-                    attr_type, xml_type, write_type, default = members[attrname]
-                    attr_value = GetAttributeValue(attr)
-                    if write_type != "optional" or attr_value != "":
-                        # Extracts the value
-                        if attr_type.startswith("bse:"):
-                            val = GetComputedValue(attr_type, attr_value)
-                        elif attr_type.startswith("cls:"):
-                            val = classes[attr_type[4:]]()
-                            val.loadXMLTree(attr)
-                        setattr(self, attrname, val)
-            
-            # Load the node childs if they are defined in the list
+def generateSetattrMethod(factory, classinfos):
+    attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
+    optional_attributes = [attr["name"] 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 name in attributes:
+            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 name in optional_attributes:
+                    return object.__setattr__(self, name, None)
+                else:
+                    raise ValueError, "Attribute '%s' isn't optional."%name
+            elif "fixed" in attributes[name] 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 name in elements:
+            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 "fixed" in elements[name] 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 "base" in classinfos:
+            return classinfos["base"].__setattr__(self, name, value)
+        else:
+            raise AttributeError, "'%s' can't have an attribute '%s'."%(classinfos["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){0, %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}(?:%s )*"%(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") or len(elements) == 0:
+        structure = "".join(elements)
+    else:
+        raise ValueError, "XSD structure not yet supported!"
+    
+    def getStructureMethod(self):
+        if "base" in classinfos:
+            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):
+        if not derived:
+            children_structure = ""
             for node in tree.childNodes:
-                if node.nodeType == node.COMMENT_NODE:
-                    continue
-                name = node.nodeName
-                # We make fun of #text elements
-                if name != "#text":
-                    
-                    # Class has an attribute that can have different value types
-                    if "choice_content" in members.keys() and name in members["choice_content"].keys():
-                        attr_type = members["choice_content"][name]
-                        # Extracts the value
-                        if attr_type.startswith("bse:"):
-                            val = GetComputedValue(attr_type.replace("[]",""), GetAttributeValue(node))
-                        elif attr_type.startswith("cls:"):
-                            val = classes[attr_type[4:].replace("[]","")]()
-                            val.loadXMLTree(node)
-                        else:
-                            val = None
-                        # Stock value in content attribute
-                        if val is not None:
-                            if attr_type.endswith("[]"):
-                                if self.content:
-                                    self.content["value"].append(val)
-                                else:
-                                    self.content = {"name":name,"value":[val]}
-                            else:
-                                self.content = {"name":name,"value":val}
-                        else:
-                            self.content = {"name":name,"value":None}
-                    
-                    # Class has a list of attributes that can have different value types
-                    elif "multichoice_content" in members.keys() and name in members["multichoice_content"].keys():
-                        attr_type = members["multichoice_content"][name]
-                        # Extracts the value
-                        if attr_type.startswith("bse:"):
-                            val = GetComputedValue(attr_type, GetAttributeValue(node))
-                        elif attr_type.startswith("cls:"):
-                            val = classes[attr_type[4:]]()
-                            val.loadXMLTree(node)
-                        # Add to content attribute list
-                        if val:
-                            self.content.append({"name":name,"value":val})
-                    
-                    # The node child is defined in the list
-                    elif name in members.keys():
-                        attr_type, xml_type, write_type, default = members[name]
-                        # Extracts the value
-                        if attr_type.startswith("bse:"):
-                            attr_value = GetAttributeValue(node)
-                            if write_type != "optional" or attr_value != "":
-                                val = GetComputedValue(attr_type.replace("[]",""), attr_value)
-                            else:
-                                val = None
-                        elif attr_type.startswith("cls:"):
-                            val = classes[attr_type[4:].replace("[]","")]()
-                            val.loadXMLTree(node)
-                        # Stock value in attribute
-                        if val:
-                            if attr_type.endswith("[]"):
-                                getattr(self, name).append(val)
-                            else:
-                                setattr(self, name, val)
+                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 = [attr["name"] for attr in classinfos["attributes"] if attr["use"] == "required"]
+        if "base" in classinfos:
+            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.items():
+            if attrname in attributes:
+                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 "base" not in classinfos and attrname not in extras:
+                raise ValueError, "Invalid attribute \"%s\" for \"%s\" element!"%(attrname, tree.nodeName)
+            if attrname in required_attributes:
+                required_attributes.remove(attrname)
+        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 name in elements:
+                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 "text" in elements:
+                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 "content" in elements:
+                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(bases, members):
-    def generateXMLTextMethod(self, name, indent, extras = {}, derived = False):
+def generateGenerateXMLText(factory, classinfos):
+    def generateXMLTextMethod(self, name, indent = 0, extras = {}, derived = False):
         ind1, ind2 = getIndent(indent, name)
         if not derived:
             text = ind1 + "<%s"%name
         else:
             text = ""
-        if len(bases) > 0:
-            base_extras = {}
-        if "order" in members.keys():
-            order = members["order"]
-        else:
-            order = []
-        for attr, values in members.items():
-            if attr != "order" and (attr in ("choice_content", "multichoice_content") or values[1] != "attribute"):
-                if attr not in order:
-                    order.append(attr)
-        size = 0
+        
         first = True
-        for attr, value in extras.items():
-            if not first and not self.singleLineAttributes:
-                text += "\n%s"%(ind2)
-            text += " %s=\"%s\""%(attr, ComputeValue(value))
-            first = False
-        for attr, values in members.items():
-            if attr in ["order","choice_content","multichoice_content"]:
-                pass
-            elif attr in ["enum","limit"]:
-                if not derived:
-                    text += ">%s</%s>\n"%(ComputeValue(self.value),name)
-                else:
-                    text += ComputeValue(self.value)
-                return text
-            elif values[1] == "attribute":
-                value = getattr(self, attr, None)
+        if "base" not in classinfos:
+            for attr, value in extras.items():
+                if not first and not self.singleLineAttributes:
+                    text += "\n%s"%(ind2)
+                text += " %s=\"%s\""%(attr, 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:
-                    if values[0].startswith("cls"):
-                        value = value.getValue()
-                    computed_value = ComputeValue(value)
+                    computed_value = attr["attr_type"]["generate"](value)
                 else:
                     computed_value = None
-                if values[2] != "optional" or (value != None and computed_value != values[3]):
-                    if len(bases) > 0:
-                        base_extras[attr] = value
+                if attr["use"] != "optional" or (value != None and computed_value != attr.get("default", attr["attr_type"]["generate"](attr["attr_type"]["initial"]()))):
+                    if "base" in classinfos:
+                        extras[attr["name"]] = computed_value
                     else:
                         if not first and not self.singleLineAttributes:
                             text += "\n%s"%(ind2)
-                        text += " %s=\"%s\""%(attr, computed_value)
+                        text += " %s=\"%s\""%(attr["name"], computed_value)
                     first = False
-        if len(bases) > 0:
-            first, new_text = bases[0].generateXMLText(self, name, indent, base_extras, True)
+        if "base" in classinfos:
+            first, new_text = classinfos["base"].generateXMLText(self, name, indent, extras, True)
             text += new_text
         else:
             first = True
-        ind3, ind4 = getIndent(indent + 1, name)
-        for attr in order:
-            value = getattr(self, attr, None)
-            if attr == "choice_content":
-                if self.content:
+        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 += ">\n"
                         first = False
-                    value_type = members[attr][self.content["name"]]
-                    if value_type.startswith("bse:"):
-                        if value_type.endswith("[]"):
-                            for content in self.content["value"]:
-                                text += ind1 + "<%s>%s</%s>\n"%(self.content["name"], ComputeValue(content), self.content["name"])
-                        else:
-                            text += ind1 + "<%s>%s</%s>\n"%(self.content["name"], ComputeValue(self.content["value"]), self.content["name"])
-                    elif value_type.endswith("[]"):
-                        for content in self.content["value"]:
-                            text += content.generateXMLText(self.content["name"], indent + 1)
-                    elif self.content["value"] is not None:
-                        text += self.content["value"].generateXMLText(self.content["name"], indent + 1)
-                    else:
-                        ind5, ind6 = getIndent(indent + 1, self.content["name"])
-                        text += ind5 + "<%s/>\n"%self.content["name"]
-            elif attr == "multichoice_content":
-                if len(self.content) > 0:
-                    for element in self.content:
-                        if first:
-                            text += ">\n"
-                            first = False
-                        value_type = members[attr][element["name"]]
-                        if value_type.startswith("bse:"):
-                            text += ind1 + "<%s>%s</%s>\n"%(element["name"], ComputeValue(element["value"]), element["name"])
-                        else:
-                            text += element["value"].generateXMLText(element["name"], indent + 1)
-            elif members[attr][2] != "optional" or value != None:
-                if members[attr][0].endswith("[]"):
-                    if first and len(value) > 0:
-                        text += ">\n"
-                        first = False
-                    for element in value:
-                        if members[attr][0].startswith("bse:"):
-                            text += ind3 + "<%s>%s</%s>\n"%(attr, ComputeValue(element), attr)
-                        else:
-                            text += element.generateXMLText(attr, indent + 1)
-                else:
-                    if first:
-                        text += ">\n"
-                        first = False
-                    if members[attr][0].startswith("bse:"):
-                        text += ind3 + "<%s>%s</%s>\n"%(attr, ComputeValue(value), attr)
-                    else:
-                        text += getattr(self, attr).generateXMLText(attr, indent + 1)
+                    text += element["elmt_type"]["generate"](value, element["name"], indent + 1)
+            elif element["minOccurs"] == 1 and element["maxOccurs"] == 1:
+                if first:
+                    text += ">\n"
+                    first = False
+                text += element["elmt_type"]["generate"](value, element["name"], indent + 1)
+            else:
+                if first and len(value) > 0:
+                    text += ">\n"
+                    first = False
+                for item in value:
+                    text += element["elmt_type"]["generate"](item, element["name"], indent + 1)
         if not derived:
             if first:
                 text += "/>\n"
@@ -854,178 +1301,188 @@
             return first, text
     return generateXMLTextMethod
 
-
-def generateGetElementAttributes(members, classes):
+def gettypeinfos(name, facets):
+    if "enumeration" in facets and facets["enumeration"][0] is not None:
+        return facets["enumeration"][0]
+    elif "maxInclusive" in facets:
+        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 = []
-        for attr, values in members.items():
-            if attr in ["order","choice_content","multichoice_content"]:
-                pass
-            elif values[1] == "attribute":
-                attr_params = {"name": attr, "require": values[2] == "required"}
-                if values[0].startswith("cls:"):
-                    attr_value = getattr(self, attr, None)
-                    if attr_value:
-                        attr_params["value"] = attr_value.getValue()
-                    else:
-                        attr_params["value"] = ""
-                    attr_params["type"] = classes[values[0][4:]]().getValidValues()
-                else:
-                    attr_params["value"] = getattr(self, attr, "")
-                    attr_params["type"] = values[0][4:]
+        for attr in classinfos["attributes"]:
+            if attr["use"] != "prohibited":
+                attr_params = {"name" : attr["name"], "require" : attr["use"] == "required", 
+                    "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(members, classes):
+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):
         attr_type = "element"
         value = None
         children = []
-        if "enum" in members:
-            attr_type = self.getValidValues()
-            value = self.value
-        elif "limit" in members:
-            attr_type = {"min" : None, "max" : None}
-            if "min" in members:
-                attr_type["min"] = members["min"]
-            if "max" in members:
-                attr_type["max"] = members["max"]
-            value = self.value
-        elif path:
-            if "choice_content" in members:
-                return self.content["value"].getElementInfos(self.content["name"], path)
-            elif "multichoice_content" not in members:
-                parts = path.split(".", 1)
-                if parts[0] in members:
-                    values = members[parts[0]]
-                    if values[1] == "attribute" and len(parts) == 1:
-                        attr = getattr(self, parts[0], None)
-                        if attr != None:
-                            if values[0].startswith("cls:"):
-                                return attr.getElementInfos(parts[0])
-                            else:
-                                attr_type = values[0][4:]
-                                value = getattr(self, attr, "")
-                    elif values[1] == "element":
-                        attr = getattr(self, parts[0], None)
-                        if attr != None:
-                            if len(parts) == 1:
-                                return attr.getElementInfos(parts[0])
-                            else:
-                                return attr.getElementInfos(parts[0], parts[1])
-        else:
-            for attr, values in members.items():
-                if attr == "order":
-                    pass
-                elif attr == "choice_content":
-                    attr_type = self.getChoices().items()
-                    if self.content:
-                        value = self.content["name"]
-                        children.extend(self.content["value"].getElementInfos(self.content["name"])["children"])
-                elif attr == "multichoice_content":
-                    for element_infos in self.content:
-                        children.append(element_infos["value"].getElementInfos(element_infos["name"]))
-                elif values[1] == "attribute" and not values[0].startswith("cls:"):
-                    children.append({"name" : attr, "value" : getattr(self, attr, ""), "type" : values[0][4:], "children" : []})
-                else:
-                    element = getattr(self, attr, None)
-                    if not element:
-                        element = classes[values[0][4:]]()
-                    children.append(element.getElementInfos(attr))
+        if path is not None:
+            parts = path.split(".", 1)
+            if parts[0] in attributes:
+                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 parts[0] in elements:
+                if element["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)
+                elif len(parts) == 1:
+                    return attr.getElementInfos(parts[0])
+                else:
+                    return attr.getElementInfos(parts[0], parts[1])
+            else:
+                raise ValueError, "Wrong path!"
+        else:
+            children.extend(self.getElementAttributes())
+            for element_name, element in elements.items():
+                if element_name == "content":
+                    attr_type = [(choice["name"], None) for choice in element["choices"]]
+                    value = self.content["name"]
+                    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 = elmt_type["elmt_type"]["initial"]()
+                    children.append(instance.getElementInfos(element_name))
         return {"name" : name, "type" : attr_type, "value" : value, "children" : children}
     return getElementInfos
 
-def generateSetElementValue(members):
+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 "enum" in members or "limit" in members:
-            if not path:
-                self.setValue(value)
-        elif "choice_content" in members:
+        if "content" in elements:
             if path:
                 self.content["value"].setElementValue(path, value)
             else:
-                self.addContent(value)
+                self.addcontentbytype(value)
         else: 
             parts = path.split(".", 1)
-            if parts[0] in members:
-                values = members[parts[0]]
-                if values[1] == "attribute" and len(parts) == 1:
-                    attr = getattr(self, parts[0], None)
-                    if attr != None:
-                        if values[0].startswith("cls:"):
-                            attr.setElementValue(None, value)
-                        elif values[0][4:] == "boolean":
-                            setattr(self, parts[0], value)
+            if parts[0] in attributes:
+                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 parts[0] in elements:
+                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(None, value)
                         else:
-                            setattr(self, parts[0], GetComputedValue(values[0], value))
-                elif values[1] == "element":
-                    attr = getattr(self, parts[0], None)
-                    if attr != None:
-                        if len(parts) == 1:
-                            attr.setElementValue(None, value)
-                        else:
-                            attr.setElementValue(parts[1], value)
+                            instance.setElementValue(parts[1], value)
     return setElementValue
 
 """
 Methods that generates the different methods for setting and getting the attributes
 """
-def generateInitMethod(bases, members):
+def generateInitMethod(factory, classinfos):
     def initMethod(self):
-        for base in bases:
-            base.__init__(self)
-        for attr, initial in members.items():
-            setattr(self, attr, initial())
+        if "base" in classinfos:
+            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 "default" in attribute:
+                    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, attr_type):
+def generateSetMethod(attr):
     def setMethod(self, value):
         setattr(self, attr, value)
     return setMethod
 
-def generateAddChoiceMethod(choice_type, initial_values):
-    def addChoiceMethod(self, name):
-        if name in choice_type:
-            self.content = {"name" : name, "value" : initial_values[name]()}
-    return addChoiceMethod
-
-def generateSetChoiceMethod(choice_type):
-    def setChoiceMethod(self, name, value):
-        self.content = {"name" : name, "value" : value}
-    return setChoiceMethod
-
-def generateGetChoicesMethod(choice_type):
-    def getChoicesMethod(self):
-        return choice_type
-    return getChoicesMethod
-
-def generateSetEnumMethod(enum, attr_type):
-    def setEnumMethod(self, value):
-        if value in enum:
-            self.value = value
-        else:
-            raise ValueError, "%s is not a valid value. Must be in %s"%(value, str(enum))
-    return setEnumMethod
-
-def generateSetLimitMethod(limit, attr_type):
-    def setMethod(self, value):
-        if "min" in limit and value < limit["min"]:
-            raise ValueError, "%s is not a valid value. Must be greater than %d"%(value, limit["min"])
-        elif "max" in limit and value > limit["max"]:
-            raise ValueError, "%s is not a valid value. Must be smaller than %d"%(value, limit["max"])
-        else:
-            self.value = value
-    return setMethod
-
 def generateGetMethod(attr):
     def getMethod(self):
         return getattr(self, attr, None)
     return getMethod
 
-def generateAddMethod(attr, initial):
+def generateAddMethod(attr, factory, infos):
     def addMethod(self):
-        setattr(self, attr, initial())
+        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 "default" in infos:
+            setattr(self, attr, extract(infos["default"], False))
+        else:
+            setattr(self, attr, initial())
     return addMethod
 
 def generateDeleteMethod(attr):
@@ -1033,35 +1490,58 @@
         setattr(self, attr, None)
     return deleteMethod
 
-def generateAppendMethod(attr, attr_type):
+def generateAppendMethod(attr, maxOccurs, factory, infos):
     def appendMethod(self, value):
-        getattr(self, attr).append(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, attr_type):
+def generateInsertMethod(attr, maxOccurs, factory, infos):
     def insertMethod(self, index, value):
-        getattr(self, attr).insert(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 generateAppendChoiceByTypeMethod(choice_type, initial_values):
+def generateGetChoicesMethod(choice_types):
+    def getChoicesMethod(self):
+        return [choice["name"] for choice in choice_types]
+    return getChoicesMethod
+
+def generateAddChoiceByTypeMethod(choice_types):
+    choices = dict([(choice["name"], choice) for choice in choice_types])
     def addChoiceMethod(self, name):
-        if name in choice_type:
-            self.content.append({"name" : name, "value" : initial_values[name]()})
+        if name in choices:
+            if isinstance(choices["name"]["elmt_type"], (UnicodeType, StringType)):
+                namespace, name = DecomposeQualifiedName(infos)
+                choices["name"]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
+            self.content = {"name" : name, "value" : choices["name"]["elmt_type"]["initial"]()}
     return addChoiceMethod
 
-def generateAppendChoiceMethod(choice_types):
-    def appendMethod(self, name, value):
-        self.content.append({"name":name,"value":value})
-    return appendMethod
-
-def generateInsertChoiceMethod(choice_types):
-    def insertMethod(self, index, name, value):
-        self.content.insert(index, {"name":name,"value":value})
-    return insertMethod
-
-def generateRemoveMethod(attr):
+def generateRemoveMethod(attr, minOccurs):
     def removeMethod(self, index):
-        getattr(self, attr).pop(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):
@@ -1073,28 +1553,13 @@
 This function generate the classes from a class factory
 """
 def GenerateClasses(factory, declare = False):
-    ComputedClasses, ComputedTypes = factory.CreateClasses()
+    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, ComputedTypes
-
-"""
-This function opens the xsd file and generate the classes from the xml tree
-"""
-def GenerateClassesFromXSD(filename, declare = False):
-    xsdfile = open(filename, 'r')
-    factory = ClassFactory(minidom.parse(xsdfile))
-    xsdfile.close()
-    return GenerateClasses(factory, declare)
-
-"""
-This function generate the classes from the xsd given as a string
-"""
-def GenerateClassesFromXSDstring(xsdstring, declare = False):
-    factory = ClassFactory(minidom.parseString(xsdstring))
-    return GenerateClasses(factory, declare)
-
+    return ComputedClasses
+