diff -r 82d371634f15 -r 5bac3213fea1 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) + +