lbessard@2: #!/usr/bin/env python lbessard@2: # -*- coding: utf-8 -*- lbessard@2: lbessard@2: #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor lbessard@2: #based on the plcopen standard. lbessard@2: # lbessard@58: #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD lbessard@2: # lbessard@2: #See COPYING file for copyrights details. lbessard@2: # lbessard@2: #This library is free software; you can redistribute it and/or lbessard@2: #modify it under the terms of the GNU General Public lbessard@2: #License as published by the Free Software Foundation; either lbessard@2: #version 2.1 of the License, or (at your option) any later version. lbessard@2: # lbessard@2: #This library is distributed in the hope that it will be useful, lbessard@2: #but WITHOUT ANY WARRANTY; without even the implied warranty of lbessard@2: #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU lbessard@58: #General Public License for more details. lbessard@2: # lbessard@2: #You should have received a copy of the GNU General Public lbessard@2: #License along with this library; if not, write to the Free Software lbessard@2: #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA lbessard@2: lbessard@2: from xml.dom import minidom lbessard@2: import sys,re lbessard@2: from types import * lbessard@2: from datetime import * etisserant@75: from new import classobj lbessard@2: lbessard@2: """ lbessard@2: Regular expression models for extracting dates and times from a string lbessard@2: """ lbessard@24: time_model = re.compile('([0-9]{2}):([0-9]{2}):([0-9]{2}(?:.[0-9]*)?)') lbessard@2: date_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})') lbessard@24: 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]*)?)') lbessard@2: lbessard@90: XSD_INTEGER_TYPES = ["integer","nonPositiveInteger","negativeInteger","long", lbessard@90: "int","short","byte","nonNegativeInteger","unsignedLong","unsignedInt", lbessard@90: "unsignedShort","unsignedByte","positiveInteger"] lbessard@90: lbessard@90: XSD_STRING_TYPES = ["string","normalizedString","token","anyURI","NMTOKEN","language"] lbessard@90: lbessard@2: """ lbessard@2: This function calculates the number of whitespace for indentation lbessard@2: """ lbessard@2: def getIndent(indent, balise): lbessard@2: first = indent * 2 lbessard@2: second = first + len(balise) + 1 lbessard@2: return "\t".expandtabs(first), "\t".expandtabs(second) lbessard@2: lbessard@2: """ lbessard@2: Function that extracts data from a node lbessard@2: """ lbessard@2: def GetAttributeValue(attr): lbessard@2: if len(attr.childNodes) == 1: lbessard@2: return attr.childNodes[0].data.encode() lbessard@2: else: lbessard@67: text = "" lbessard@67: for node in attr.childNodes: lbessard@67: if node.nodeName != "#text": lbessard@67: text += node.data.encode() lbessard@67: return text lbessard@2: lbessard@2: """ lbessard@2: Function that computes value from a python type (Only Boolean are critical because lbessard@2: there is no uppercase in plcopen) lbessard@2: """ lbessard@2: def ComputeValue(value): lbessard@2: if type(value) == BooleanType: lbessard@2: if value: lbessard@2: return "true" lbessard@2: else: lbessard@2: return "false" lbessard@2: else: lbessard@2: return str(value) lbessard@2: lbessard@2: """ lbessard@2: Function that extracts a value from a string following the xsd type given lbessard@2: """ lbessard@2: def GetComputedValue(attr_type, value): lbessard@2: type_compute = attr_type[4:].replace("[]", "") lbessard@2: if type_compute == "boolean": lbessard@2: if value == "true": lbessard@2: return True lbessard@2: elif value == "false": lbessard@2: return False lbessard@2: else: lbessard@2: raise ValueError, "\"%s\" is not a valid boolean!"%value lbessard@90: elif type_compute in XSD_INTEGER_TYPES: lbessard@2: return int(value) lbessard@90: elif type_compute in ["decimal", "float", "double"]: lbessard@86: computed_value = float(value) lbessard@86: if computed_value % 1 == 0: lbessard@86: return int(computed_value) lbessard@86: return computed_value lbessard@90: elif type_compute in XSD_STRING_TYPES: lbessard@2: return value lbessard@2: elif type_compute == "time": lbessard@2: result = time_model.match(value) lbessard@2: if result: lbessard@24: values = result.groups() lbessard@24: time_values = [int(v) for v in values[:2]] lbessard@24: seconds = float(values[2]) lbessard@24: time_values.extend([int(seconds), int((seconds % 1) * 1000000)]) lbessard@2: return time(*time_values) lbessard@2: else: lbessard@2: raise ValueError, "\"%s\" is not a valid time!"%value lbessard@2: elif type_compute == "date": lbessard@2: result = date_model.match(value) lbessard@2: if result: lbessard@2: date_values = [int(v) for v in result.groups()] lbessard@2: return date(*date_values) lbessard@2: else: lbessard@2: raise ValueError, "\"%s\" is not a valid date!"%value lbessard@2: elif type_compute == "dateTime": lbessard@2: result = datetime_model.match(value) lbessard@2: if result: lbessard@24: values = result.groups() lbessard@24: datetime_values = [int(v) for v in values[:5]] lbessard@24: seconds = float(values[5]) lbessard@24: datetime_values.extend([int(seconds), int((seconds % 1) * 1000000)]) lbessard@2: return datetime(*datetime_values) lbessard@2: else: lbessard@2: raise ValueError, "\"%s\" is not a valid datetime!"%value lbessard@2: else: lbessard@2: print "Can't affect: %s"%type_compute lbessard@2: return None lbessard@2: lbessard@83: def GetInitialValueFunction(value): lbessard@83: def GetInitialValue(): lbessard@83: return value lbessard@83: return GetInitialValue lbessard@83: lbessard@2: """ lbessard@76: Class that generate class from an XML Tree lbessard@76: """ lbessard@76: class ClassFactory: lbessard@76: lbessard@76: def __init__(self, xsd_tree): lbessard@76: self.XML_Tree = xsd_tree lbessard@76: lbessard@76: # Dictionary for stocking Classes and Types definitions created from the XML tree lbessard@76: self.XMLClassDefinitions = {} lbessard@76: lbessard@76: # Dictionaries for stocking Classes and Types generated lbessard@76: self.ComputedClasses = {} lbessard@76: self.ComputedTypes = {} lbessard@76: self.AlreadyComputed = {} lbessard@76: lbessard@76: """ lbessard@76: This function recursively creates a definition of the classes and their attributes lbessard@76: for plcopen from the xsd file of plcopen opened in a DOM model lbessard@76: """ lbessard@76: def GenerateXSDClasses(self, tree, parent, sequence = False): lbessard@76: attributes = {} lbessard@76: inheritance = [] lbessard@76: if sequence: lbessard@76: order = [] lbessard@76: # The lists of attributes and inheritance of the node are generated from the childrens lbessard@76: for node in tree.childNodes: lbessard@76: # We make fun of #text elements and all other tags that don't are xsd tags lbessard@76: if node.nodeName != "#text" and node.nodeName.startswith("xsd:"): lbessard@76: recursion = False lbessard@76: name = node.nodeName[4:].encode() lbessard@76: lbessard@76: # This tags defines an attribute of the class lbessard@76: if name in ["element", "attribute"]: lbessard@76: nodename = GetAttributeValue(node._attrs["name"]) lbessard@83: default = None lbessard@76: if "type" in node._attrs: lbessard@76: nodetype = GetAttributeValue(node._attrs["type"]) lbessard@76: if nodetype.startswith("xsd"): lbessard@76: nodetype = nodetype.replace("xsd", "bse") lbessard@76: elif nodetype.startswith("ppx"): lbessard@76: nodetype = nodetype.replace("ppx", "cls") lbessard@76: else: lbessard@76: # The type of attribute is defines in the child tree so we generate a new class lbessard@76: # No name is defined so we create one from nodename and parent class name lbessard@76: # (because some different nodes can have the same name) lbessard@76: if parent: lbessard@76: classname = "%s_%s"%(parent, nodename) lbessard@76: else: lbessard@76: classname = nodename lbessard@76: self.GenerateXSDClasses(node, classname) lbessard@76: nodetype = "cls:%s"%classname lbessard@76: if name == "attribute": lbessard@76: if "use" in node._attrs: lbessard@76: use = GetAttributeValue(node._attrs["use"]) lbessard@76: else: lbessard@76: use = "optional" lbessard@83: if "default" in node._attrs: lbessard@83: default = GetAttributeValue(node._attrs["default"]) lbessard@83: elif name == "element": lbessard@76: # If a tag can be written more than one time we define a list attribute lbessard@76: if "maxOccurs" in node._attrs and GetAttributeValue(node._attrs["maxOccurs"]) == "unbounded": lbessard@76: nodetype = "%s[]"%nodetype lbessard@76: if "minOccurs" in node._attrs and GetAttributeValue(node._attrs["minOccurs"]) == "0": lbessard@76: use = "optional" lbessard@76: else: lbessard@76: use = "required" lbessard@83: attributes[nodename] = (nodetype, name, use, default) lbessard@76: if sequence: lbessard@76: order.append(nodename) lbessard@76: lbessard@76: # This tag defines a new class lbessard@76: elif name == "complexType" or name == "simpleType": lbessard@76: if "name" in node._attrs: lbessard@76: classname = GetAttributeValue(node._attrs["name"]) lbessard@76: super, attrs = self.GenerateXSDClasses(node, classname) lbessard@76: else: lbessard@76: classname = parent lbessard@76: super, attrs = self.GenerateXSDClasses(node, classname.split("_")[-1]) lbessard@76: # When all attributes and inheritances have been extracted, the lbessard@76: # values are added in the list of classes to create lbessard@76: if self.XMLClassDefinitions.get(classname, None) == None: lbessard@76: self.XMLClassDefinitions[classname] = (super, attrs) lbessard@76: elif self.XMLClassDefinitions[classname] != (super, attrs): lbessard@76: print "A different class has already got %s for name"%classname lbessard@76: lbessard@76: # This tag defines an attribute that can have different types lbessard@76: elif name == "choice": lbessard@76: super, attrs = self.GenerateXSDClasses(node, parent) lbessard@76: jon@84: choices = {} jon@84: for attr, values in attrs.items(): jon@84: if attr == "ref": jon@84: choices[attr] = values jon@84: else: jon@84: choices[attr] = values[0] lbessard@76: if "maxOccurs" in node._attrs and GetAttributeValue(node._attrs["maxOccurs"]) == "unbounded": lbessard@76: attributes["multichoice_content"] = choices lbessard@76: if sequence: lbessard@76: order.append("multichoice_content") lbessard@76: else: lbessard@76: attributes["choice_content"] = choices lbessard@76: if sequence: lbessard@76: order.append("choice_content") lbessard@76: lbessard@76: # This tag defines the order in which class attributes must be written lbessard@76: # in plcopen xml file. We have to store this order like an attribute lbessard@76: elif name in "sequence": lbessard@76: super, attrs, order = self.GenerateXSDClasses(node, parent, True) lbessard@76: if "maxOccurs" in node._attrs and GetAttributeValue(node._attrs["maxOccurs"]) == "unbounded": lbessard@83: for attr, (attr_type, xml_type, write_type, default) in attrs.items(): lbessard@83: attrs[attr] = ("%s[]"%attr_type, xml_type, write_type, default) lbessard@76: if "minOccurs" in node._attrs and GetAttributeValue(node._attrs["minOccurs"]) == "0": lbessard@83: for attr, (attr_type, xml_type, write_type, default) in attrs.items(): lbessard@83: attrs[attr] = (attr_type, xml_type, "optional", default) lbessard@76: inheritance.extend(super) lbessard@76: attributes.update(attrs) lbessard@76: attributes["order"] = order lbessard@76: lbessard@76: # This tag defines of types lbessard@76: elif name == "group": lbessard@76: if "name" in node._attrs: lbessard@76: nodename = GetAttributeValue(node._attrs["name"]) lbessard@76: super, attrs = self.GenerateXSDClasses(node, None) lbessard@76: self.XMLClassDefinitions[nodename] = (super, {"group":attrs["choice_content"]}) lbessard@76: elif "ref" in node._attrs: lbessard@76: if "ref" not in attributes: lbessard@76: attributes["ref"] = [GetAttributeValue(node._attrs["ref"])] lbessard@76: else: lbessard@76: attributes["ref"].append(GetAttributeValue(node._attrs["ref"])) lbessard@76: lbessard@76: # This tag define a base class for the node lbessard@76: elif name == "extension": lbessard@76: super = GetAttributeValue(node._attrs["base"]) lbessard@76: if super.startswith("xsd"): lbessard@76: super = super.replace("xsd", "bse") lbessard@76: elif super.startswith("ppx"): lbessard@76: super = super.replace("ppx", "cls") lbessard@76: inheritance.append(super[4:]) lbessard@76: recursion = True lbessard@76: lbessard@76: # This tag defines a restriction on the type of attribute lbessard@76: elif name == "restriction": lbessard@76: basetype = GetAttributeValue(node._attrs["base"]) lbessard@76: if basetype.startswith("xsd"): lbessard@76: basetype = basetype.replace("xsd", "bse") lbessard@76: elif basetype.startswith("ppx"): lbessard@76: basetype = basetype.replace("ppx", "cls") lbessard@76: attributes["basetype"] = basetype lbessard@76: recursion = True lbessard@76: lbessard@76: # This tag defines an enumerated type lbessard@76: elif name == "enumeration": lbessard@76: if "enum" not in attributes: lbessard@76: attributes["enum"] = [GetAttributeValue(node._attrs["value"])] lbessard@76: else: lbessard@76: attributes["enum"].append(GetAttributeValue(node._attrs["value"])) lbessard@76: lbessard@76: # This tags defines a restriction on a numerical value lbessard@76: elif name in ["minInclusive","maxInclusive"]: lbessard@76: if "limit" not in attributes: lbessard@76: attributes["limit"] = {} lbessard@76: if name == "minInclusive": lbessard@76: attributes["limit"]["min"] = eval(GetAttributeValue(node._attrs["value"])) lbessard@76: elif name == "maxInclusive": lbessard@76: attributes["limit"]["max"] = eval(GetAttributeValue(node._attrs["value"])) lbessard@76: lbessard@76: # This tag are not important but their childrens are. The childrens are then parsed. lbessard@76: elif name in ["complexContent", "schema"]: lbessard@76: recursion = True lbessard@76: lbessard@76: # We make fun of xsd documentation lbessard@76: elif name in ["annotation"]: lbessard@76: pass lbessard@76: lbessard@76: else: lbessard@76: # Unable this line to print XSD element that is not yet supported lbessard@76: #print name lbessard@76: self.GenerateXSDClasses(node, parent) lbessard@76: lbessard@76: # Parse the childrens of node lbessard@76: if recursion: lbessard@76: super, attrs = self.GenerateXSDClasses(node, parent) lbessard@76: inheritance.extend(super) lbessard@76: attributes.update(attrs) lbessard@76: lbessard@76: # if sequence tag have been found, order is returned lbessard@76: if sequence: lbessard@76: return inheritance, attributes, order lbessard@76: else: lbessard@76: return inheritance, attributes lbessard@76: lbessard@76: """ lbessard@76: Funtion that returns the Python type and default value for a given type lbessard@76: """ lbessard@83: def GetTypeInitialValue(self, attr_type, default = None): lbessard@76: type_compute = attr_type[4:].replace("[]", "") lbessard@76: if attr_type.startswith("bse:"): lbessard@76: if type_compute == "boolean": lbessard@83: if default: lbessard@83: def GetBooleanInitialValue(): lbessard@83: return default == "true" lbessard@83: return BooleanType, GetBooleanInitialValue lbessard@83: else: lbessard@83: return BooleanType, lambda:False lbessard@83: elif type_compute in ["unsignedLong","long","integer"]: lbessard@83: if default: lbessard@83: def GetIntegerInitialValue(): lbessard@83: return int(default) lbessard@83: return IntType, GetIntegerInitialValue lbessard@83: else: lbessard@83: return IntType, lambda:0 lbessard@83: elif type_compute == "decimal": lbessard@83: if default: lbessard@83: def GetFloatInitialValue(): lbessard@83: return float(default) lbessard@83: return FloatType, GetFloatInitialValue lbessard@83: else: lbessard@83: return FloatType, lambda:0. lbessard@76: elif type_compute in ["string","anyURI","NMTOKEN"]: lbessard@83: if default: lbessard@83: def GetStringInitialValue(): lbessard@83: return default lbessard@83: return StringType, GetStringInitialValue lbessard@83: else: lbessard@83: return StringType, lambda:"" lbessard@76: elif type_compute == "time": lbessard@83: if default: lbessard@83: def GetTimeInitialValue(): lbessard@83: result = time_model.match(value) lbessard@83: if result: lbessard@83: values = result.groups() lbessard@83: time_values = [int(v) for v in values[:2]] lbessard@83: seconds = float(values[2]) lbessard@83: time_values.extend([int(seconds), int((seconds % 1) * 1000000)]) lbessard@83: return time(*time_values) lbessard@83: return time(0,0,0,0) lbessard@92: return time, GetTimeInitialValue lbessard@92: else: lbessard@92: return time, lambda:time(0,0,0,0) lbessard@76: elif type_compute == "date": lbessard@83: if default: lbessard@83: def GetDateInitialValue(): lbessard@83: result = date_model.match(value) lbessard@83: if result: lbessard@83: date_values = [int(v) for v in result.groups()] lbessard@83: return date(*date_values) lbessard@83: return date(1,1,1) lbessard@92: return date, GetDateInitialValue lbessard@92: else: lbessard@92: return date, lambda:date(1,1,1) lbessard@76: elif type_compute == "dateTime": lbessard@83: if default: lbessard@83: def GetDateTimeInitialValue(): lbessard@83: result = datetime_model.match(value) lbessard@83: if result: lbessard@83: values = result.groups() lbessard@83: datetime_values = [int(v) for v in values[:5]] lbessard@83: seconds = float(values[5]) lbessard@83: datetime_values.extend([int(seconds), int((seconds % 1) * 1000000)]) lbessard@83: return datetime(*datetime_values) lbessard@83: return datetime(1,1,1,0,0,0,0) lbessard@92: return datetime, GetDateTimeInitialValue lbessard@92: else: lbessard@92: return datetime, lambda:datetime(1,1,1,0,0,0,0) lbessard@76: elif type_compute == "language": lbessard@83: if default: lbessard@83: def GetStringInitialValue(): lbessard@83: return default lbessard@83: return StringType, GetStringInitialValue lbessard@83: else: lbessard@83: return StringType, lambda:"en-US" lbessard@76: else: lbessard@76: print "Can't affect: %s"%type_compute lbessard@76: elif attr_type.startswith("cls:"): lbessard@76: if self.XMLClassDefinitions.get(type_compute, None) != None: lbessard@83: def GetClassInitialValue(): lbessard@83: if self.XMLClassDefinitions.get(type_compute, None) != None: lbessard@83: obj = self.ComputedClasses[type_compute]() lbessard@83: if default: lbessard@83: obj.setValue(default) lbessard@83: return obj lbessard@83: return None lbessard@83: return self.XMLClassDefinitions[type_compute], GetClassInitialValue lbessard@83: return None, lambda:None lbessard@83: lbessard@83: """ lbessard@83: Funtion that returns the Python type and default value for a given type lbessard@83: """ lbessard@83: def GetInitialValues(self, value_types): lbessard@83: initial_values = {} lbessard@83: for name, value_type in value_types.items(): lbessard@83: result = self.GetTypeInitialValue(value_type) lbessard@83: if result: lbessard@83: initial_values[name] = result[1] lbessard@83: return initial_values lbessard@76: lbessard@76: """ lbessard@76: Methods that generate the classes lbessard@76: """ lbessard@76: def CreateClasses(self): lbessard@76: self.GenerateXSDClasses(self.XML_Tree, None) lbessard@76: for classname in self.XMLClassDefinitions.keys(): lbessard@76: self.CreateClass(classname) lbessard@76: for classname in self.XMLClassDefinitions.keys(): lbessard@76: self.MarkUsedClasses(classname) lbessard@76: return self.ComputedClasses, self.ComputedTypes lbessard@76: lbessard@76: def CreateClass(self, classname): lbessard@76: # Checks that classe haven't been generated yet lbessard@76: if not self.AlreadyComputed.get(classname, False) and classname in self.XMLClassDefinitions: lbessard@76: self.AlreadyComputed[classname] = True lbessard@76: inheritance, attributes = self.XMLClassDefinitions[classname] lbessard@76: #print classname, inheritance, attributes lbessard@76: members = {} lbessard@76: bases = [] lbessard@76: lbessard@76: # If inheritance classes haven't been generated lbessard@76: for base in inheritance: lbessard@76: self.CreateClass(base) lbessard@76: bases.append(self.ComputedClasses[base]) lbessard@76: lbessard@76: # Checks that all attribute types are available lbessard@76: for attribute, type_attribute in attributes.items(): lbessard@76: if attribute == "group": lbessard@76: self.ComputedTypes[classname] = type_attribute lbessard@76: elif attribute in ["choice_content","multichoice_content"]: lbessard@76: element_types = {} lbessard@76: for attr, value in type_attribute.items(): lbessard@76: if attr == "ref": lbessard@76: for ref in value: lbessard@76: self.CreateClass(ref[4:]) lbessard@76: element_types.update(self.ComputedTypes[ref[4:]]) lbessard@76: else: lbessard@76: element_types[attr] = value lbessard@76: members[attribute] = element_types lbessard@76: else: lbessard@76: members[attribute] = type_attribute lbessard@76: if attribute == "enum": lbessard@76: self.ComputedTypes["%s_enum"%classname] = type_attribute lbessard@76: elif attribute not in ["limit", "order"]: lbessard@76: if type_attribute[0].startswith("cls:"): lbessard@76: type_compute = type_attribute[0][4:].replace("[]","") lbessard@76: self.CreateClass(type_compute) lbessard@76: if "group" not in attributes: lbessard@76: bases = tuple(bases) lbessard@76: classmembers = {"IsBaseClass" : True} lbessard@76: initialValues = {} lbessard@76: for attr, values in members.items(): lbessard@76: if attr in ["order", "basetype"]: lbessard@76: pass lbessard@76: lbessard@76: # Class is a enumerated type lbessard@76: elif attr == "enum": lbessard@76: value_type, initial = self.GetTypeInitialValue(members["basetype"]) lbessard@83: initialValues["value"] = GetInitialValueFunction(values[0]) lbessard@76: classmembers["value"] = values[0] lbessard@76: classmembers["setValue"] = generateSetEnumMethod(values, value_type) lbessard@76: classmembers["getValue"] = generateGetMethod("value") lbessard@83: classmembers["getValidValues"] = generateGetChoicesMethod(values) lbessard@76: lbessard@76: # Class is a limited type lbessard@76: elif attr == "limit": lbessard@76: value_type, initial = self.GetTypeInitialValue(members["basetype"]) lbessard@76: if "min" in values: lbessard@76: initial = max(initial, values["min"]) lbessard@92: elif "max" in values: lbessard@76: initial = min(initial, values["max"]) lbessard@83: initialValues["value"] = GetInitialValueFunction(initial) lbessard@76: classmembers["value"] = initial lbessard@76: classmembers["setValue"] = generateSetLimitMethod(values, value_type) lbessard@76: classmembers["getValue"] = generateGetMethod("value") lbessard@76: lbessard@76: # Class has an attribute that can have different value types lbessard@76: elif attr == "choice_content": lbessard@76: classmembers["content"] = None lbessard@83: initialValues["content"] = lambda:None lbessard@76: classmembers["deleteContent"] = generateDeleteMethod("content") lbessard@83: classmembers["addContent"] = generateAddChoiceMethod(values, self.GetInitialValues(values)) lbessard@76: classmembers["setContent"] = generateSetChoiceMethod(values) lbessard@76: classmembers["getContent"] = generateGetMethod("content") lbessard@83: classmembers["getChoices"] = generateGetChoicesMethod(values) lbessard@76: elif attr == "multichoice_content": lbessard@76: classmembers["content"] = [] lbessard@83: initialValues["content"] = lambda:[] lbessard@76: classmembers["appendContent"] = generateAppendChoiceMethod(values) lbessard@83: classmembers["appendContentByType"] = generateAppendChoiceByTypeMethod(values, self.GetInitialValues(values)) lbessard@76: classmembers["insertContent"] = generateInsertChoiceMethod(values) lbessard@76: classmembers["removeContent"] = generateRemoveMethod("content") lbessard@76: classmembers["countContent"] = generateCountMethod("content") lbessard@76: classmembers["setContent"] = generateSetMethod("content", ListType) lbessard@76: classmembers["getContent"] = generateGetMethod("content") lbessard@83: classmembers["getChoices"] = generateGetChoicesMethod(values) lbessard@76: lbessard@76: # It's an attribute of the class lbessard@76: else: lbessard@76: attrname = attr[0].upper()+attr[1:] lbessard@83: attr_type, xml_type, write_type, default = values lbessard@83: value_type, initial = self.GetTypeInitialValue(attr_type, default) lbessard@76: # Value of the attribute is a list lbessard@76: if attr_type.endswith("[]"): lbessard@76: classmembers[attr] = [] lbessard@83: initialValues[attr] = lambda:[] lbessard@76: classmembers["append"+attrname] = generateAppendMethod(attr, value_type) lbessard@76: classmembers["insert"+attrname] = generateInsertMethod(attr, value_type) lbessard@76: classmembers["remove"+attrname] = generateRemoveMethod(attr) lbessard@76: classmembers["count"+attrname] = generateCountMethod(attr) lbessard@76: classmembers["set"+attrname] = generateSetMethod(attr, ListType) lbessard@76: else: lbessard@76: if write_type == "optional": lbessard@76: classmembers[attr] = None lbessard@83: initialValues[attr] = lambda:None lbessard@83: classmembers["add"+attrname] = generateAddMethod(attr, initial) lbessard@76: classmembers["delete"+attrname] = generateDeleteMethod(attr) lbessard@76: else: lbessard@83: classmembers[attr] = initial() lbessard@76: initialValues[attr] = initial lbessard@76: classmembers["set"+attrname] = generateSetMethod(attr, value_type) lbessard@76: classmembers["get"+attrname] = generateGetMethod(attr) lbessard@83: classmembers["__init__"] = generateInitMethod(bases, initialValues) lbessard@76: classmembers["loadXMLTree"] = generateLoadXMLTree(bases, members, self.ComputedClasses) lbessard@76: classmembers["generateXMLText"] = generateGenerateXMLText(bases, members) lbessard@85: classmembers["getElementAttributes"] = generateGetElementAttributes(members, self.ComputedClasses) lbessard@85: classmembers["getElementInfos"] = generateGetElementInfos(members, self.ComputedClasses) lbessard@85: classmembers["setElementValue"] = generateSetElementValue(members) lbessard@76: classmembers["singleLineAttributes"] = True lbessard@76: lbessard@76: self.ComputedClasses[classname] = classobj(classname, bases, classmembers) lbessard@76: lbessard@76: def MarkUsedClasses(self, classname): lbessard@76: # Checks that classe haven't been generated yet lbessard@76: if classname in self.XMLClassDefinitions: lbessard@76: inheritance, attributes = self.XMLClassDefinitions[classname] lbessard@76: lbessard@76: # If inheritance classes haven't been generated lbessard@76: for base in inheritance: lbessard@76: if base in self.ComputedClasses: lbessard@76: self.ComputedClasses[base].IsBaseClass = False lbessard@76: lbessard@76: # Checks that all attribute types are available lbessard@76: for attribute, type_attribute in attributes.items(): lbessard@76: if attribute in ["choice_content","multichoice_content"]: lbessard@76: element_types = {} lbessard@76: for attr, value in type_attribute.items(): lbessard@76: if attr == "ref": lbessard@76: for ref in value: lbessard@76: element_types.update(self.ComputedTypes[ref[4:]]) lbessard@76: else: lbessard@76: element_types[attr] = value lbessard@76: for type_name in element_types.values(): lbessard@76: type_compute = type_name[4:].replace("[]","") lbessard@76: if type_compute in self.ComputedClasses: lbessard@76: self.ComputedClasses[type_compute].IsBaseClass = False lbessard@76: elif attribute != "group": lbessard@76: if attribute not in ["enum", "limit", "order"]: lbessard@76: if type_attribute[0].startswith("cls:"): lbessard@76: type_compute = type_attribute[0][4:].replace("[]","") lbessard@76: if type_compute in self.ComputedClasses: lbessard@76: self.ComputedClasses[type_compute].IsBaseClass = False lbessard@76: lbessard@76: """ lbessard@76: Methods that print the classes generated lbessard@76: """ lbessard@76: def PrintClasses(self): lbessard@76: for classname, xmlclass in self.ComputedClasses.items(): lbessard@76: print "%s : %s"%(classname, str(xmlclass)) lbessard@76: lbessard@76: def PrintClassNames(self): lbessard@76: classnames = self.XMLClassDefinitions.keys() lbessard@76: classnames.sort() lbessard@76: for classname in classnames: lbessard@76: print classname lbessard@76: lbessard@76: """ etisserant@75: Method that generate the method for loading an xml tree by following the etisserant@75: attributes list defined etisserant@75: """ lbessard@76: def generateLoadXMLTree(bases, members, classes): etisserant@75: def loadXMLTreeMethod(self, tree): etisserant@75: # If class is derived, values of inheritance classes are loaded etisserant@75: for base in bases: etisserant@75: base.loadXMLTree(self, tree) etisserant@75: # Class is a enumerated or limited value etisserant@75: if "enum" in members.keys() or "limit" in members.keys(): etisserant@75: attr_value = GetAttributeValue(tree) etisserant@75: attr_type = members["basetype"] etisserant@75: val = GetComputedValue(attr_type, attr_value) etisserant@75: self.setValue(val) etisserant@75: else: etisserant@75: etisserant@75: # Load the node attributes if they are defined in the list etisserant@75: for attrname, attr in tree._attrs.items(): etisserant@75: if attrname in members.keys(): lbessard@83: attr_type, xml_type, write_type, default = members[attrname] etisserant@75: attr_value = GetAttributeValue(attr) etisserant@75: if write_type != "optional" or attr_value != "": etisserant@75: # Extracts the value etisserant@75: if attr_type.startswith("bse:"): etisserant@75: val = GetComputedValue(attr_type, attr_value) etisserant@75: elif attr_type.startswith("cls:"): lbessard@76: val = classes[attr_type[4:]]() etisserant@75: val.loadXMLTree(attr) etisserant@75: setattr(self, attrname, val) etisserant@75: etisserant@75: # Load the node childs if they are defined in the list etisserant@75: for node in tree.childNodes: etisserant@75: name = node.nodeName etisserant@75: # We make fun of #text elements etisserant@75: if name != "#text": etisserant@75: etisserant@75: # Class has an attribute that can have different value types etisserant@75: if "choice_content" in members.keys() and name in members["choice_content"].keys(): etisserant@75: attr_type = members["choice_content"][name] etisserant@75: # Extracts the value etisserant@75: if attr_type.startswith("bse:"): etisserant@75: attr_value = GetAttributeValue(node) etisserant@75: if write_type != "optional" or attr_value != "": etisserant@75: val = GetComputedValue(attr_type.replace("[]",""), attr_value) etisserant@75: else: etisserant@75: val = None etisserant@75: elif attr_type.startswith("cls:"): lbessard@76: val = classes[attr_type[4:].replace("[]","")]() etisserant@75: val.loadXMLTree(node) etisserant@75: # Stock value in content attribute etisserant@75: if val: etisserant@75: if attr_type.endswith("[]"): etisserant@75: if self.content: etisserant@75: self.content["value"].append(val) etisserant@75: else: etisserant@75: self.content = {"name":name,"value":[val]} etisserant@75: else: etisserant@75: self.content = {"name":name,"value":val} etisserant@75: etisserant@75: # Class has a list of attributes that can have different value types etisserant@75: elif "multichoice_content" in members.keys() and name in members["multichoice_content"].keys(): etisserant@75: attr_type = members["multichoice_content"][name] etisserant@75: # Extracts the value etisserant@75: if attr_type.startswith("bse:"): etisserant@75: attr_value = GetAttributeValue(node) etisserant@75: if write_type != "optional" or attr_value != "": etisserant@75: val = GetComputedValue(attr_type, attr_value) etisserant@75: else: etisserant@75: val = None etisserant@75: elif attr_type.startswith("cls:"): lbessard@76: val = classes[attr_type[4:]]() etisserant@75: val.loadXMLTree(node) etisserant@75: # Add to content attribute list etisserant@75: if val: etisserant@75: self.content.append({"name":name,"value":val}) etisserant@75: etisserant@75: # The node child is defined in the list etisserant@75: elif name in members.keys(): lbessard@83: attr_type, xml_type, write_type, default = members[name] etisserant@75: # Extracts the value etisserant@75: if attr_type.startswith("bse:"): etisserant@75: attr_value = GetAttributeValue(node) etisserant@75: if write_type != "optional" or attr_value != "": etisserant@75: val = GetComputedValue(attr_type.replace("[]",""), attr_value) etisserant@75: else: etisserant@75: val = None etisserant@75: elif attr_type.startswith("cls:"): lbessard@76: val = classes[attr_type[4:].replace("[]","")]() etisserant@75: val.loadXMLTree(node) etisserant@75: # Stock value in attribute etisserant@75: if val: etisserant@75: if attr_type.endswith("[]"): etisserant@75: getattr(self, name).append(val) etisserant@75: else: etisserant@75: setattr(self, name, val) etisserant@75: return loadXMLTreeMethod etisserant@75: etisserant@75: """ etisserant@75: Method that generates the method for generating an xml text by following the etisserant@75: attributes list defined etisserant@75: """ etisserant@75: def generateGenerateXMLText(bases, members): etisserant@75: def generateXMLTextMethod(self, name, indent, extras = {}, derived = False): etisserant@75: ind1, ind2 = getIndent(indent, name) etisserant@75: if not derived: etisserant@75: text = ind1 + "<%s"%name etisserant@75: else: etisserant@75: text = "" etisserant@75: if len(bases) > 0: etisserant@75: base_extras = {} etisserant@75: if "order" in members.keys(): etisserant@75: order = members["order"] etisserant@75: else: etisserant@75: order = [] lbessard@83: for attr, values in members.items(): lbessard@83: if attr != "order" and (attr in ("choice_content", "multichoice_content") or values[1] != "attribute"): lbessard@83: if attr not in order: lbessard@83: order.append(attr) etisserant@75: size = 0 etisserant@75: first = True etisserant@75: for attr, value in extras.items(): etisserant@75: if not first and not self.singleLineAttributes: etisserant@75: text += "\n%s"%(ind2) etisserant@75: text += " %s=\"%s\""%(attr, ComputeValue(value)) etisserant@75: first = False etisserant@75: for attr, values in members.items(): etisserant@75: if attr in ["order","choice_content","multichoice_content"]: lbessard@2: pass etisserant@75: elif attr in ["enum","limit"]: etisserant@75: if not derived: etisserant@75: text += ">%s\n"%(ComputeValue(self.value),name) etisserant@75: else: etisserant@75: text += ComputeValue(self.value) etisserant@75: return text etisserant@75: elif values[1] == "attribute": etisserant@75: value = getattr(self, attr, None) lbessard@86: if value != None: lbessard@86: if values[0].startswith("cls"): lbessard@86: value = value.getValue() lbessard@86: computed_value = ComputeValue(value) lbessard@86: else: lbessard@86: computed_value = None lbessard@88: if values[2] != "optional" or (value != None and computed_value != values[3]): lbessard@83: if len(bases) > 0: lbessard@83: base_extras[attr] = value etisserant@75: else: lbessard@83: if not first and not self.singleLineAttributes: lbessard@83: text += "\n%s"%(ind2) lbessard@83: text += " %s=\"%s\""%(attr, computed_value) etisserant@75: first = False etisserant@75: if len(bases) > 0: etisserant@75: first, new_text = bases[0].generateXMLText(self, name, indent, base_extras, True) etisserant@75: text += new_text etisserant@75: else: etisserant@75: first = True etisserant@75: ind3, ind4 = getIndent(indent + 1, name) etisserant@75: for attr in order: etisserant@75: value = getattr(self, attr, None) etisserant@75: if attr == "choice_content": etisserant@75: if self.content: etisserant@75: if first: etisserant@75: text += ">\n" etisserant@75: first = False etisserant@75: value_type = members[attr][self.content["name"]] etisserant@75: if value_type.startswith("bse:"): etisserant@75: if value_type.endswith("[]"): etisserant@75: for content in self.content["value"]: etisserant@75: text += ind1 + "<%s>%s\n"%(self.content["name"], ComputeValue(content), self.content["name"]) etisserant@75: else: etisserant@75: text += ind1 + "<%s>%s\n"%(self.content["name"], ComputeValue(self.content["value"]), self.content["name"]) etisserant@75: elif value_type.endswith("[]"): etisserant@75: for content in self.content["value"]: etisserant@75: text += content.generateXMLText(self.content["name"], indent + 1) etisserant@75: else: etisserant@75: text += self.content["value"].generateXMLText(self.content["name"], indent + 1) lbessard@2: elif attr == "multichoice_content": etisserant@75: if len(self.content) > 0: etisserant@75: for element in self.content: lbessard@2: if first: lbessard@2: text += ">\n" lbessard@2: first = False etisserant@75: value_type = members[attr][element["name"]] lbessard@2: if value_type.startswith("bse:"): etisserant@75: text += ind1 + "<%s>%s\n"%(element["name"], ComputeValue(element["value"]), element["name"]) lbessard@2: else: etisserant@75: text += element["value"].generateXMLText(element["name"], indent + 1) etisserant@75: elif members[attr][2] != "optional" or value != None: etisserant@75: if members[attr][0].endswith("[]"): etisserant@75: if first and len(value) > 0: etisserant@75: text += ">\n" etisserant@75: first = False etisserant@75: for element in value: etisserant@75: if members[attr][0].startswith("bse:"): etisserant@75: text += ind3 + "<%s>%s\n"%(attr, ComputeValue(element), attr) etisserant@75: else: etisserant@75: text += element.generateXMLText(attr, indent + 1) etisserant@75: else: etisserant@75: if first: etisserant@75: text += ">\n" etisserant@75: first = False etisserant@75: if members[attr][0].startswith("bse:"): etisserant@75: text += ind3 + "<%s>%s\n"%(attr, ComputeValue(value), attr) lbessard@2: else: etisserant@75: text += getattr(self, attr).generateXMLText(attr, indent + 1) etisserant@75: if not derived: etisserant@75: if first: etisserant@75: text += "/>\n" etisserant@75: else: etisserant@75: text += ind1 + "\n"%(name) etisserant@75: return text etisserant@75: else: etisserant@75: return first, text etisserant@75: return generateXMLTextMethod etisserant@75: etisserant@75: lbessard@85: def generateGetElementAttributes(members, classes): etisserant@75: def getElementAttributes(self): etisserant@75: attr_list = [] etisserant@75: for attr, values in members.items(): etisserant@75: if attr in ["order","choice_content","multichoice_content"]: etisserant@75: pass etisserant@75: elif values[1] == "attribute": lbessard@83: attr_params = {"name": attr, "require": values[2] == "required"} lbessard@83: if values[0].startswith("cls:"): lbessard@83: attr_value = getattr(self, attr, None) lbessard@83: if attr_value: lbessard@83: attr_params["value"] = attr_value.getValue() lbessard@83: else: lbessard@83: attr_params["value"] = "" lbessard@83: attr_params["type"] = classes[values[0][4:]]().getValidValues() lbessard@83: else: lbessard@83: attr_params["value"] = getattr(self, attr, "") lbessard@83: attr_params["type"] = values[0][4:] lbessard@83: attr_list.append(attr_params) etisserant@75: return attr_list etisserant@75: return getElementAttributes lbessard@85: lbessard@85: def generateGetElementInfos(members, classes): lbessard@85: def getElementInfos(self, name, path = None): lbessard@85: attr_type = "element" lbessard@85: value = None lbessard@85: children = [] lbessard@85: if "enum" in members: lbessard@85: attr_type = self.getValidValues() lbessard@85: value = self.value lbessard@85: elif "limit" in members: lbessard@85: attr_type = {"min" : None, "max" : None} lbessard@85: if "min" in members: lbessard@85: attr_type["min"] = members["min"] lbessard@85: if "max" in members: lbessard@85: attr_type["max"] = members["max"] lbessard@85: value = self.value lbessard@85: elif path: lbessard@85: if "choice_content" in members: lbessard@85: return self.content["value"].getElementInfos(self.content["name"], path) lbessard@85: elif "multichoice_content" not in members: lbessard@85: parts = path.split(".", 1) lbessard@85: if parts[0] in members: lbessard@85: values = members[parts[0]] lbessard@85: if values[1] == "attribute" and len(parts) == 1: lbessard@85: attr = getattr(self, parts[0], None) lbessard@85: if attr != None: lbessard@85: if values[0].startswith("cls:"): lbessard@85: return attr.getElementInfos(parts[0]) lbessard@85: else: lbessard@85: attr_type = values[0][4:] lbessard@85: value = getattr(self, attr, "") lbessard@85: elif values[1] == "element": lbessard@85: attr = getattr(self, parts[0], None) lbessard@85: if attr != None: lbessard@85: if len(parts) == 1: lbessard@85: return attr.getElementInfos(parts[0]) lbessard@85: else: lbessard@85: return attr.getElementInfos(parts[0], parts[1]) lbessard@85: else: lbessard@85: for attr, values in members.items(): lbessard@85: if attr == "order": lbessard@85: pass lbessard@85: elif attr == "choice_content": lbessard@85: attr_type = self.getChoices().items() etisserant@87: if self.content: etisserant@87: value = self.content["name"] etisserant@87: children.extend(self.content["value"].getElementInfos(self.content["name"])["children"]) lbessard@85: elif attr == "multichoice_content": lbessard@85: for element_infos in self.content: lbessard@85: children.append(element_infos["value"].getElementInfos(element_infos["name"])) lbessard@85: elif values[1] == "attribute" and not values[0].startswith("cls:"): lbessard@85: children.append({"name" : attr, "value" : getattr(self, attr, ""), "type" : values[0][4:], "children" : []}) lbessard@85: else: lbessard@85: element = getattr(self, attr, None) lbessard@85: if not element: lbessard@85: element = classes[values[0][4:]]() lbessard@85: children.append(element.getElementInfos(attr)) lbessard@85: return {"name" : name, "type" : attr_type, "value" : value, "children" : children} lbessard@85: return getElementInfos lbessard@85: lbessard@85: def generateSetElementValue(members): lbessard@85: def setElementValue(self, path, value): lbessard@85: if "enum" in members or "limit" in members: lbessard@85: if not path: lbessard@85: self.setValue(value) lbessard@85: elif "choice_content" in members: lbessard@85: if path: lbessard@85: self.content["value"].setElementValue(path, value) lbessard@85: else: lbessard@85: self.addContent(value) lbessard@85: else: lbessard@85: parts = path.split(".", 1) lbessard@85: if parts[0] in members: lbessard@85: values = members[parts[0]] lbessard@85: if values[1] == "attribute" and len(parts) == 1: lbessard@85: attr = getattr(self, parts[0], None) lbessard@85: if attr != None: lbessard@85: if values[0].startswith("cls:"): lbessard@85: attr.setElementValue(None, value) lbessard@85: elif values[0][4:] == "boolean": lbessard@85: setattr(self, parts[0], value) lbessard@85: else: lbessard@85: setattr(self, parts[0], GetComputedValue(values[0], value)) lbessard@85: elif values[1] == "element": lbessard@85: attr = getattr(self, parts[0], None) lbessard@85: if attr != None: lbessard@85: if len(parts) == 1: lbessard@85: attr.setElementValue(None, value) lbessard@85: else: lbessard@85: attr.setElementValue(parts[1], value) lbessard@85: return setElementValue lbessard@85: etisserant@75: """ etisserant@75: Methods that generates the different methods for setting and getting the attributes etisserant@75: """ lbessard@83: def generateInitMethod(bases, members): etisserant@75: def initMethod(self): etisserant@75: for base in bases: etisserant@75: base.__init__(self) etisserant@75: for attr, initial in members.items(): lbessard@83: setattr(self, attr, initial()) etisserant@75: return initMethod etisserant@75: etisserant@75: def generateSetMethod(attr, attr_type): etisserant@75: def setMethod(self, value): etisserant@75: setattr(self, attr, value) etisserant@75: return setMethod etisserant@75: lbessard@83: def generateAddChoiceMethod(choice_type, initial_values): lbessard@83: def addChoiceMethod(self, name): lbessard@83: if name in choice_type: lbessard@83: self.content = {"name" : name, "value" : initial_values[name]()} lbessard@83: return addChoiceMethod lbessard@83: etisserant@75: def generateSetChoiceMethod(choice_type): etisserant@75: def setChoiceMethod(self, name, value): lbessard@83: self.content = {"name" : name, "value" : value} etisserant@75: return setChoiceMethod etisserant@75: lbessard@83: def generateGetChoicesMethod(choice_type): lbessard@83: def getChoicesMethod(self): lbessard@83: return choice_type lbessard@83: return getChoicesMethod lbessard@83: etisserant@75: def generateSetEnumMethod(enum, attr_type): etisserant@75: def setEnumMethod(self, value): etisserant@75: if value in enum: etisserant@75: self.value = value etisserant@75: else: etisserant@75: raise ValueError, "%s is not a valid value. Must be in %s"%(value, str(enum)) etisserant@75: return setEnumMethod etisserant@75: etisserant@75: def generateSetLimitMethod(limit, attr_type): etisserant@75: def setMethod(self, value): etisserant@75: if "min" in limit and value < limit["min"]: etisserant@75: raise ValueError, "%s is not a valid value. Must be greater than %d"%(value, limit["min"]) etisserant@75: elif "max" in limit and value > limit["max"]: etisserant@75: raise ValueError, "%s is not a valid value. Must be smaller than %d"%(value, limit["max"]) etisserant@75: else: etisserant@75: self.value = value etisserant@75: return setMethod etisserant@75: etisserant@75: def generateGetMethod(attr): etisserant@75: def getMethod(self): etisserant@75: return getattr(self, attr, None) etisserant@75: return getMethod etisserant@75: lbessard@83: def generateAddMethod(attr, initial): etisserant@75: def addMethod(self): lbessard@83: setattr(self, attr, initial()) etisserant@75: return addMethod etisserant@75: etisserant@75: def generateDeleteMethod(attr): etisserant@75: def deleteMethod(self): etisserant@75: setattr(self, attr, None) etisserant@75: return deleteMethod etisserant@75: etisserant@75: def generateAppendMethod(attr, attr_type): etisserant@75: def appendMethod(self, value): etisserant@75: getattr(self, attr).append(value) etisserant@75: return appendMethod etisserant@75: etisserant@75: def generateInsertMethod(attr, attr_type): etisserant@75: def insertMethod(self, index, value): etisserant@75: getattr(self, attr).insert(index, value) etisserant@75: return insertMethod etisserant@75: lbessard@83: def generateAppendChoiceByTypeMethod(choice_type, initial_values): lbessard@83: def addChoiceMethod(self, name): lbessard@83: if name in choice_type: lbessard@83: self.content.append({"name" : name, "value" : initial_values[name]()}) lbessard@83: return addChoiceMethod lbessard@83: etisserant@75: def generateAppendChoiceMethod(choice_types): etisserant@75: def appendMethod(self, name, value): etisserant@75: self.content.append({"name":name,"value":value}) etisserant@75: return appendMethod etisserant@75: etisserant@75: def generateInsertChoiceMethod(choice_types): etisserant@75: def insertMethod(self, index, name, value): etisserant@75: self.content.insert(index, {"name":name,"value":value}) etisserant@75: return insertMethod etisserant@75: etisserant@75: def generateRemoveMethod(attr): etisserant@75: def removeMethod(self, index): etisserant@75: getattr(self, attr).pop(index) etisserant@75: return removeMethod etisserant@75: etisserant@75: def generateCountMethod(attr): etisserant@75: def countMethod(self): etisserant@75: return len(getattr(self, attr)) etisserant@75: return countMethod etisserant@75: etisserant@75: """ lbessard@76: This function generate the classes from a class factory lbessard@76: """ lbessard@76: def GenerateClasses(factory, declare = False): lbessard@76: ComputedClasses, ComputedTypes = factory.CreateClasses() lbessard@76: if declare: lbessard@76: for ClassName, Class in pluginClasses.items(): lbessard@76: sys._getframe(1).f_locals[ClassName] = Class lbessard@76: for TypeName, Type in pluginTypes.items(): lbessard@76: sys._getframe(1).f_locals[TypeName] = Type lbessard@83: globals().update(ComputedClasses) lbessard@76: return ComputedClasses, ComputedTypes lbessard@76: lbessard@76: """ lbessard@76: This function opens the xsd file and generate the classes from the xml tree lbessard@76: """ lbessard@76: def GenerateClassesFromXSD(filename, declare = False): lbessard@76: xsdfile = open(filename, 'r') lbessard@76: factory = ClassFactory(minidom.parse(xsdfile)) lbessard@76: xsdfile.close() lbessard@76: return GenerateClasses(factory, declare) lbessard@76: lbessard@76: """ lbessard@76: This function generate the classes from the xsd given as a string lbessard@76: """ lbessard@76: def GenerateClassesFromXSDstring(xsdstring, declare = False): lbessard@76: factory = ClassFactory(minidom.parseString(xsdstring)) lbessard@76: return GenerateClasses(factory, declare) lbessard@76: