xmlclass modified for allowing class definitions for multiple XSD files and indicating which classes are the base classes
authorlbessard
Thu, 23 Aug 2007 09:23:32 +0200
changeset 76 5bac3213fea1
parent 75 82d371634f15
child 77 346a43f179a5
xmlclass modified for allowing class definitions for multiple XSD files and indicating which classes are the base classes
xmlclass/xmlclass.py
--- a/xmlclass/xmlclass.py	Tue Aug 21 08:55:59 2007 +0200
+++ b/xmlclass/xmlclass.py	Thu Aug 23 09:23:32 2007 +0200
@@ -43,11 +43,6 @@
 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]*)?)')
 
 """
-Dictionaries for stocking Classes and Types created from XML
-"""
-XMLClasses = {}
-
-"""
 This function calculates the number of whitespace for indentation
 """
 def getIndent(indent, balise):
@@ -56,190 +51,6 @@
     return "\t".expandtabs(first), "\t".expandtabs(second)
 
 """
-This function opens the xsd file and generate the classes from the xml tree
-"""
-def GenerateClassesFromXSD(filename):
-    xsdfile = open(filename, 'r')
-    Generate_xsd_classes(minidom.parse(xsdfile), None)
-    xsdfile.close()
-
-"""
-This function generate the classes from the xsd given as a string
-"""
-def GenerateClassesFromXSDstring(xsdstring):
-    Generate_xsd_classes(minidom.parseString(xsdstring), None)
-
-"""
-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 Generate_xsd_classes(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"])
-                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")
-                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
-                    Generate_xsd_classes(node, classname)
-                    nodetype = "cls:%s"%classname
-                if name == "attribute":
-                    if "use" in node._attrs:
-                        use = GetAttributeValue(node._attrs["use"])
-                    else:
-                        use = "optional"
-                if 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)
-                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 = Generate_xsd_classes(node, classname)
-                else:
-                    classname = parent
-                    super, attrs = Generate_xsd_classes(node, classname.split("_")[-1])
-                # When all attributes and inheritances have been extracted, the
-                # values are added in the list of classes to create
-                if classname not in XMLClasses:
-                    XMLClasses[classname] = (super, attrs)
-                elif XMLClasses[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 = Generate_xsd_classes(node, parent)
-                if "ref" in attrs.keys():
-                    choices = attrs
-                else:
-                    choices = {}
-                    for attr, (attr_type, xml_type, write_type) in attrs.items():
-                        choices[attr] = attr_type
-                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 = Generate_xsd_classes(node, parent, True)
-                if "maxOccurs" in node._attrs and GetAttributeValue(node._attrs["maxOccurs"]) == "unbounded":
-                    for attr, (attr_type, xml_type, write_type) in attrs.items():
-                        attrs[attr] = ("%s[]"%attr_type, xml_type, write_type)
-                if "minOccurs" in node._attrs and GetAttributeValue(node._attrs["minOccurs"]) == "0":
-                    for attr, (attr_type, xml_type, write_type) in attrs.items():
-                        attrs[attr] = (attr_type, xml_type, "optional")
-                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 = Generate_xsd_classes(node, None)
-                    XMLClasses[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:
-                #print name
-                Generate_xsd_classes(node, parent)
-            
-            # Parse the childrens of node
-            if recursion:
-                super, attrs = Generate_xsd_classes(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
-"""
 Function that extracts data from a node
 """
 def GetAttributeValue(attr):
@@ -253,32 +64,6 @@
         return text
 
 """
-Funtion that returns the Python type and default value for a given type
-"""
-def GetTypeInitialValue(attr_type):
-    type_compute = attr_type[4:].replace("[]", "")
-    if attr_type.startswith("bse:"):
-        if type_compute == "boolean":
-            return BooleanType, "False"
-        elif type_compute in ["decimal","unsignedLong","long","integer"]:
-            return IntType, "0"
-        elif type_compute in ["string","anyURI","NMTOKEN"]:
-            return StringType, "\"\""
-        elif type_compute == "time":
-            return TimeType, "time(0,0,0,0)"
-        elif type_compute == "date":
-            return DateType, "date(1,1,1)"
-        elif type_compute == "dateTime":
-            return DateTimeType, "datetime(1,1,1,0,0,0,0)"
-        elif type_compute == "language":
-            return StringType, "\"en-US\""
-        else:
-            print "Can't affect: %s"%type_compute
-    elif attr_type.startswith("cls:"):
-        if type_compute in XMLClasses:
-            return XMLClasses[type_compute],"%s()"%type_compute
-
-"""
 Function that computes value from a python type (Only Boolean are critical because
 there is no uppercase in plcopen)
 """
@@ -339,10 +124,395 @@
         return None
 
 """
+Class that generate class from an XML Tree 
+"""
+class ClassFactory:
+
+    def __init__(self, xsd_tree):
+        self.XML_Tree = xsd_tree
+        
+        # Dictionary for stocking Classes and Types definitions created from the XML tree
+        self.XMLClassDefinitions = {}
+        
+        # Dictionaries for stocking Classes and Types generated
+        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"])
+                    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")
+                    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
+                        self.GenerateXSDClasses(node, classname)
+                        nodetype = "cls:%s"%classname
+                    if name == "attribute":
+                        if "use" in node._attrs:
+                            use = GetAttributeValue(node._attrs["use"])
+                        else:
+                            use = "optional"
+                    if 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)
+                    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)
+                    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)
+                    
+                    if "ref" in attrs.keys():
+                        choices = attrs
+                    else:
+                        choices = {}
+                        for attr, (attr_type, xml_type, write_type) in attrs.items():
+                            choices[attr] = attr_type
+                    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) in attrs.items():
+                            attrs[attr] = ("%s[]"%attr_type, xml_type, write_type)
+                    if "minOccurs" in node._attrs and GetAttributeValue(node._attrs["minOccurs"]) == "0":
+                        for attr, (attr_type, xml_type, write_type) in attrs.items():
+                            attrs[attr] = (attr_type, xml_type, "optional")
+                    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):
+        type_compute = attr_type[4:].replace("[]", "")
+        if attr_type.startswith("bse:"):
+            if type_compute == "boolean":
+                return BooleanType, "False"
+            elif type_compute in ["decimal","unsignedLong","long","integer"]:
+                return IntType, "0"
+            elif type_compute in ["string","anyURI","NMTOKEN"]:
+                return StringType, "\"\""
+            elif type_compute == "time":
+                return TimeType, "time(0,0,0,0)"
+            elif type_compute == "date":
+                return DateType, "date(1,1,1)"
+            elif type_compute == "dateTime":
+                return DateTimeType, "datetime(1,1,1,0,0,0,0)"
+            elif type_compute == "language":
+                return StringType, "\"en-US\""
+            else:
+                print "Can't affect: %s"%type_compute
+        elif attr_type.startswith("cls:"):
+            if self.XMLClassDefinitions.get(type_compute, None) != None:
+                return self.XMLClassDefinitions[type_compute],"%s()"%type_compute
+
+    """
+    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 = []
+            
+            # 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"] = "\"%s\""%values[0]
+                        classmembers["value"] = values[0]
+                        classmembers["setValue"] = generateSetEnumMethod(values, value_type)
+                        classmembers["getValue"] = generateGetMethod("value")
+                    
+                    # Class is a limited type
+                    elif attr == "limit":
+                        value_type, initial = self.GetTypeInitialValue(members["basetype"])
+                        initial = 0
+                        if "min" in values:
+                            initial = max(initial, values["min"])
+                        if "max" in values:
+                            initial = min(initial, values["max"])
+                        initialValues["value"] = "%d"%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"] = "None"
+                        classmembers["deleteContent"] = generateDeleteMethod("content")
+                        classmembers["setContent"] = generateSetChoiceMethod(values)
+                        classmembers["getContent"] = generateGetMethod("content")
+                    elif attr == "multichoice_content":
+                        classmembers["content"] = []
+                        initialValues["content"] = "[]"
+                        classmembers["appendContent"] = generateAppendChoiceMethod(values)
+                        classmembers["insertContent"] = generateInsertChoiceMethod(values)
+                        classmembers["removeContent"] = generateRemoveMethod("content")
+                        classmembers["countContent"] = generateCountMethod("content")
+                        classmembers["setContent"] = generateSetMethod("content", ListType)
+                        classmembers["getContent"] = generateGetMethod("content")
+                    
+                    # It's an attribute of the class
+                    else:
+                        attrname = attr[0].upper()+attr[1:]
+                        attr_type, xml_type, write_type = values
+                        value_type, initial = self.GetTypeInitialValue(attr_type)
+                        # Value of the attribute is a list
+                        if attr_type.endswith("[]"):
+                            classmembers[attr] = []
+                            initialValues[attr] = "[]"
+                            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] = "None"
+                                classmembers["add"+attrname] = generateAddMethod(attr, initial, self.ComputedClasses)
+                                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, self.ComputedClasses)
+                classmembers["loadXMLTree"] = generateLoadXMLTree(bases, members, self.ComputedClasses)
+                classmembers["generateXMLText"] = generateGenerateXMLText(bases, members)
+                classmembers["getElementAttributes"] = generategetElementAttributes(bases, members)
+                classmembers["singleLineAttributes"] = True
+                
+                self.ComputedClasses[classname] = classobj(classname, bases, classmembers)
+
+    def MarkUsedClasses(self, classname):
+        # Checks that classe haven't been generated yet
+        if classname in self.XMLClassDefinitions:
+            inheritance, attributes = self.XMLClassDefinitions[classname]
+            
+            # If inheritance classes haven't been generated
+            for base in inheritance:
+                if base in self.ComputedClasses:
+                    self.ComputedClasses[base].IsBaseClass = False
+                
+            # Checks that all attribute types are available 
+            for attribute, type_attribute in attributes.items():
+                if attribute in ["choice_content","multichoice_content"]:
+                    element_types = {}
+                    for attr, value in type_attribute.items():
+                        if attr == "ref":
+                            for ref in value:
+                                element_types.update(self.ComputedTypes[ref[4:]])
+                        else:
+                            element_types[attr] = value
+                    for type_name in element_types.values():
+                        type_compute = type_name[4:].replace("[]","")
+                        if type_compute in self.ComputedClasses:
+                            self.ComputedClasses[type_compute].IsBaseClass = False
+                elif attribute != "group":
+                    if attribute not in ["enum", "limit", "order"]:
+                        if type_attribute[0].startswith("cls:"):
+                            type_compute = type_attribute[0][4:].replace("[]","")
+                            if type_compute in self.ComputedClasses:
+                                self.ComputedClasses[type_compute].IsBaseClass = False
+
+    """
+    Methods that print the classes generated
+    """
+    def PrintClasses(self):
+        for classname, xmlclass in self.ComputedClasses.items():
+            print "%s : %s"%(classname, str(xmlclass))
+        
+    def PrintClassNames(self):
+        classnames = self.XMLClassDefinitions.keys()
+        classnames.sort()
+        for classname in classnames:
+            print classname
+
+"""
 Method that generate the method for loading an xml tree by following the
 attributes list defined
 """
-def generateLoadXMLTree(bases, members, user_classes):
+def generateLoadXMLTree(bases, members, classes):
     def loadXMLTreeMethod(self, tree):
         # If class is derived, values of inheritance classes are loaded
         for base in bases:
@@ -365,7 +535,7 @@
                         if attr_type.startswith("bse:"):
                             val = GetComputedValue(attr_type, attr_value)
                         elif attr_type.startswith("cls:"):
-                            val = eval("%s()"%attr_type[4:], globals().update(user_classes))
+                            val = classes[attr_type[4:]]()
                             val.loadXMLTree(attr)
                         setattr(self, attrname, val)
             
@@ -386,7 +556,7 @@
                             else:
                                 val = None
                         elif attr_type.startswith("cls:"):
-                            val = eval("%s()"%attr_type[4:].replace("[]",""), globals().update(user_classes))
+                            val = classes[attr_type[4:].replace("[]","")]()
                             val.loadXMLTree(node)
                         # Stock value in content attribute
                         if val:
@@ -409,7 +579,7 @@
                             else:
                                 val = None
                         elif attr_type.startswith("cls:"):
-                            val = eval("%s()"%attr_type[4:], globals().update(user_classes))
+                            val = classes[attr_type[4:]]()
                             val.loadXMLTree(node)
                         # Add to content attribute list
                         if val:
@@ -426,7 +596,7 @@
                             else:
                                 val = None
                         elif attr_type.startswith("cls:"):
-                            val = eval("%s()"%attr_type[4:].replace("[]",""), globals().update(user_classes))
+                            val = classes[attr_type[4:].replace("[]","")]()
                             val.loadXMLTree(node)
                         # Stock value in attribute
                         if val:
@@ -575,13 +745,12 @@
 """
 Methods that generates the different methods for setting and getting the attributes
 """
-
-def generateInitMethod(bases, members, user_classes):
+def generateInitMethod(bases, members, classes):
     def initMethod(self):
         for base in bases:
             base.__init__(self)
         for attr, initial in members.items():
-            setattr(self, attr, eval(initial, globals().update(user_classes)))
+            setattr(self, attr, eval(initial, globals().update(classes)))
     return initMethod
 
 def generateSetMethod(attr, attr_type):
@@ -617,9 +786,9 @@
         return getattr(self, attr, None)
     return getMethod
 
-def generateAddMethod(attr, initial, user_classes):
+def generateAddMethod(attr, initial, classes):
     def addMethod(self):
-        setattr(self, attr, eval(initial, globals().update(user_classes)))
+        setattr(self, attr, eval(initial, globals().update(classes)))
     return addMethod
 
 def generateDeleteMethod(attr):
@@ -658,162 +827,31 @@
     return countMethod
 
 """
-This is the Metaclass for PLCOpen element classes. It generates automatically
-the basic useful methods for manipulate the differents attributes of the classes
-"""
-def MetaClass(name, bases, members, user_classes):
-    classmembers = {}
-    initialValues = {}
-    for attr, values in members.items():
-        if attr in ["order", "basetype"]:
-            pass
-        
-        # Class is a enumerated type
-        elif attr == "enum":
-            value_type, initial = GetTypeInitialValue(members["basetype"])
-            initialValues["value"] = "\"%s\""%values[0]
-            classmembers["value"]= values[0]
-            classmembers["setValue"]= generateSetEnumMethod(values, value_type)
-            classmembers["getValue"]= generateGetMethod("value")
-        
-        # Class is a limited type
-        elif attr == "limit":
-            value_type, initial = GetTypeInitialValue(members["basetype"])
-            initial = 0
-            if "min" in values:
-                initial = max(initial, values["min"])
-            if "max" in values:
-                initial = min(initial, values["max"])
-            initialValues["value"] = "%d"%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"] = "None"
-            classmembers["deleteContent"]= generateDeleteMethod("content")
-            classmembers["setContent"]= generateSetChoiceMethod(values)
-            classmembers["getContent"]= generateGetMethod("content")
-        elif attr == "multichoice_content":
-            classmembers["content"]= []
-            initialValues["content"] = "[]"
-            classmembers["appendContent"]= generateAppendChoiceMethod(values)
-            classmembers["insertContent"]= generateInsertChoiceMethod(values)
-            classmembers["removeContent"]= generateRemoveMethod("content")
-            classmembers["countContent"]= generateCountMethod("content")
-            classmembers["setContent"]= generateSetMethod("content", ListType)
-            classmembers["getContent"]= generateGetMethod("content")
-        
-        # It's an attribute of the class
-        else:
-            attrname = attr[0].upper()+attr[1:]
-            attr_type, xml_type, write_type = values
-            value_type, initial = GetTypeInitialValue(attr_type)
-            # Value of the attribute is a list
-            if attr_type.endswith("[]"):
-                classmembers[attr]= []
-                initialValues[attr] = "[]"
-                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] = "None"
-                    classmembers["add"+attrname] = generateAddMethod(attr, initial, user_classes)
-                    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, user_classes)
-    classmembers["loadXMLTree"]= generateLoadXMLTree(bases, members, user_classes)
-    classmembers["generateXMLText"]= generateGenerateXMLText(bases, members)
-    classmembers["getElementAttributes"]= generategetElementAttributes(bases, members)
-    classmembers["singleLineAttributes"]= True
-
-    return classobj(name, bases, classmembers)
-    
-
-
-"""
-Methods that generate the classes
-"""
-def CreateClasses(user_classes, user_types):
-    for classname in XMLClasses.keys():
-        CreateClass(classname, user_classes, user_types)
-
-def CreateClass(classname, user_classes, user_types):
-    # Checks that classe haven't been generated yet
-    if classname not in user_classes and classname not in user_types and classname in XMLClasses:
-        inheritance, attributes = XMLClasses[classname]
-        #print classe, inheritance, attributes
-        members = {}
-        bases = []
-        
-        # If inheritance classes haven't been generated
-        for base in inheritance:
-            if base not in user_classes:
-                CreateClass(base, user_classes, user_types)
-            bases.append(user_classes[base])
-        
-        # Checks that all attribute types are available 
-        for attribute, type_attribute in attributes.items():
-            if attribute == "group":
-                user_types[classname] = type_attribute
-            elif attribute == "ref":
-                user_types[classname] = {}
-                for attr in type_attribute:
-                    if attr[4:] not in user_types:
-                        CreateClass(attr[4:], user_classes, user_types)
-                    user_types[classname].update(user_types[attr[4:]])
-            elif attribute in ["choice_content","multichoice_content"]:
-                element_types = {}
-                for attr, value in type_attribute.items():
-                    if attr == "ref":
-                        for ref in value:
-                            if ref[4:] not in user_types:
-                                CreateClass(ref[4:], user_classes, user_types)
-                            element_types.update(user_types[ref[4:]])
-                    else:
-                        element_types[attr] = value
-                members[attribute] = element_types
-            else:
-                members[attribute] = type_attribute
-                if attribute == "enum":
-                    user_types["%s_enum"%classname] = type_attribute
-                elif attribute not in ["limit", "order"]:
-                    if type_attribute[0].startswith("ppx:"):
-                        type_compute = type_attribute[0][4:].replace("[]","")
-                        if type_compute not in user_classes:
-                            CreateClass(type_compute, user_classes, user_types)
-        if "group" not in attributes.keys() and "ref" not in attributes.keys():
-            cls = MetaClass(classname, tuple(bases), members, user_classes)
-            user_classes[classname] = cls
-
-"""
-Methods that print the classes generated
-"""
-def PrintClasses():
-    for classname, xmlclass in XMLClasses.items():
-        print "%s : %s\n"%(classname, str(xmlclass))
-    
-def PrintClassNames():
-    classnames = XMLClasses.keys()
-    classnames.sort()
-    for classname in classnames:
-        print classname
-
-def DeclareXSDClass(XSDstring):
-    pluginClasses = {}
-    pluginTypes = {}
-    GenerateClassesFromXSDstring(XSDstring)
-    CreateClasses(pluginClasses, pluginTypes)
-    
-    for ClassName, Class in pluginClasses.items():
-        sys._getframe(1).f_locals[ClassName] = Class
+This function generate the classes from a class factory
+"""
+def GenerateClasses(factory, declare = False):
+    ComputedClasses, ComputedTypes = factory.CreateClasses()
+    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
+    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)
+
+