xmlclass/xmlclass.py
changeset 1303 908a5803c2cc
parent 1300 8e1ee07bdff8
child 1304 6be6c1e0e4d0
equal deleted inserted replaced
1302:7856cd7767d6 1303:908a5803c2cc
   614                 return value
   614                 return value
   615         return [initial_value() for i in xrange(infos["minOccurs"])]
   615         return [initial_value() for i in xrange(infos["minOccurs"])]
   616     else:
   616     else:
   617         return []
   617         return []
   618 
   618 
   619 def HandleError(message, raise_exception):
       
   620     if raise_exception:
       
   621         raise ValueError(message)
       
   622     return False
       
   623 
       
   624 def CheckElementValue(factory, name, infos, value, raise_exception=True):
       
   625     infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
       
   626     if value is None and raise_exception:
       
   627         if not (infos["minOccurs"] == 0 and infos["maxOccurs"] == 1):
       
   628             return HandleError("Attribute '%s' isn't optional." % name, raise_exception)
       
   629     elif infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
       
   630         if not isinstance(value, ListType):
       
   631             return HandleError("Attribute '%s' must be a list." % name, raise_exception)
       
   632         if len(value) < infos["minOccurs"] or infos["maxOccurs"] != "unbounded" and len(value) > infos["maxOccurs"]:
       
   633             return HandleError("List out of bounds for attribute '%s'." % name, raise_exception)
       
   634         if not reduce(lambda x, y: x and y, map(infos["elmt_type"]["check"], value), True):
       
   635             return HandleError("Attribute '%s' must be a list of valid elements." % name, raise_exception)
       
   636     elif infos.has_key("fixed") and value != infos["fixed"]:
       
   637         return HandleError("Value of attribute '%s' can only be '%s'." % (name, str(infos["fixed"])), raise_exception)
       
   638     else:
       
   639         return infos["elmt_type"]["check"](value)
       
   640     return True
       
   641 
       
   642 def GetContentInfos(name, choices):
   619 def GetContentInfos(name, choices):
   643     for choice_infos in choices:
   620     for choice_infos in choices:
   644         if choices_infos["type"] == "sequence":
   621         if choices_infos["type"] == "sequence":
   645             for element_infos in choices_infos["elements"]:
   622             for element_infos in choices_infos["elements"]:
   646                 if element_infos["type"] == CHOICE:
   623                 if element_infos["type"] == CHOICE:
   670             if choice_infos is not None:
   647             if choice_infos is not None:
   671                 choice["elmt_type"] = choice_infos
   648                 choice["elmt_type"] = choice_infos
   672         choices.append((choice["name"], choice))
   649         choices.append((choice["name"], choice))
   673     return choices
   650     return choices
   674 
   651 
   675 def ExtractContentElement(factory, tree, infos, content):
       
   676     infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
       
   677     if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
       
   678         if isinstance(content, ListType) and len(content) > 0 and \
       
   679            content[-1]["name"] == tree.nodeName:
       
   680             content_item = content.pop(-1)
       
   681             content_item["value"].append(infos["elmt_type"]["extract"](tree))
       
   682             return content_item
       
   683         elif not isinstance(content, ListType) and \
       
   684              content is not None and \
       
   685              content["name"] == tree.nodeName:
       
   686             return {"name": tree.nodeName, 
       
   687                     "value": content["value"] + [infos["elmt_type"]["extract"](tree)]}
       
   688         else:
       
   689             return {"name": tree.nodeName, 
       
   690                     "value": [infos["elmt_type"]["extract"](tree)]}
       
   691     else:
       
   692         return {"name": tree.nodeName, 
       
   693                 "value": infos["elmt_type"]["extract"](tree)}
       
   694 
       
   695 def GenerateContentInfos(factory, name, choices):
   652 def GenerateContentInfos(factory, name, choices):
   696     choices_dict = {}
   653     choices_dict = {}
   697     for choice_name, infos in choices:
   654     for choice_name, infos in choices:
   698         if choice_name == "sequence":
   655         if choice_name == "sequence":
   699             for element in infos["elements"]:
   656             for element in infos["elements"]:
   726                             content_value.append({"name": element_infos["name"], "value": value})
   683                             content_value.append({"name": element_infos["name"], "value": value})
   727         else:
   684         else:
   728             content_value = GetElementInitialValue(factory, infos)
   685             content_value = GetElementInitialValue(factory, infos)
   729         return {"name": content_name, "value": content_value}
   686         return {"name": content_name, "value": content_value}
   730         
   687         
   731     def CheckContent(value):
       
   732         if value["name"] != "sequence":
       
   733             infos = choices_dict.get(value["name"], None)
       
   734             if infos is not None:
       
   735                 return CheckElementValue(factory, value["name"], infos, value["value"], False)
       
   736         elif len(value["value"]) > 0:
       
   737             infos = choices_dict.get(value["value"][0]["name"], None)
       
   738             if infos is None:
       
   739                 for choice_name, infos in choices:
       
   740                     if infos["type"] == "sequence":
       
   741                         for element_infos in infos["elements"]:
       
   742                             if element_infos["type"] == CHOICE:
       
   743                                 infos = GetContentInfos(value["value"][0]["name"], element_infos["choices"])
       
   744             if infos is not None:
       
   745                 sequence_number = 0
       
   746                 element_idx = 0
       
   747                 while element_idx < len(value["value"]):
       
   748                     for element_infos in infos["elements"]:
       
   749                         element_value = None
       
   750                         if element_infos["type"] == CHOICE:
       
   751                             choice_infos = None
       
   752                             if element_idx < len(value["value"]):
       
   753                                 for choice in element_infos["choices"]:
       
   754                                     if choice["name"] == value["value"][element_idx]["name"]:
       
   755                                         choice_infos = choice
       
   756                                         element_value = value["value"][element_idx]["value"]
       
   757                                         element_idx += 1
       
   758                                         break
       
   759                             if ((choice_infos is not None and 
       
   760                                  not CheckElementValue(factory, choice_infos["name"], choice_infos, element_value, False)) or
       
   761                                 (choice_infos is None and element_infos["minOccurs"] > 0)):
       
   762                                 raise ValueError("Invalid sequence value in attribute 'content'")
       
   763                         else:
       
   764                             if element_idx < len(value["value"]) and element_infos["name"] == value["value"][element_idx]["name"]:
       
   765                                 element_value = value["value"][element_idx]["value"]
       
   766                                 element_idx += 1
       
   767                             if not CheckElementValue(factory, element_infos["name"], element_infos, element_value, False):
       
   768                                 raise ValueError("Invalid sequence value in attribute 'content'")
       
   769                     sequence_number += 1
       
   770                 if sequence_number < infos["minOccurs"] or infos["maxOccurs"] != "unbounded" and sequence_number > infos["maxOccurs"]:
       
   771                     raise ValueError("Invalid sequence value in attribute 'content'")
       
   772                 return True
       
   773         else:
       
   774             for element_name, infos in choices:
       
   775                 if element_name == "sequence":
       
   776                     required = 0
       
   777                     for element in infos["elements"]:
       
   778                         if element["minOccurs"] > 0:
       
   779                             required += 1
       
   780                     if required == 0:
       
   781                         return True
       
   782         return False
       
   783     
       
   784     def ExtractContent(tree, content):
       
   785         infos = choices_dict.get(tree.nodeName, None)
       
   786         if infos is not None:
       
   787             if infos["name"] == "sequence":
       
   788                 sequence_dict = dict([(element_infos["name"], element_infos) for element_infos in infos["elements"] if element_infos["type"] != CHOICE])
       
   789                 element_infos = sequence_dict.get(tree.nodeName)
       
   790                 if content is not None and \
       
   791                    content["name"] == "sequence" and \
       
   792                    len(content["value"]) > 0 and \
       
   793                    choices_dict.get(content["value"][-1]["name"]) == infos:
       
   794                     return {"name": "sequence",
       
   795                             "value": content["value"] + [ExtractContentElement(factory, tree, element_infos, content["value"][-1])]}
       
   796                 else:
       
   797                     return {"name": "sequence",
       
   798                             "value": [ExtractContentElement(factory, tree, element_infos, None)]}
       
   799             else:
       
   800                 return ExtractContentElement(factory, tree, infos, content)
       
   801         else:
       
   802             for choice_name, infos in choices:
       
   803                 if infos["type"] == "sequence":
       
   804                     for element_infos in infos["elements"]:
       
   805                         if element_infos["type"] == CHOICE:
       
   806                             try:
       
   807                                 if content is not None and \
       
   808                                     content["name"] == "sequence" and \
       
   809                                     len(content["value"]) > 0:
       
   810                                     return {"name": "sequence",
       
   811                                             "value": content["value"] + [element_infos["elmt_type"]["extract"](tree, content["value"][-1])]}
       
   812                                 else:
       
   813                                     return {"name": "sequence",
       
   814                                             "value": [element_infos["elmt_type"]["extract"](tree, None)]}
       
   815                             except:
       
   816                                 pass
       
   817         raise ValueError("Invalid element \"%s\" for content!" % tree.nodeName)
       
   818     
       
   819     def GenerateContent(value, name=None, indent=0):
       
   820         text = ""
       
   821         if value["name"] != "sequence":
       
   822             infos = choices_dict.get(value["name"], None)
       
   823             if infos is not None:
       
   824                 infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
       
   825                 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
       
   826                     for item in value["value"]:
       
   827                         text += infos["elmt_type"]["generate"](item, value["name"], indent)
       
   828                 else:
       
   829                     text += infos["elmt_type"]["generate"](value["value"], value["name"], indent)
       
   830         elif len(value["value"]) > 0:
       
   831             infos = choices_dict.get(value["value"][0]["name"], None)
       
   832             if infos is None:
       
   833                 for choice_name, infos in choices:
       
   834                     if infos["type"] == "sequence":
       
   835                         for element_infos in infos["elements"]:
       
   836                             if element_infos["type"] == CHOICE:
       
   837                                 infos = GetContentInfos(value["value"][0]["name"], element_infos["choices"])
       
   838             if infos is not None:
       
   839                 sequence_dict = dict([(element_infos["name"], element_infos) for element_infos in infos["elements"]]) 
       
   840                 for element_value in value["value"]:
       
   841                     element_infos = sequence_dict.get(element_value["name"])
       
   842                     if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
       
   843                         for item in element_value["value"]:
       
   844                             text += element_infos["elmt_type"]["generate"](item, element_value["name"], indent)
       
   845                     else:
       
   846                         text += element_infos["elmt_type"]["generate"](element_value["value"], element_infos["name"], indent)
       
   847         return text
       
   848         
       
   849     return {
   688     return {
   850         "type": COMPLEXTYPE,
   689         "type": COMPLEXTYPE,
   851         "choices_xpath": GetContentChoicesXPath,
   690         "choices_xpath": GetContentChoicesXPath,
   852         "initial": GetContentInitial,
   691         "initial": GetContentInitial,
   853         "check": CheckContent,
       
   854         "extract": ExtractContent,
       
   855         "generate": GenerateContent
       
   856     }
   692     }
   857 
   693 
   858 #-------------------------------------------------------------------------------
   694 #-------------------------------------------------------------------------------
   859 #                           Structure extraction functions
   695 #                           Structure extraction functions
   860 #-------------------------------------------------------------------------------
   696 #-------------------------------------------------------------------------------
  1298                     classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname)
  1134                     classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname)
  1299             classmembers["set%s" % elmtname] = generateSetMethod(elmtname)
  1135             classmembers["set%s" % elmtname] = generateSetMethod(elmtname)
  1300             classmembers["get%s" % elmtname] = generateGetMethod(elmtname)
  1136             classmembers["get%s" % elmtname] = generateGetMethod(elmtname)
  1301             
  1137             
  1302         classmembers["init"] = generateInitMethod(self, classinfos)
  1138         classmembers["init"] = generateInitMethod(self, classinfos)
  1303         classmembers["getStructure"] = generateStructureMethod(classinfos)
       
  1304         classmembers["loadXMLTree"] = generateLoadXMLTree(self, classinfos)
       
  1305         classmembers["generateXMLText"] = generateGenerateXMLText(self, classinfos)
       
  1306         classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos)
  1139         classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos)
  1307         classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos)
  1140         classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos)
  1308         classmembers["setElementValue"] = generateSetElementValue(self, classinfos)
  1141         classmembers["setElementValue"] = generateSetElementValue(self, classinfos)
  1309         classmembers["singleLineAttributes"] = True
       
  1310         classmembers["compatibility"] = lambda x, y: None
       
  1311         classmembers["extraAttrs"] = {}
       
  1312         
  1142         
  1313         class_definition = classobj(str(classname), bases, classmembers)
  1143         class_definition = classobj(str(classname), bases, classmembers)
  1314         setattr(class_definition, "__getattr__", generateGetattrMethod(self, class_definition, classinfos))
  1144         setattr(class_definition, "__getattr__", generateGetattrMethod(self, class_definition, classinfos))
  1315         setattr(class_definition, "__setattr__", generateSetattrMethod(self, class_definition, classinfos))
  1145         setattr(class_definition, "__setattr__", generateSetattrMethod(self, class_definition, classinfos))
  1316         class_infos = {"type": COMPILEDCOMPLEXTYPE,
  1146         class_infos = {"type": COMPILEDCOMPLEXTYPE,
  1317                        "name": classname,
  1147                        "name": classname,
  1318                        "check": generateClassCheckFunction(class_definition),
       
  1319                        "initial": generateClassCreateFunction(class_definition),
  1148                        "initial": generateClassCreateFunction(class_definition),
  1320                        "extract": generateClassExtractFunction(class_definition),
  1149         }
  1321                        "generate": class_definition.generateXMLText}
       
  1322         
  1150         
  1323         if self.FileName is not None:
  1151         if self.FileName is not None:
  1324             self.ComputedClasses[self.FileName][classname] = class_definition
  1152             self.ComputedClasses[self.FileName][classname] = class_definition
  1325         else:
  1153         else:
  1326             self.ComputedClasses[classname] = class_definition
  1154             self.ComputedClasses[classname] = class_definition
  1353         classnames.sort()
  1181         classnames.sort()
  1354         for classname in classnames:
  1182         for classname in classnames:
  1355             print classname
  1183             print classname
  1356 
  1184 
  1357 """
  1185 """
  1358 Method that generate the method for checking a class instance
       
  1359 """
       
  1360 def generateClassCheckFunction(class_definition):
       
  1361     def classCheckfunction(instance):
       
  1362         return isinstance(instance, class_definition)
       
  1363     return classCheckfunction
       
  1364 
       
  1365 """
       
  1366 Method that generate the method for creating a class instance
  1186 Method that generate the method for creating a class instance
  1367 """
  1187 """
  1368 def generateClassCreateFunction(class_definition):
  1188 def generateClassCreateFunction(class_definition):
  1369     def classCreatefunction():
  1189     def classCreatefunction():
  1370         return class_definition()
  1190         return class_definition()
  1371     return classCreatefunction
  1191     return classCreatefunction
  1372 
       
  1373 """
       
  1374 Method that generate the method for extracting a class instance
       
  1375 """
       
  1376 def generateClassExtractFunction(class_definition):
       
  1377     def classExtractfunction(node):
       
  1378         instance = class_definition()
       
  1379         instance.loadXMLTree(node)
       
  1380         return instance
       
  1381     return classExtractfunction
       
  1382 
  1192 
  1383 def generateGetattrMethod(factory, class_definition, classinfos):
  1193 def generateGetattrMethod(factory, class_definition, classinfos):
  1384     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1194     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1385     optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
  1195     optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
  1386     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1196     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1422         
  1232         
  1423         return DefaultElementClass.__getattribute__(self, name)
  1233         return DefaultElementClass.__getattribute__(self, name)
  1424     
  1234     
  1425     return getattrMethod
  1235     return getattrMethod
  1426 
  1236 
  1427 """
       
  1428 Method that generate the method for loading an xml tree by following the
       
  1429 attributes list defined
       
  1430 """
       
  1431 def generateSetattrMethod(factory, class_definition, classinfos):
  1237 def generateSetattrMethod(factory, class_definition, classinfos):
  1432     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1238     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1433     optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
  1239     optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
  1434     elements = OrderedDict([(element["name"], element) for element in classinfos["elements"]])
  1240     elements = OrderedDict([(element["name"], element) for element in classinfos["elements"]])
  1435     
  1241     
  1480                         self.insert(insertion_point, element)
  1286                         self.insert(insertion_point, element)
  1481         
  1287         
  1482         elif classinfos.has_key("base"):
  1288         elif classinfos.has_key("base"):
  1483             return classinfos["base"].__setattr__(self, name, value)
  1289             return classinfos["base"].__setattr__(self, name, value)
  1484         
  1290         
  1485         elif class_definition.__dict__.has_key(name):
       
  1486             return DefaultElementClass.__setattr__(self, name, value)
       
  1487         
       
  1488         else:
  1291         else:
  1489             raise AttributeError("'%s' can't have an attribute '%s'." % (self.__class__.__name__, name))
  1292             raise AttributeError("'%s' can't have an attribute '%s'." % (self.__class__.__name__, name))
  1490         
  1293         
  1491     return setattrMethod
  1294     return setattrMethod
  1492 
       
  1493 """
       
  1494 Method that generate the method for generating the xml tree structure model by 
       
  1495 following the attributes list defined
       
  1496 """
       
  1497 def ComputeMultiplicity(name, infos):
       
  1498     if infos["minOccurs"] == 0:
       
  1499         if infos["maxOccurs"] == "unbounded":
       
  1500             return "(?:%s)*" % name
       
  1501         elif infos["maxOccurs"] == 1:
       
  1502             return "(?:%s)?" % name
       
  1503         else:
       
  1504             return "(?:%s){,%d}" % (name, infos["maxOccurs"])
       
  1505     elif infos["minOccurs"] == 1:
       
  1506         if infos["maxOccurs"] == "unbounded":
       
  1507             return "(?:%s)+" % name
       
  1508         elif infos["maxOccurs"] == 1:
       
  1509             return "(?:%s)" % name
       
  1510         else:
       
  1511             return "(?:%s){1,%d}" % (name, infos["maxOccurs"])
       
  1512     else:
       
  1513         if infos["maxOccurs"] == "unbounded":
       
  1514             return "(?:%s){%d,}" % (name, infos["minOccurs"], name)
       
  1515         else:
       
  1516             return "(?:%s){%d,%d}" % (name, infos["minOccurs"], 
       
  1517                                        infos["maxOccurs"])
       
  1518 
       
  1519 def GetStructure(classinfos):
       
  1520     elements = []
       
  1521     for element in classinfos["elements"]:
       
  1522         if element["type"] == ANY:
       
  1523             infos = element.copy()
       
  1524             infos["minOccurs"] = 0
       
  1525             elements.append(ComputeMultiplicity("#text |#cdata-section |\w* ", infos))
       
  1526         elif element["type"] == CHOICE:
       
  1527             choices = []
       
  1528             for infos in element["choices"]:
       
  1529                 if infos["type"] == "sequence":
       
  1530                     structure = "(?:%s)" % GetStructure(infos)
       
  1531                 else:
       
  1532                     structure = "%s " % infos["name"]
       
  1533                 choices.append(ComputeMultiplicity(structure, infos))
       
  1534             elements.append(ComputeMultiplicity("|".join(choices), element))
       
  1535         elif element["name"] == "content" and element["elmt_type"]["type"] == SIMPLETYPE:
       
  1536             elements.append("(?:#text |#cdata-section )?")
       
  1537         else:
       
  1538             elements.append(ComputeMultiplicity("%s " % element["name"], element))
       
  1539     if classinfos.get("order", True) or len(elements) == 0:
       
  1540         return "".join(elements)
       
  1541     else:
       
  1542         raise ValueError("XSD structure not yet supported!")
       
  1543 
       
  1544 def generateStructureMethod(classinfos):
       
  1545     def getStructureMethod(self):
       
  1546         structure = GetStructure(classinfos)
       
  1547         if classinfos.has_key("base"):
       
  1548             return classinfos["base"].getStructure(self) + structure
       
  1549         return structure
       
  1550     return getStructureMethod
       
  1551 
       
  1552 """
       
  1553 Method that generate the method for loading an xml tree by following the
       
  1554 attributes list defined
       
  1555 """
       
  1556 def generateLoadXMLTree(factory, classinfos):
       
  1557     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
       
  1558     elements = dict([(element["name"], element) for element in classinfos["elements"]])
       
  1559     
       
  1560     def loadXMLTreeMethod(self, tree, extras=[], derived=False):
       
  1561         self.extraAttrs = {}
       
  1562         self.compatibility(tree)
       
  1563         if not derived:
       
  1564             children_structure = ""
       
  1565             for node in tree.childNodes:
       
  1566                 if not (node.nodeName == "#text" and node.data.strip() == "") and node.nodeName != "#comment":
       
  1567                     children_structure += "%s " % node.nodeName
       
  1568             structure_pattern = self.getStructure()
       
  1569             if structure_pattern != "":
       
  1570                 structure_model = re.compile("(%s)$" % structure_pattern)
       
  1571                 result = structure_model.match(children_structure)
       
  1572                 if not result:
       
  1573                     raise ValueError("Invalid structure for \"%s\" children!." % tree.nodeName)
       
  1574         required_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "required"])
       
  1575         if classinfos.has_key("base"):
       
  1576             extras.extend([attr["name"] for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
       
  1577             classinfos["base"].loadXMLTree(self, tree, extras, True)
       
  1578         for attrname, attr in tree._attrs.iteritems():
       
  1579             if attributes.has_key(attrname):
       
  1580                 attributes[attrname]["attr_type"] = FindTypeInfos(factory, attributes[attrname]["attr_type"])
       
  1581                 object.__setattr__(self, attrname, attributes[attrname]["attr_type"]["extract"](attr))
       
  1582             elif not classinfos.has_key("base") and not attrname in extras and not self.extraAttrs.has_key(attrname):
       
  1583                 self.extraAttrs[attrname] = GetAttributeValue(attr)
       
  1584             required_attributes.pop(attrname, None)
       
  1585         if len(required_attributes) > 0:
       
  1586             raise ValueError("Required attributes %s missing for \"%s\" element!" % (", ".join(["\"%s\""%name for name in required_attributes]), tree.nodeName))
       
  1587         first = {}
       
  1588         for node in tree.childNodes:
       
  1589             name = node.nodeName
       
  1590             if name == "#text" and node.data.strip() == "" or name == "#comment":
       
  1591                 continue
       
  1592             elif elements.has_key(name):
       
  1593                 elements[name]["elmt_type"] = FindTypeInfos(factory, elements[name]["elmt_type"])
       
  1594                 if elements[name]["maxOccurs"] == "unbounded" or elements[name]["maxOccurs"] > 1:
       
  1595                     if first.get(name, True):
       
  1596                         object.__setattr__(self, name, [elements[name]["elmt_type"]["extract"](node)])
       
  1597                         first[name] = False
       
  1598                     else:
       
  1599                         getattr(self, name).append(elements[name]["elmt_type"]["extract"](node))
       
  1600                 else:
       
  1601                     object.__setattr__(self, name, elements[name]["elmt_type"]["extract"](node))
       
  1602             elif elements.has_key("text"):
       
  1603                 if elements["text"]["maxOccurs"] == "unbounded" or elements["text"]["maxOccurs"] > 1:
       
  1604                     if first.get("text", True):
       
  1605                         object.__setattr__(self, "text", [elements["text"]["elmt_type"]["extract"](node)])
       
  1606                         first["text"] = False
       
  1607                     else:
       
  1608                         getattr(self, "text").append(elements["text"]["elmt_type"]["extract"](node))
       
  1609                 else:
       
  1610                     object.__setattr__(self, "text", elements["text"]["elmt_type"]["extract"](node))
       
  1611             elif elements.has_key("content"):
       
  1612                 if name in ["#cdata-section", "#text"]:
       
  1613                     if elements["content"]["elmt_type"]["type"] == SIMPLETYPE:
       
  1614                         object.__setattr__(self, "content", elements["content"]["elmt_type"]["extract"](node.data, False))
       
  1615                 else:
       
  1616                     content = getattr(self, "content")
       
  1617                     if elements["content"]["maxOccurs"] == "unbounded" or elements["content"]["maxOccurs"] > 1:
       
  1618                         if first.get("content", True):
       
  1619                             object.__setattr__(self, "content", [elements["content"]["elmt_type"]["extract"](node, None)])
       
  1620                             first["content"] = False
       
  1621                         else:
       
  1622                             content.append(elements["content"]["elmt_type"]["extract"](node, content))
       
  1623                     else:
       
  1624                         object.__setattr__(self, "content", elements["content"]["elmt_type"]["extract"](node, content))
       
  1625     return loadXMLTreeMethod
       
  1626         
       
  1627 
       
  1628 """
       
  1629 Method that generates the method for generating an xml text by following the
       
  1630 attributes list defined
       
  1631 """
       
  1632 def generateGenerateXMLText(factory, classinfos):
       
  1633     def generateXMLTextMethod(self, name, indent=0, extras={}, derived=False):
       
  1634         ind1, ind2 = getIndent(indent, name)
       
  1635         if not derived:
       
  1636             text = ind1 + u'<%s' % name
       
  1637         else:
       
  1638             text = u''
       
  1639         
       
  1640         first = True
       
  1641         
       
  1642         if not classinfos.has_key("base"):
       
  1643             extras.update(self.extraAttrs)
       
  1644             for attr, value in extras.iteritems():
       
  1645                 if not first and not self.singleLineAttributes:
       
  1646                     text += u'\n%s' % (ind2)
       
  1647                 text += u' %s=%s' % (attr, quoteattr(value))
       
  1648                 first = False
       
  1649             extras.clear()
       
  1650         for attr in classinfos["attributes"]:
       
  1651             if attr["use"] != "prohibited":
       
  1652                 attr["attr_type"] = FindTypeInfos(factory, attr["attr_type"])
       
  1653                 value = getattr(self, attr["name"], None)
       
  1654                 if value != None:
       
  1655                     computed_value = attr["attr_type"]["generate"](value)
       
  1656                 else:
       
  1657                     computed_value = None
       
  1658                 if attr["use"] != "optional" or (value != None and \
       
  1659                    computed_value != attr.get("default", attr["attr_type"]["generate"](attr["attr_type"]["initial"]()))):
       
  1660                     if classinfos.has_key("base"):
       
  1661                         extras[attr["name"]] = computed_value
       
  1662                     else:
       
  1663                         if not first and not self.singleLineAttributes:
       
  1664                             text += u'\n%s' % (ind2)
       
  1665                         text += ' %s=%s' % (attr["name"], quoteattr(computed_value))
       
  1666                     first = False
       
  1667         if classinfos.has_key("base"):
       
  1668             first, new_text = classinfos["base"].generateXMLText(self, name, indent, extras, True)
       
  1669             text += new_text
       
  1670         else:
       
  1671             first = True
       
  1672         for element in classinfos["elements"]:
       
  1673             element["elmt_type"] = FindTypeInfos(factory, element["elmt_type"])
       
  1674             value = getattr(self, element["name"], None)
       
  1675             if element["minOccurs"] == 0 and element["maxOccurs"] == 1:
       
  1676                 if value is not None:
       
  1677                     if first:
       
  1678                         text += u'>\n'
       
  1679                         first = False
       
  1680                     text += element["elmt_type"]["generate"](value, element["name"], indent + 1)
       
  1681             elif element["minOccurs"] == 1 and element["maxOccurs"] == 1:
       
  1682                 if first:
       
  1683                     text += u'>\n'
       
  1684                     first = False
       
  1685                 if element["name"] == "content" and element["elmt_type"]["type"] == SIMPLETYPE:
       
  1686                     text += element["elmt_type"]["generate"](value)
       
  1687                 else:
       
  1688                     text += element["elmt_type"]["generate"](value, element["name"], indent + 1)
       
  1689             else:
       
  1690                 if first and len(value) > 0:
       
  1691                     text += u'>\n'
       
  1692                     first = False
       
  1693                 for item in value:
       
  1694                     text += element["elmt_type"]["generate"](item, element["name"], indent + 1)
       
  1695         if not derived:
       
  1696             if first:
       
  1697                 text += u'/>\n'
       
  1698             else:
       
  1699                 text += ind1 + u'</%s>\n' % (name)
       
  1700             return text
       
  1701         else:
       
  1702             return first, text
       
  1703     return generateXMLTextMethod
       
  1704 
  1295 
  1705 def gettypeinfos(name, facets):
  1296 def gettypeinfos(name, facets):
  1706     if facets.has_key("enumeration") and facets["enumeration"][0] is not None:
  1297     if facets.has_key("enumeration") and facets["enumeration"][0] is not None:
  1707         return facets["enumeration"][0]
  1298         return facets["enumeration"][0]
  1708     elif facets.has_key("maxInclusive"):
  1299     elif facets.has_key("maxInclusive"):
  1868 """
  1459 """
  1869 Methods that generates the different methods for setting and getting the attributes
  1460 Methods that generates the different methods for setting and getting the attributes
  1870 """
  1461 """
  1871 def generateInitMethod(factory, classinfos):
  1462 def generateInitMethod(factory, classinfos):
  1872     def initMethod(self):
  1463     def initMethod(self):
  1873         self.extraAttrs = {}
       
  1874         if classinfos.has_key("base"):
  1464         if classinfos.has_key("base"):
  1875             classinfos["base"].init(self)
  1465             classinfos["base"].init(self)
  1876         for attribute in classinfos["attributes"]:
  1466         for attribute in classinfos["attributes"]:
  1877             attribute["attr_type"] = FindTypeInfos(factory, attribute["attr_type"])
  1467             attribute["attr_type"] = FindTypeInfos(factory, attribute["attr_type"])
  1878             if attribute["use"] == "required":
  1468             if attribute["use"] == "required":