Changed the way class are generated, using classobj from "new" module, instead of type inheritence.
authoretisserant
Tue, 21 Aug 2007 08:55:59 +0200
changeset 75 82d371634f15
parent 74 a33f06a63e1d
child 76 5bac3213fea1
Changed the way class are generated, using classobj from "new" module, instead of type inheritence.
xmlclass/xmlclass.py
--- a/xmlclass/xmlclass.py	Tue Aug 21 08:55:06 2007 +0200
+++ b/xmlclass/xmlclass.py	Tue Aug 21 08:55:59 2007 +0200
@@ -26,6 +26,7 @@
 import sys,re
 from types import *
 from datetime import *
+from new import classobj
 
 """
 Time and date definitions
@@ -63,6 +64,12 @@
     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
 """
@@ -332,386 +339,407 @@
         return None
 
 """
-This is the Metaclass for PLCOpen element classes. It generates automatically
-the basic useful methods for manipulate the differents attributes of the classes
-"""
-class MetaClass(type):
-    
-    def __init__(cls, name, bases, dict, user_classes):
-        super(MetaClass, cls).__init__(name, bases, {})
-        #print name, bases, dict, "\n"
-        initialValues = {}
-        for attr, values in dict.items():
-            if attr in ["order", "basetype"]:
+Method that generate the method for loading an xml tree by following the
+attributes list defined
+"""
+def generateLoadXMLTree(bases, members, user_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 = 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 = eval("%s()"%attr_type[4:], globals().update(user_classes))
+                            val.loadXMLTree(attr)
+                        setattr(self, attrname, val)
+            
+            # Load the node childs if they are defined in the list
+            for node in tree.childNodes:
+                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:"):
+                            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 = eval("%s()"%attr_type[4:].replace("[]",""), globals().update(user_classes))
+                            val.loadXMLTree(node)
+                        # Stock value in content attribute
+                        if val:
+                            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}
+                    
+                    # 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:"):
+                            attr_value = GetAttributeValue(node)
+                            if write_type != "optional" or attr_value != "":
+                                val = GetComputedValue(attr_type, attr_value)
+                            else:
+                                val = None
+                        elif attr_type.startswith("cls:"):
+                            val = eval("%s()"%attr_type[4:], globals().update(user_classes))
+                            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 = 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 = eval("%s()"%attr_type[4:].replace("[]",""), globals().update(user_classes))
+                            val.loadXMLTree(node)
+                        # Stock value in attribute
+                        if val:
+                            if attr_type.endswith("[]"):
+                                getattr(self, name).append(val)
+                            else:
+                                setattr(self, name, val)
+    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):
+        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 = []
+        if "choice_content" in members.keys() and "choice_content" not in order:
+            order.append("choice_content") 
+        if "multichoice_content" in members.keys() and "multichoice_content" not in order:
+            order.append("multichoice_content") 
+        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
-            
-            # Class is a enumerated type
-            elif attr == "enum":
-                value_type, initial = GetTypeInitialValue(dict["basetype"])
-                initialValues["value"] = "\"%s\""%values[0]
-                setattr(cls, "value", values[0])
-                setattr(cls, "setValue", MetaClass.generateSetEnumMethod(cls, values, value_type))
-                setattr(cls, "getValue", MetaClass.generateGetMethod(cls, "value"))
-            
-            # Class is a limited type
-            elif attr == "limit":
-                value_type, initial = GetTypeInitialValue(dict["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
-                setattr(cls, "value", initial)
-                setattr(cls, "setValue", MetaClass.generateSetLimitMethod(cls, values, value_type))
-                setattr(cls, "getValue", MetaClass.generateGetMethod(cls, "value"))
-            
-            # Class has an attribute that can have different value types
-            elif attr == "choice_content":
-                setattr(cls, "content", None)
-                initialValues["content"] = "None"
-                setattr(cls, "deleteContent", MetaClass.generateDeleteMethod(cls, "content"))
-                setattr(cls, "setContent", MetaClass.generateSetChoiceMethod(cls, values))
-                setattr(cls, "getContent", MetaClass.generateGetMethod(cls, "content"))
+            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 value == "":
+                    value = None
+                if values[2] != "optional" or value != None:
+                    if not first and not self.singleLineAttributes:
+                        text += "\n%s"%(ind2)
+                    if values[0].startswith("cls"):
+                        if len(bases) > 0:
+                            base_extras[attr] = value.getValue()
+                        else:
+                            text += " %s=\"%s\""%(attr, ComputeValue(value.getValue()))
+                    else:
+                        if len(bases) > 0:
+                            base_extras[attr] = value
+                        else:
+                            text += " %s=\"%s\""%(attr, ComputeValue(value))
+                    first = False
+        if len(bases) > 0:
+            first, new_text = bases[0].generateXMLText(self, name, indent, base_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:
+                    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)
+                    else:
+                        text += self.content["value"].generateXMLText(self.content["name"], indent + 1)
             elif attr == "multichoice_content":
-                setattr(cls, "content", [])
-                initialValues["content"] = "[]"
-                setattr(cls, "appendContent", MetaClass.generateAppendChoiceMethod(cls, values))
-                setattr(cls, "insertContent", MetaClass.generateInsertChoiceMethod(cls, values))
-                setattr(cls, "removeContent", MetaClass.generateRemoveMethod(cls, "content"))
-                setattr(cls, "countContent", MetaClass.generateCountMethod(cls, "content"))
-                setattr(cls, "setContent", MetaClass.generateSetMethod(cls, "content", ListType))
-                setattr(cls, "getContent", MetaClass.generateGetMethod(cls, "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("[]"):
-                    setattr(cls, attr, [])
-                    initialValues[attr] = "[]"
-                    setattr(cls, "append"+attrname, MetaClass.generateAppendMethod(cls, attr, value_type))
-                    setattr(cls, "insert"+attrname, MetaClass.generateInsertMethod(cls, attr, value_type))
-                    setattr(cls, "remove"+attrname, MetaClass.generateRemoveMethod(cls, attr))
-                    setattr(cls, "count"+attrname, MetaClass.generateCountMethod(cls, attr))
-                    setattr(cls, "set"+attrname, MetaClass.generateSetMethod(cls, attr, ListType))
-                else:
-                    if write_type == "optional":
-                        setattr(cls, attr, None)
-                        initialValues[attr] = "None"
-                        setattr(cls, "add"+attrname, MetaClass.generateAddMethod(cls, attr, initial, user_classes))
-                        setattr(cls, "delete"+attrname, MetaClass.generateDeleteMethod(cls, attr))
-                    else:
-                        setattr(cls, attr, initial)
-                        initialValues[attr] = initial
-                    setattr(cls, "set"+attrname, MetaClass.generateSetMethod(cls, attr, value_type))
-                setattr(cls, "get"+attrname, MetaClass.generateGetMethod(cls, attr))
-        setattr(cls, "__init__", MetaClass.generateInitMethod(cls, bases, initialValues, user_classes))
-        setattr(cls, "loadXMLTree", MetaClass.generateLoadXMLTree(cls, bases, dict, user_classes))
-        setattr(cls, "generateXMLText", MetaClass.generateGenerateXMLText(cls, bases, dict))
-        setattr(cls, "singleLineAttributes", True)
-
-    """
-    Method that generate the method for loading an xml tree by following the
-    attributes list defined
-    """
-    def generateLoadXMLTree(cls, bases, dict, user_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 dict.keys() or "limit" in dict.keys():
-                attr_value = GetAttributeValue(tree)
-                attr_type = dict["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 dict.keys():
-                        attr_type, xml_type, write_type = dict[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 = eval("%s()"%attr_type[4:], globals().update(user_classes))
-                                val.loadXMLTree(attr)
-                            setattr(self, attrname, val)
-                
-                # Load the node childs if they are defined in the list
-                for node in tree.childNodes:
-                    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 dict.keys() and name in dict["choice_content"].keys():
-                            attr_type = dict["choice_content"][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 = eval("%s()"%attr_type[4:].replace("[]",""), globals().update(user_classes))
-                                val.loadXMLTree(node)
-                            # Stock value in content attribute
-                            if val:
-                                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}
-                        
-                        # Class has a list of attributes that can have different value types
-                        elif "multichoice_content" in dict.keys() and name in dict["multichoice_content"].keys():
-                            attr_type = dict["multichoice_content"][name]
-                            # Extracts the value
-                            if attr_type.startswith("bse:"):
-                                attr_value = GetAttributeValue(node)
-                                if write_type != "optional" or attr_value != "":
-                                    val = GetComputedValue(attr_type, attr_value)
-                                else:
-                                    val = None
-                            elif attr_type.startswith("cls:"):
-                                val = eval("%s()"%attr_type[4:], globals().update(user_classes))
-                                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 dict.keys():
-                            attr_type, xml_type, write_type = dict[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 = eval("%s()"%attr_type[4:].replace("[]",""), globals().update(user_classes))
-                                val.loadXMLTree(node)
-                            # Stock value in attribute
-                            if val:
-                                if attr_type.endswith("[]"):
-                                    getattr(self, name).append(val)
-                                else:
-                                    setattr(self, name, val)
-        return loadXMLTreeMethod
-
-    """
-    Method that generates the method for generating an xml text by following the
-    attributes list defined
-    """
-    def generateGenerateXMLText(cls, bases, dict):
-        def generateXMLTextMethod(self, name, indent, 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 dict.keys():
-                order = dict["order"]
-            else:
-                order = []
-            if "choice_content" in dict.keys() and "choice_content" not in order:
-                order.append("choice_content") 
-            if "multichoice_content" in dict.keys() and "multichoice_content" not in order:
-                order.append("multichoice_content") 
-            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 dict.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 values[2] != "optional" or value != None:
-                        if not first and not self.singleLineAttributes:
-                            text += "\n%s"%(ind2)
-                        if values[0].startswith("cls"):
-                            if len(bases) > 0:
-                                base_extras[attr] = value.getValue()
-                            else:
-                                text += " %s=\"%s\""%(attr, ComputeValue(value.getValue()))
-                        else:
-                            if len(bases) > 0:
-                                base_extras[attr] = value
-                            else:
-                                text += " %s=\"%s\""%(attr, ComputeValue(value))
-                        first = False
-            if len(bases) > 0:
-                first, new_text = bases[0].generateXMLText(self, name, indent, base_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:
+                if len(self.content) > 0:
+                    for element in self.content:
                         if first:
                             text += ">\n"
                             first = False
-                        value_type = dict[attr][self.content["name"]]
+                        value_type = members[attr][element["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)
+                            text += ind1 + "<%s>%s</%s>\n"%(element["name"], ComputeValue(element["value"]), element["name"])
                         else:
-                            text += self.content["value"].generateXMLText(self.content["name"], indent + 1)
-                elif attr == "multichoice_content":
-                    if len(self.content) > 0:
-                        for element in self.content:
-                            if first:
-                                text += ">\n"
-                                first = False
-                            value_type = dict[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 dict[attr][2] != "optional" or value != None:
-                    if dict[attr][0].endswith("[]"):
-                        if first and len(value) > 0:
-                            text += ">\n"
-                            first = False
-                        for element in value:
-                            if dict[attr][0].startswith("bse:"):
-                                text += ind3 + "<%s>%s</%s>\n"%(attr, ComputeValue(element), attr)
-                            else:
-                                text += element.generateXMLText(attr, indent + 1)
+                            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:
-                        if first:
-                            text += ">\n"
-                            first = False
-                        if dict[attr][0].startswith("bse:"):
-                            text += ind3 + "<%s>%s</%s>\n"%(attr, ComputeValue(value), attr)
-                        else:
-                            text += getattr(self, attr).generateXMLText(attr, indent + 1)
-            if not derived:
-                if first:
-                    text += "/>\n"
+                        text += getattr(self, attr).generateXMLText(attr, indent + 1)
+        if not derived:
+            if first:
+                text += "/>\n"
+            else:
+                text += ind1 + "</%s>\n"%(name)
+            return text
+        else:
+            return first, text
+    return generateXMLTextMethod
+
+
+def generategetElementAttributes(bases, members):
+    def getElementAttributes(self):
+        attr_list = []
+        for attr, values in members.items():
+            if attr in ["order","choice_content","multichoice_content"]:
+                pass
+            elif values[1] == "attribute":
+                if values[2] == "required":
+                    require = True
                 else:
-                    text += ind1 + "</%s>\n"%(name)
-                return text
+                    require = False
+                attr_hash ={"name": attr,"type": values[0] ,"value": getattr(self, attr, "") ,"require": require}
+                attr_list.append(attr_hash)
+        return attr_list
+    return getElementAttributes
+    
+"""
+Methods that generates the different methods for setting and getting the attributes
+"""
+
+def generateInitMethod(bases, members, user_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)))
+    return initMethod
+
+def generateSetMethod(attr, attr_type):
+    def setMethod(self, value):
+        setattr(self, attr, value)
+    return setMethod
+
+def generateSetChoiceMethod(choice_type):
+    def setChoiceMethod(self, name, value):
+        self.content = {"name":name,"value":value}
+    return setChoiceMethod
+
+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, user_classes):
+    def addMethod(self):
+        setattr(self, attr, eval(initial, globals().update(user_classes)))
+    return addMethod
+
+def generateDeleteMethod(attr):
+    def deleteMethod(self):
+        setattr(self, attr, None)
+    return deleteMethod
+
+def generateAppendMethod(attr, attr_type):
+    def appendMethod(self, value):
+        getattr(self, attr).append(value)
+    return appendMethod
+
+def generateInsertMethod(attr, attr_type):
+    def insertMethod(self, index, value):
+        getattr(self, attr).insert(index, value)
+    return insertMethod
+
+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 removeMethod(self, index):
+        getattr(self, attr).pop(index)
+    return removeMethod
+
+def generateCountMethod(attr):
+    def countMethod(self):
+        return len(getattr(self, attr))
+    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:
-                return first, text
-        return generateXMLTextMethod
-        
-    """
-    Methods that generates the different methods for setting and getting the attributes
-    """
+                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)
     
-    def generateInitMethod(cls, bases, dict, user_classes):
-        def initMethod(self):
-            for base in bases:
-                base.__init__(self)
-            for attr, initial in dict.items():
-                setattr(self, attr, eval(initial, globals().update(user_classes)))
-        return initMethod
-
-    def generateSetMethod(cls, attr, choice_type):
-        def setMethod(self, value):
-            setattr(self, attr, value)
-        return setMethod
-
-    def generateSetChoiceMethod(cls, attr_type):
-        def setChoiceMethod(self, name, value):
-            self.content = {"name":name,"value":value}
-        return setChoiceMethod
-
-    def generateSetEnumMethod(cls, 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(cls, 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(cls, attr):
-        def getMethod(self):
-            return getattr(self, attr, None)
-        return getMethod
-
-    def generateAddMethod(cls, attr, initial, user_classes):
-        def addMethod(self):
-            setattr(self, attr, eval(initial, globals().update(user_classes)))
-        return addMethod
-
-    def generateDeleteMethod(cls, attr):
-        def deleteMethod(self):
-            setattr(self, attr, None)
-        return deleteMethod
-
-    def generateAppendMethod(cls, attr, attr_type):
-        def appendMethod(self, value):
-            getattr(self, attr).append(value)
-        return appendMethod
-
-    def generateInsertMethod(cls, attr, attr_type):
-        def insertMethod(self, index, value):
-            getattr(self, attr).insert(index, value)
-        return insertMethod
-
-    def generateAppendChoiceMethod(cls, choice_types):
-        def appendMethod(self, name, value):
-            self.content.append({"name":name,"value":value})
-        return appendMethod
-
-    def generateInsertChoiceMethod(cls, choice_types):
-        def insertMethod(self, index, name, value):
-            self.content.insert(index, {"name":name,"value":value})
-        return insertMethod
-
-    def generateRemoveMethod(cls, attr):
-        def removeMethod(self, index):
-            getattr(self, attr).pop(index)
-        return removeMethod
-
-    def generateCountMethod(cls, attr):
-        def countMethod(self):
-            return len(getattr(self, attr))
-        return countMethod
+
 
 """
 Methods that generate the classes
@@ -725,7 +753,7 @@
     if classname not in user_classes and classname not in user_types and classname in XMLClasses:
         inheritance, attributes = XMLClasses[classname]
         #print classe, inheritance, attributes
-        dict = {}
+        members = {}
         bases = []
         
         # If inheritance classes haven't been generated
@@ -748,15 +776,15 @@
                 element_types = {}
                 for attr, value in type_attribute.items():
                     if attr == "ref":
-                        for ref in type_attribute["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
-                dict[attribute] = element_types
+                members[attribute] = element_types
             else:
-                dict[attribute] = type_attribute
+                members[attribute] = type_attribute
                 if attribute == "enum":
                     user_types["%s_enum"%classname] = type_attribute
                 elif attribute not in ["limit", "order"]:
@@ -765,8 +793,7 @@
                         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.__new__(MetaClass, classname, tuple(bases), dict)
-            MetaClass.__init__(cls, classname, tuple(bases), dict, user_classes)
+            cls = MetaClass(classname, tuple(bases), members, user_classes)
             user_classes[classname] = cls
 
 """
@@ -781,3 +808,12 @@
     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