--- 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)
+
+