xmlclass/xmlclass.py
changeset 592 89ff2738ef20
parent 565 94c11207aa6f
child 593 34c3569042db
equal deleted inserted replaced
591:4d6719c51f05 592:89ff2738ef20
    20 #
    20 #
    21 #You should have received a copy of the GNU General Public
    21 #You should have received a copy of the GNU General Public
    22 #License along with this library; if not, write to the Free Software
    22 #License along with this library; if not, write to the Free Software
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24 
    24 
    25 import sys
    25 import os, sys
    26 import re
    26 import re
    27 import datetime
    27 import datetime
    28 from types import *
    28 from types import *
    29 from xml.dom import minidom
    29 from xml.dom import minidom
    30 from xml.sax.saxutils import escape, unescape, quoteattr
    30 from xml.sax.saxutils import escape, unescape, quoteattr
    90 
    90 
    91     def dst(self, dt):
    91     def dst(self, dt):
    92         return ZERO
    92         return ZERO
    93 
    93 
    94 [SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE, 
    94 [SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE, 
    95  ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG
    95  ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG, CONSTRAINT,
    96 ] = range(12)
    96 ] = range(13)
    97 
    97 
    98 def NotSupportedYet(type):
    98 def NotSupportedYet(type):
    99     """
    99     """
   100     Function that generates a function that point out to user that datatype
   100     Function that generates a function that point out to user that datatype
   101     used is not supported by xmlclass yet
   101     used is not supported by xmlclass yet
   124     @return: data extracted as string
   124     @return: data extracted as string
   125     """
   125     """
   126     if not extract:
   126     if not extract:
   127         return attr
   127         return attr
   128     if len(attr.childNodes) == 1:
   128     if len(attr.childNodes) == 1:
   129         return unescape(attr.childNodes[0].data.encode())
   129         return unescape(attr.childNodes[0].data.encode("utf-8"))
   130     else:
   130     else:
   131         # content is a CDATA
   131         # content is a CDATA
   132         text = ""
   132         text = ""
   133         for node in attr.childNodes:
   133         for node in attr.childNodes:
   134             if node.nodeName != "#text":
   134             if node.nodeName != "#text":
   135                 text += node.data.encode()
   135                 text += node.data.encode("utf-8")
   136         return text
   136         return text
   137 
   137 
   138 
   138 
   139 def GetNormalizedString(attr, extract=True):
   139 def GetNormalizedString(attr, extract=True):
   140     """
   140     """
   530                 raise ValueError("\"%s\" isn't a valid value for %s!" % \
   530                 raise ValueError("\"%s\" isn't a valid value for %s!" % \
   531                                  (value, type))
   531                                  (value, type))
   532         return values
   532         return values
   533     return GetModelNameList
   533     return GetModelNameList
   534 
   534 
   535 def GenerateAnyInfos():
   535 def GenerateAnyInfos(infos):
   536     def ExtractAny(tree):
   536     def ExtractAny(tree):
   537         return tree.data.encode("utf-8")
   537         if tree.nodeName == "#cdata-section":
       
   538             return tree.data.encode("utf-8")
       
   539         else:
       
   540             return tree
   538     
   541     
   539     def GenerateAny(value, name=None, indent=0):
   542     def GenerateAny(value, name=None, indent=0):
   540         try:
   543         if isinstance(value, (StringType, UnicodeType)):
   541             value = value.decode("utf-8")
   544             try:
   542         except:
   545                 value = value.decode("utf-8")
   543             pass
   546             except:
   544         return u'<![CDATA[%s]]>\n' % value
   547                 pass
       
   548             return u'<![CDATA[%s]]>\n' % value
       
   549         else:
       
   550             return value.toprettyxml(indent=" "*indent, encoding="utf-8")
   545         
   551         
   546     return {
   552     return {
   547         "type": COMPLEXTYPE, 
   553         "type": COMPLEXTYPE, 
   548         "extract": ExtractAny,
   554         "extract": ExtractAny,
   549         "generate": GenerateAny,
   555         "generate": GenerateAny,
   550         "initial": lambda: "",
   556         "initial": lambda: "",
   551         "check": lambda x: isinstance(x, (StringType, UnicodeType))
   557         "check": lambda x: isinstance(x, (StringType, UnicodeType, minidom.Node))
   552     }
   558     }
   553 
   559 
   554 def GenerateTagInfos(name):
   560 def GenerateTagInfos(name):
   555     def ExtractTag(tree):
   561     def ExtractTag(tree):
   556         if len(tree._attrs) > 0:
   562         if len(tree._attrs) > 0:
   571         "extract": ExtractTag,
   577         "extract": ExtractTag,
   572         "generate": GenerateTag,
   578         "generate": GenerateTag,
   573         "initial": lambda: None,
   579         "initial": lambda: None,
   574         "check": lambda x: x == None
   580         "check": lambda x: x == None
   575     }
   581     }
       
   582 
       
   583 def FindTypeInfos(factory, infos):
       
   584     if isinstance(infos, (UnicodeType, StringType)):
       
   585         namespace, name = DecomposeQualifiedName(infos)
       
   586         return factory.GetQualifiedNameInfos(name, namespace)
       
   587     return infos
   576     
   588     
   577 def GenerateContentInfos(factory, choices):
   589 def GetElementInitialValue(factory, infos):
       
   590     infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
       
   591     if infos["minOccurs"] == 0 and infos["maxOccurs"] == 1:
       
   592         if infos.has_key("default"):
       
   593             return infos["elmt_type"]["extract"](infos["default"], False)
       
   594         else:
       
   595             return None
       
   596     elif infos["minOccurs"] == 1 and infos["maxOccurs"] == 1:
       
   597         return infos["elmt_type"]["initial"]()
       
   598     else:
       
   599         return [infos["elmt_type"]["initial"]() for i in xrange(infos["minOccurs"])]
       
   600 
       
   601 def HandleError(message, raise_exception):
       
   602     if raise_exception:
       
   603         raise ValueError(message)
       
   604     return False
       
   605 
       
   606 def CheckElementValue(factory, name, infos, value, raise_exception=True):
       
   607     infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
       
   608     if value is None and raise_exception:
       
   609         if not (infos["minOccurs"] == 0 and infos["maxOccurs"] == 1):
       
   610             return HandleError("Attribute '%s' isn't optional." % name, raise_exception)
       
   611     elif infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
       
   612         if not isinstance(value, ListType):
       
   613             return HandleError("Attribute '%s' must be a list." % name, raise_exception)
       
   614         if len(value) < infos["minOccurs"] or infos["maxOccurs"] != "unbounded" and len(value) > infos["maxOccurs"]:
       
   615             return HandleError("List out of bounds for attribute '%s'." % name, raise_exception)
       
   616         if not reduce(lambda x, y: x and y, map(infos["elmt_type"]["check"], value), True):
       
   617             return HandleError("Attribute '%s' must be a list of valid elements." % name, raise_exception)
       
   618     elif infos.has_key("fixed") and value != infos["fixed"]:
       
   619         return HandleError("Value of attribute '%s' can only be '%s'." % (name, str(infos["fixed"])), raise_exception)
       
   620     else:
       
   621         return infos["elmt_type"]["check"](value)
       
   622     return True
       
   623 
       
   624 def GetContentInfos(name, choices):
       
   625     for choice_infos in choices:
       
   626         if choices_infos["type"] == "sequence":
       
   627             for element_infos in choices_infos["elements"]:
       
   628                 if element_infos["type"] == CHOICE:
       
   629                     if GetContentInfos(name, element_infos["choices"]):
       
   630                         return choices_infos
       
   631                 elif element_infos["name"] == name:
       
   632                     return choices_infos
       
   633         elif choice_infos["name"] == name:
       
   634             return choices_infos
       
   635     return None
       
   636 
       
   637 def ComputeContentChoices(factory, name, infos):
       
   638     choices = []
       
   639     for choice in infos["choices"]:
       
   640         if choice["type"] == "sequence":
       
   641             choice["name"] = "sequence"
       
   642             for sequence_element in choice["elements"]:
       
   643                 if sequence_element["type"] != CHOICE:
       
   644                     element_infos = factory.ExtractTypeInfos(sequence_element["name"], name, sequence_element["elmt_type"])
       
   645                     if element_infos is not None:
       
   646                         sequence_element["elmt_type"] = element_infos
       
   647         elif choice["elmt_type"] == "tag":
       
   648             choice["elmt_type"] = GenerateTagInfos(choice["name"])
       
   649         else:
       
   650             choice_infos = factory.ExtractTypeInfos(choice["name"], name, choice["elmt_type"])
       
   651             if choice_infos is not None:
       
   652                 choice["elmt_type"] = choice_infos
       
   653         choices.append((choice["name"], choice))
       
   654     return choices
       
   655 
       
   656 def ExtractContentElement(factory, tree, infos, content):
       
   657     infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
       
   658     if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
       
   659         if isinstance(content, ListType) and len(content) > 0 and \
       
   660            content[-1]["name"] == tree.nodeName:
       
   661             content_item = content.pop(-1)
       
   662             content_item["value"].append(infos["elmt_type"]["extract"](tree))
       
   663             return content_item
       
   664         elif not isinstance(content, ListType) and \
       
   665              content is not None and \
       
   666              content["name"] == tree.nodeName:
       
   667             return {"name": tree.nodeName, 
       
   668                     "value": content["value"] + [infos["elmt_type"]["extract"](tree)]}
       
   669         else:
       
   670             return {"name": tree.nodeName, 
       
   671                     "value": [infos["elmt_type"]["extract"](tree)]}
       
   672     else:
       
   673         return {"name": tree.nodeName, 
       
   674                 "value": infos["elmt_type"]["extract"](tree)}
       
   675 
       
   676 def GenerateContentInfos(factory, name, choices):
       
   677     choices_dict = {}
       
   678     for choice_name, infos in choices:
       
   679         if choice_name == "sequence":
       
   680             for element in infos["elements"]:
       
   681                 if element["type"] == CHOICE:
       
   682                     element["elmt_type"] = GenerateContentInfos(factory, name, ComputeContentChoices(factory, name, element))
       
   683                 elif choices_dict.has_key(element["name"]):
       
   684                     raise ValueError("'%s' element defined two times in choice" % choice_name)
       
   685                 else:
       
   686                     choices_dict[element["name"]] = infos
       
   687         else:
       
   688             if choices_dict.has_key(choice_name):
       
   689                 raise ValueError("'%s' element defined two times in choice" % choice_name)
       
   690             choices_dict[choice_name] = infos
       
   691     
   578     def GetContentInitial():
   692     def GetContentInitial():
   579         content_name, infos = choices[0]
   693         content_name, infos = choices[0]
   580         if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
   694         if content_name == "sequence":
   581             namespace, name = DecomposeQualifiedName(infos["elmt_type"])
   695             content_value = []
   582             infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
   696             for i in xrange(infos["minOccurs"]):
   583         if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
   697                 for element_infos in infos["elements"]:
   584             return {"name": content_name, 
   698                     value = GetElementInitialValue(factory, element_infos)
   585                     "value": map(infos["elmt_type"]["initial"], 
   699                     if value is not None:
   586                                  range(infos["minOccurs"]))}
   700                         if element_infos["type"] == CHOICE:
   587         else:
   701                             content_value.append(value)
   588             return {"name": content_name, 
   702                         else:
   589                     "value": infos["elmt_type"]["initial"]()}
   703                             content_value.append({"name": element_infos["name"], "value": value})
       
   704         else:
       
   705             content_value = GetElementInitialValue(factory, infos)
       
   706         return {"name": content_name, "value": content_value}
       
   707         
       
   708     def CheckContent(value):
       
   709         if value["name"] != "sequence":
       
   710             infos = choices_dict.get(value["name"], None)
       
   711             if infos is not None:
       
   712                 return CheckElementValue(factory, value["name"], infos, value["value"], False)
       
   713         elif len(value["value"]) > 0:
       
   714             infos = choices_dict.get(value["value"][0]["name"], None)
       
   715             if infos is None:
       
   716                 for choice_name, infos in choices:
       
   717                     if infos["type"] == "sequence":
       
   718                         for element_infos in infos["elements"]:
       
   719                             if element_infos["type"] == CHOICE:
       
   720                                 infos = GetContentInfos(value["value"][0]["name"], element_infos["choices"])
       
   721             if infos is not None:
       
   722                 sequence_number = 0
       
   723                 element_idx = 0
       
   724                 while element_idx < len(value["value"]):
       
   725                     for element_infos in infos["elements"]:
       
   726                         if element_infos["name"] == value["value"][element_idx]["name"]:
       
   727                             element_value = value["value"][element_idx]["value"]
       
   728                             element_idx += 1
       
   729                         else:
       
   730                             element_value = None
       
   731                         if not CheckElementValue(factory, element_infos["name"], element_infos, element_value, False):
       
   732                             raise ValueError("Invalid sequence value in attribute 'content'")
       
   733                     sequence_number += 1
       
   734                 if sequence_number < infos["minOccurs"] or infos["maxOccurs"] != "unbounded" and sequence_number > infos["maxOccurs"]:
       
   735                     raise ValueError("Invalid sequence value in attribute 'content'")
       
   736                 return True
       
   737         else:
       
   738             for element_name, infos in choices:
       
   739                 if element_name == "sequence":
       
   740                     required = 0
       
   741                     for element in infos["elements"]:
       
   742                         if element["minOccurs"] > 0:
       
   743                             required += 1
       
   744                     if required == 0:
       
   745                         return True
       
   746         return False
   590     
   747     
   591     def CheckContent(value):
       
   592         for content_name, infos in choices:
       
   593             if content_name == value["name"]:
       
   594                 if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
       
   595                     namespace, name = DecomposeQualifiedName(infos["elmt_type"])
       
   596                     infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
   597                 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
       
   598                     if isinstance(value["value"], ListType) and \
       
   599                        infos["minOccurs"] <= len(value["value"]) <= infos["maxOccurs"]:
       
   600                         return reduce(lambda x, y: x and y, 
       
   601                                       map(infos["elmt_type"]["check"], 
       
   602                                           value["value"]), 
       
   603                                       True)
       
   604                 else:
       
   605                     return infos["elmt_type"]["check"](value["value"])
       
   606         return False
       
   607         
       
   608     def ExtractContent(tree, content):
   748     def ExtractContent(tree, content):
   609         for content_name, infos in choices:
   749         infos = choices_dict.get(tree.nodeName, None)
   610             if content_name == tree.nodeName:
   750         if infos is not None:
   611                 if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
   751             if infos["name"] == "sequence":
   612                     namespace, name = DecomposeQualifiedName(infos["elmt_type"])
   752                 sequence_dict = dict([(element_infos["name"], element_infos) for element_infos in infos["elements"] if element_infos["type"] != CHOICE])
   613                     infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
   753                 element_infos = sequence_dict.get(tree.nodeName)
   614                 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
   754                 if content is not None and \
   615                     if isinstance(content, ListType) and len(content) > 0 and \
   755                    content["name"] == "sequence" and \
   616                        content[-1]["name"] == content_name:
   756                    len(content["value"]) > 0 and \
   617                         content_item = content.pop(-1)
   757                    choices_dict.get(content["value"][-1]["name"]) == infos:
   618                         content_item["value"].append(infos["elmt_type"]["extract"](tree))
   758                     return {"name": "sequence",
   619                         return content_item
   759                             "value": content["value"] + [ExtractContentElement(factory, tree, element_infos, content["value"][-1])]}
   620                     elif not isinstance(content, ListType) and \
   760                 else:
   621                          content is not None and \
   761                     return {"name": "sequence",
   622                          content["name"] == content_name:
   762                             "value": [ExtractContentElement(factory, tree, element_infos, None)]}
   623                         return {"name": content_name, 
   763             else:
   624                                 "value": content["value"] + \
   764                 return ExtractContentElement(factory, tree, infos, content)
   625                                          [infos["elmt_type"]["extract"](tree)]}
   765         else:
   626                     else:
   766             for choice_name, infos in choices:
   627                         return {"name": content_name, 
   767                 if infos["type"] == "sequence":
   628                                 "value": [infos["elmt_type"]["extract"](tree)]}
   768                     for element_infos in infos["elements"]:
   629                 else:
   769                         if element_infos["type"] == CHOICE:
   630                     return {"name": content_name, 
   770                             try:
   631                             "value": infos["elmt_type"]["extract"](tree)}
   771                                 if content is not None and \
       
   772                                     content["name"] == "sequence" and \
       
   773                                     len(content["value"]) > 0:
       
   774                                     return {"name": "sequence",
       
   775                                             "value": content["value"] + [element_infos["elmt_type"]["extract"](tree, content["value"][-1])]}
       
   776                                 else:
       
   777                                     return {"name": "sequence",
       
   778                                             "value": [element_infos["elmt_type"]["extract"](tree, None)]}
       
   779                             except:
       
   780                                 pass
   632         raise ValueError("Invalid element \"%s\" for content!" % tree.nodeName)
   781         raise ValueError("Invalid element \"%s\" for content!" % tree.nodeName)
   633     
   782     
   634     def GenerateContent(value, name=None, indent=0):
   783     def GenerateContent(value, name=None, indent=0):
   635         for content_name, infos in choices:
   784         text = ""
   636             if content_name == value["name"]:
   785         if value["name"] != "sequence":
   637                 if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
   786             infos = choices_dict.get(value["name"], None)
   638                     namespace, name = DecomposeQualifiedName(infos["elmt_type"])
   787             if infos is not None:
   639                     infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
   788                 infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
   640                 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
   789                 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1:
   641                     text = ""
       
   642                     for item in value["value"]:
   790                     for item in value["value"]:
   643                         text += infos["elmt_type"]["generate"](item, content_name, indent)
   791                         text += infos["elmt_type"]["generate"](item, value["name"], indent)
   644                     return text
   792                 else:
   645                 else:
   793                     text += infos["elmt_type"]["generate"](value["value"], value["name"], indent)
   646                     return infos["elmt_type"]["generate"](value["value"], content_name, indent)
   794         elif len(value["value"]) > 0:
   647         return ""
   795             infos = choices_dict.get(value["value"][0]["name"], None)
       
   796             if infos is None:
       
   797                 for choice_name, infos in choices:
       
   798                     if infos["type"] == "sequence":
       
   799                         for element_infos in infos["elements"]:
       
   800                             if element_infos["type"] == CHOICE:
       
   801                                 infos = GetContentInfos(value["value"][0]["name"], element_infos["choices"])
       
   802             if infos is not None:
       
   803                 sequence_dict = dict([(element_infos["name"], element_infos) for element_infos in infos["elements"]]) 
       
   804                 for element_value in value["value"]:
       
   805                     element_infos = sequence_dict.get(element_value["name"])
       
   806                     if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
       
   807                         for item in element_value["value"]:
       
   808                             text += element_infos["elmt_type"]["generate"](item, element_value["name"], indent)
       
   809                     else:
       
   810                         text += element_infos["elmt_type"]["generate"](element_value["value"], element_infos["name"], indent)
       
   811         return text
   648         
   812         
   649     return {
   813     return {
       
   814         "type": COMPLEXTYPE,
   650         "initial": GetContentInitial,
   815         "initial": GetContentInitial,
   651         "check": CheckContent,
   816         "check": CheckContent,
   652         "extract": ExtractContent,
   817         "extract": ExtractContent,
   653         "generate": GenerateContent
   818         "generate": GenerateContent
   654     }
   819     }
   705 """
   870 """
   706 Class that generate class from an XML Tree
   871 Class that generate class from an XML Tree
   707 """
   872 """
   708 class ClassFactory:
   873 class ClassFactory:
   709 
   874 
   710     def __init__(self, document, debug=False):
   875     def __init__(self, document, filepath=None, debug=False):
   711         self.Document = document
   876         self.Document = document
       
   877         if filepath is not None:
       
   878             self.BaseFolder, self.FileName = os.path.split(filepath)
       
   879         else:
       
   880             self.BaseFolder = self.FileName = None
   712         self.Debug = debug
   881         self.Debug = debug
   713         
   882         
   714         # Dictionary for stocking Classes and Types definitions created from
   883         # Dictionary for stocking Classes and Types definitions created from
   715         # the XML tree
   884         # the XML tree
   716         self.XMLClassDefinitions = {}
   885         self.XMLClassDefinitions = {}
   722         
   891         
   723         self.CurrentCompilations = []
   892         self.CurrentCompilations = []
   724         
   893         
   725         # Dictionaries for stocking Classes and Types generated
   894         # Dictionaries for stocking Classes and Types generated
   726         self.ComputeAfter = []
   895         self.ComputeAfter = []
   727         self.ComputedClasses = {}
   896         if self.FileName is not None:
       
   897             self.ComputedClasses = {self.FileName: {}}
       
   898         else:
       
   899             self.ComputedClasses = {}
   728         self.ComputedClassesInfos = {}
   900         self.ComputedClassesInfos = {}
   729         self.AlreadyComputed = {}
   901         self.AlreadyComputed = {}
   730 
   902 
   731     def GetQualifiedNameInfos(self, name, namespace=None, canbenone=False):
   903     def GetQualifiedNameInfos(self, name, namespace=None, canbenone=False):
   732         if namespace is None:
   904         if namespace is None:
   733             if self.Namespaces[self.SchemaNamespace].has_key(name):
   905             if self.Namespaces[self.SchemaNamespace].has_key(name):
   734                 return self.Namespaces[self.SchemaNamespace][name]
   906                 return self.Namespaces[self.SchemaNamespace][name]
   735             for space, elements in self.Namespaces.items():
   907             for space, elements in self.Namespaces.iteritems():
   736                 if space != self.SchemaNamespace and elements.has_key(name):
   908                 if space != self.SchemaNamespace and elements.has_key(name):
   737                     return elements[name]
   909                     return elements[name]
   738             parts = name.split("_", 1)
   910             parts = name.split("_", 1)
   739             if len(parts) > 1:
   911             if len(parts) > 1:
   740                 group = self.GetQualifiedNameInfos(parts[0], namespace)
   912                 group = self.GetQualifiedNameInfos(parts[0], namespace)
   844         return attrs
  1016         return attrs
   845 
  1017 
   846     def ReduceElements(self, elements, schema=False):
  1018     def ReduceElements(self, elements, schema=False):
   847         result = []
  1019         result = []
   848         for child_infos in elements:
  1020         for child_infos in elements:
   849             if child_infos[1].has_key("name") and schema:
  1021             if child_infos is not None:
   850                 self.CurrentCompilations.append(child_infos[1]["name"])
  1022                 if child_infos[1].has_key("name") and schema:
   851             namespace, name = DecomposeQualifiedName(child_infos[0])
  1023                     self.CurrentCompilations.append(child_infos[1]["name"])
   852             infos = self.GetQualifiedNameInfos(name, namespace)
  1024                 namespace, name = DecomposeQualifiedName(child_infos[0])
   853             if infos["type"] != SYNTAXELEMENT:
  1025                 infos = self.GetQualifiedNameInfos(name, namespace)
   854                 raise ValueError("\"%s\" can't be a member child!" % name)
  1026                 if infos["type"] != SYNTAXELEMENT:
   855             result.append(infos["reduce"](self, child_infos[1], child_infos[2]))
  1027                     raise ValueError("\"%s\" can't be a member child!" % name)
   856             if child_infos[1].has_key("name") and schema:
  1028                 element = infos["reduce"](self, child_infos[1], child_infos[2])
   857                 self.CurrentCompilations.pop(-1)
  1029                 if element is not None:
       
  1030                     result.append(element)
       
  1031                 if child_infos[1].has_key("name") and schema:
       
  1032                     self.CurrentCompilations.pop(-1)
   858         annotations = []
  1033         annotations = []
   859         children = []
  1034         children = []
   860         for element in result:
  1035         for element in result:
   861             if element["type"] == "annotation":
  1036             if element["type"] == "annotation":
   862                 annotations.append(element)
  1037                 annotations.append(element)
   946                 self.AlreadyComputed[classname].IsBaseClass = baseclass
  1121                 self.AlreadyComputed[classname].IsBaseClass = baseclass
   947             return self.ComputedClassesInfos.get(classname, None)
  1122             return self.ComputedClassesInfos.get(classname, None)
   948         
  1123         
   949         # If base classes haven't been generated
  1124         # If base classes haven't been generated
   950         bases = []
  1125         bases = []
   951         if classinfos.has_key("base"):
  1126         base_infos = classinfos.get("base", None)
   952             result = self.ExtractTypeInfos("base", name, classinfos["base"])
  1127         if base_infos is not None:
       
  1128             result = self.ExtractTypeInfos("base", name, base_infos)
   953             if result is None:
  1129             if result is None:
   954                 namespace, base_name = DecomposeQualifiedName(classinfos["base"])                
  1130                 namespace, base_name = DecomposeQualifiedName(base_infos)                
   955                 if self.AlreadyComputed.get(base_name, False):
  1131                 if self.AlreadyComputed.get(base_name, False):
   956                     self.ComputeAfter.append((name, parent, classinfos))
  1132                     self.ComputeAfter.append((name, parent, classinfos))
   957                     if self.TargetNamespace is not None:
  1133                     if self.TargetNamespace is not None:
   958                         return "%s:%s" % (self.TargetNamespace, classname)
  1134                         return "%s:%s" % (self.TargetNamespace, classname)
   959                     else:
  1135                     else:
   960                         return classname
  1136                         return classname
   961             elif result is not None:
  1137             elif result is not None:
   962                 classinfos["base"] = self.ComputedClasses[result["name"]]
  1138                 if self.FileName is not None:
   963                 bases.append(self.ComputedClasses[result["name"]])
  1139                     classinfos["base"] = self.ComputedClasses[self.FileName].get(result["name"], None)
       
  1140                     if classinfos["base"] is None:
       
  1141                         for filename, classes in self.ComputedClasses.iteritems():
       
  1142                             if filename != self.FileName:
       
  1143                                 classinfos["base"] = classes.get(result["name"], None)
       
  1144                                 if classinfos["base"] is not None:
       
  1145                                     break
       
  1146                 else:
       
  1147                     classinfos["base"] = self.ComputedClasses.get(result["name"], None)
       
  1148                 if classinfos["base"] is None:
       
  1149                     raise ValueError("No class found for base type")
       
  1150                 bases.append(classinfos["base"])
   964         bases.append(object)
  1151         bases.append(object)
   965         bases = tuple(bases)
  1152         bases = tuple(bases)
   966         classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass}
  1153         classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass}
   967         
  1154         
   968         self.AlreadyComputed[classname] = True
  1155         self.AlreadyComputed[classname] = True
   982                 classmembers["set%s"%attrname] = generateSetMethod(attrname)
  1169                 classmembers["set%s"%attrname] = generateSetMethod(attrname)
   983                 classmembers["get%s"%attrname] = generateGetMethod(attrname)
  1170                 classmembers["get%s"%attrname] = generateGetMethod(attrname)
   984             else:
  1171             else:
   985                 raise ValueError("\"%s\" type unrecognized!" % attribute["attr_type"])
  1172                 raise ValueError("\"%s\" type unrecognized!" % attribute["attr_type"])
   986             attribute["attr_type"] = infos
  1173             attribute["attr_type"] = infos
   987             
  1174         
   988         for element in classinfos["elements"]:
  1175         for element in classinfos["elements"]:
   989             if element["type"] == CHOICE:
  1176             if element["type"] == CHOICE:
   990                 elmtname = element["name"]
  1177                 elmtname = element["name"]
   991                 choices = []
  1178                 choices = ComputeContentChoices(self, name, element)
   992                 for choice in element["choices"]:
       
   993                     if choice["elmt_type"] == "tag":
       
   994                         choice["elmt_type"] = GenerateTagInfos(choice["name"])
       
   995                     else:
       
   996                         infos = self.ExtractTypeInfos(choice["name"], name, choice["elmt_type"])
       
   997                         if infos is not None:
       
   998                             choice["elmt_type"] = infos
       
   999                     choices.append((choice["name"], choice))
       
  1000                 classmembers["get%schoices"%elmtname] = generateGetChoicesMethod(element["choices"])
  1179                 classmembers["get%schoices"%elmtname] = generateGetChoicesMethod(element["choices"])
  1001                 if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1:
  1180                 if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1:
  1002                     classmembers["append%sbytype" % elmtname] = generateAppendChoiceByTypeMethod(element["maxOccurs"], self, element["choices"])
  1181                     classmembers["append%sbytype" % elmtname] = generateAppendChoiceByTypeMethod(element["maxOccurs"], self, element["choices"])
  1003                     classmembers["insert%sbytype" % elmtname] = generateInsertChoiceByTypeMethod(element["maxOccurs"], self, element["choices"])
  1182                     classmembers["insert%sbytype" % elmtname] = generateInsertChoiceByTypeMethod(element["maxOccurs"], self, element["choices"])
  1004                 else:
  1183                 else:
  1005                     classmembers["set%sbytype" % elmtname] = generateSetChoiceByTypeMethod(self, element["choices"])
  1184                     classmembers["set%sbytype" % elmtname] = generateSetChoiceByTypeMethod(self, element["choices"])
  1006                 infos = GenerateContentInfos(self, choices)
  1185                 infos = GenerateContentInfos(self, name, choices)
  1007             elif element["type"] == ANY:
  1186             elif element["type"] == ANY:
  1008                 elmtname = element["name"] = "text"
  1187                 elmtname = element["name"] = "text"
  1009                 element["minOccurs"] = element["maxOccurs"] = 1
  1188                 element["minOccurs"] = element["maxOccurs"] = 1
  1010                 infos = GenerateAnyInfos()
  1189                 infos = GenerateAnyInfos(element)
  1011             else:
  1190             else:
  1012                 elmtname = element["name"]
  1191                 elmtname = element["name"]
  1013                 infos = self.ExtractTypeInfos(element["name"], name, element["elmt_type"])
  1192                 infos = self.ExtractTypeInfos(element["name"], name, element["elmt_type"])
  1014             if infos is not None:
  1193             if infos is not None:
  1015                 element["elmt_type"] = infos
  1194                 element["elmt_type"] = infos
  1048                 "check": generateClassCheckFunction(class_definition),
  1227                 "check": generateClassCheckFunction(class_definition),
  1049                 "initial": generateClassCreateFunction(class_definition),
  1228                 "initial": generateClassCreateFunction(class_definition),
  1050                 "extract": generateClassExtractFunction(class_definition),
  1229                 "extract": generateClassExtractFunction(class_definition),
  1051                 "generate": class_definition.generateXMLText}
  1230                 "generate": class_definition.generateXMLText}
  1052         
  1231         
  1053         self.ComputedClasses[classname] = class_definition
  1232         if self.FileName is not None:
       
  1233             self.ComputedClasses[self.FileName][classname] = class_definition
       
  1234         else:
       
  1235             self.ComputedClasses[classname] = class_definition
  1054         self.ComputedClassesInfos[classname] = class_infos
  1236         self.ComputedClassesInfos[classname] = class_infos
  1055         
  1237         
  1056         return class_infos
  1238         return class_infos
  1057 
  1239 
  1058     """
  1240     """
  1059     Methods that print the classes generated
  1241     Methods that print the classes generated
  1060     """
  1242     """
  1061     def PrintClasses(self):
  1243     def PrintClasses(self):
  1062         items = self.ComputedClasses.items()
  1244         items = self.ComputedClasses.items()
  1063         items.sort()
  1245         items.sort()
  1064         for classname, xmlclass in items:
  1246         if self.FileName is not None:
  1065             print "%s : %s" % (classname, str(xmlclass))
  1247             for filename, classes in items:
       
  1248                 print "File '%s':" % filename
       
  1249                 class_items = classes.items()
       
  1250                 class_items.sort()
       
  1251                 for classname, xmlclass in class_items:
       
  1252                     print "%s: %s" % (classname, str(xmlclass))
       
  1253         else:
       
  1254             for classname, xmlclass in items:
       
  1255                 print "%s: %s" % (classname, str(xmlclass))
  1066         
  1256         
  1067     def PrintClassNames(self):
  1257     def PrintClassNames(self):
  1068         classnames = self.XMLClassDefinitions.keys()
  1258         classnames = self.XMLClassDefinitions.keys()
  1069         classnames.sort()
  1259         classnames.sort()
  1070         for classname in classnames:
  1260         for classname in classnames:
  1105     optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
  1295     optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
  1106     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1296     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1107     
  1297     
  1108     def setattrMethod(self, name, value):
  1298     def setattrMethod(self, name, value):
  1109         if attributes.has_key(name):
  1299         if attributes.has_key(name):
  1110             if isinstance(attributes[name]["attr_type"], (UnicodeType, StringType)):
  1300             attributes[name]["attr_type"] = FindTypeInfos(factory, attributes[name]["attr_type"])
  1111                 namespace, name = DecomposeQualifiedName(infos)
       
  1112                 attributes[name]["attr_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1113             if value is None:
  1301             if value is None:
  1114                 if optional_attributes.get(name, False):
  1302                 if optional_attributes.get(name, False):
  1115                     return object.__setattr__(self, name, None)
  1303                     return object.__setattr__(self, name, None)
  1116                 else:
  1304                 else:
  1117                     raise ValueError("Attribute '%s' isn't optional." % name)
  1305                     raise ValueError("Attribute '%s' isn't optional." % name)
  1120             elif attributes[name]["attr_type"]["check"](value):
  1308             elif attributes[name]["attr_type"]["check"](value):
  1121                 return object.__setattr__(self, name, value)
  1309                 return object.__setattr__(self, name, value)
  1122             else:
  1310             else:
  1123                 raise ValueError("Invalid value for attribute '%s'." % (name))
  1311                 raise ValueError("Invalid value for attribute '%s'." % (name))
  1124         elif elements.has_key(name):
  1312         elif elements.has_key(name):
  1125             if isinstance(elements[name]["elmt_type"], (UnicodeType, StringType)):
  1313             if CheckElementValue(factory, name, elements[name], value):
  1126                 namespace, name = DecomposeQualifiedName(infos)
       
  1127                 elements[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1128             if value is None:
       
  1129                 if elements[name]["minOccurs"] == 0 and elements[name]["maxOccurs"] == 1:
       
  1130                     return object.__setattr__(self, name, None)
       
  1131                 else:
       
  1132                     raise ValueError("Attribute '%s' isn't optional." % name)
       
  1133             elif elements[name]["maxOccurs"] == "unbounded" or elements[name]["maxOccurs"] > 1:
       
  1134                 if isinstance(value, ListType) and elements[name]["minOccurs"] <= len(value) <= elements[name]["maxOccurs"]:
       
  1135                     if reduce(lambda x, y: x and y, map(elements[name]["elmt_type"]["check"], value), True):
       
  1136                         return object.__setattr__(self, name, value)
       
  1137                 raise ValueError, "Attribute '%s' must be a list of valid elements."%name
       
  1138             elif elements[name].has_key("fixed") and value != elements[name]["fixed"]:
       
  1139                 raise ValueError("Value of attribute '%s' can only be '%s'." % (name, str(elements[name]["fixed"])))
       
  1140             elif elements[name]["elmt_type"]["check"](value):
       
  1141                 return object.__setattr__(self, name, value)
  1314                 return object.__setattr__(self, name, value)
  1142             else:
  1315             else:
  1143                 raise ValueError("Invalid value for attribute '%s'." % (name))
  1316                 raise ValueError("Invalid value for attribute '%s'." % (name))
  1144         elif classinfos.has_key("base"):
  1317         elif classinfos.has_key("base"):
  1145             return classinfos["base"].__setattr__(self, name, value)
  1318             return classinfos["base"].__setattr__(self, name, value)
  1164             return "(?:%s){,%d}" % (name, infos["maxOccurs"])
  1337             return "(?:%s){,%d}" % (name, infos["maxOccurs"])
  1165     elif infos["minOccurs"] == 1:
  1338     elif infos["minOccurs"] == 1:
  1166         if infos["maxOccurs"] == "unbounded":
  1339         if infos["maxOccurs"] == "unbounded":
  1167             return "(?:%s)+" % name
  1340             return "(?:%s)+" % name
  1168         elif infos["maxOccurs"] == 1:
  1341         elif infos["maxOccurs"] == 1:
  1169             return name
  1342             return "(?:%s)" % name
  1170         else:
  1343         else:
  1171             return "(?:%s){1,%d}" % (name, infos["maxOccurs"])
  1344             return "(?:%s){1,%d}" % (name, infos["maxOccurs"])
  1172     else:
  1345     else:
  1173         if infos["maxOccurs"] == "unbounded":
  1346         if infos["maxOccurs"] == "unbounded":
  1174             return "(?:%s){%d,}" % (name, infos["minOccurs"], name)
  1347             return "(?:%s){%d,}" % (name, infos["minOccurs"], name)
  1175         else:
  1348         else:
  1176             return "(?:%s){%d,%d}" % (name, infos["minOccurs"], 
  1349             return "(?:%s){%d,%d}" % (name, infos["minOccurs"], 
  1177                                        infos["maxOccurs"])
  1350                                        infos["maxOccurs"])
  1178 
  1351 
  1179 def generateStructureMethod(classinfos):
  1352 def GetStructure(classinfos):
  1180     elements = []
  1353     elements = []
  1181     for element in classinfos["elements"]:
  1354     for element in classinfos["elements"]:
  1182         if element["type"] == ANY:
  1355         if element["type"] == ANY:
  1183             elements.append(ComputeMultiplicity("(?:#cdata-section )?", element))
  1356             elements.append(ComputeMultiplicity("#cdata-section |\w* ", element))
  1184         elif element["type"] == CHOICE:
  1357         elif element["type"] == CHOICE:
  1185             elements.append(ComputeMultiplicity(
  1358             choices = []
  1186                 "|".join([ComputeMultiplicity("%s " % infos["name"], infos) for infos in element["choices"]]), 
  1359             for infos in element["choices"]:
  1187                 element))
  1360                 if infos["type"] == "sequence":
       
  1361                     structure = "(?:%s)" % GetStructure(infos)
       
  1362                 else:
       
  1363                     structure = "%s " % infos["name"]
       
  1364                 choices.append(ComputeMultiplicity(structure, infos))
       
  1365             elements.append(ComputeMultiplicity("|".join(choices), element))
       
  1366         elif element["name"] == "content" and element["elmt_type"]["type"] == SIMPLETYPE:
       
  1367             elements.append("(?:#cdata-section )?")
  1188         else:
  1368         else:
  1189             elements.append(ComputeMultiplicity("%s " % element["name"], element))
  1369             elements.append(ComputeMultiplicity("%s " % element["name"], element))
  1190     if classinfos.get("order", True) or len(elements) == 0:
  1370     if classinfos.get("order", True) or len(elements) == 0:
  1191         structure = "".join(elements)
  1371         return "".join(elements)
  1192     else:
  1372     else:
  1193         raise ValueError("XSD structure not yet supported!")
  1373         raise ValueError("XSD structure not yet supported!")
  1194     
  1374 
       
  1375 def generateStructureMethod(classinfos):
  1195     def getStructureMethod(self):
  1376     def getStructureMethod(self):
       
  1377         structure = GetStructure(classinfos)
  1196         if classinfos.has_key("base"):
  1378         if classinfos.has_key("base"):
  1197             return classinfos["base"].getStructure(self) + structure
  1379             return classinfos["base"].getStructure(self) + structure
  1198         return structure
  1380         return structure
  1199     return getStructureMethod
  1381     return getStructureMethod
  1200 
  1382 
  1211         if not derived:
  1393         if not derived:
  1212             children_structure = ""
  1394             children_structure = ""
  1213             for node in tree.childNodes:
  1395             for node in tree.childNodes:
  1214                 if node.nodeName not in ["#comment", "#text"]:
  1396                 if node.nodeName not in ["#comment", "#text"]:
  1215                     children_structure += "%s " % node.nodeName
  1397                     children_structure += "%s " % node.nodeName
  1216             structure_model = re.compile("(%s)$" % self.getStructure())
  1398             structure_pattern = self.getStructure()
  1217             result = structure_model.match(children_structure)
  1399             if structure_pattern != "":
  1218             if not result:
  1400                 structure_model = re.compile("(%s)$" % structure_pattern)
  1219                 raise ValueError("Invalid structure for \"%s\" children!." % tree.nodeName)
  1401                 result = structure_model.match(children_structure)
       
  1402                 if not result:
       
  1403                     raise ValueError("Invalid structure for \"%s\" children!." % tree.nodeName)
  1220         required_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "required"])
  1404         required_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "required"])
  1221         if classinfos.has_key("base"):
  1405         if classinfos.has_key("base"):
  1222             extras.extend([attr["name"] for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1406             extras.extend([attr["name"] for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1223             classinfos["base"].loadXMLTree(self, tree, extras, True)
  1407             classinfos["base"].loadXMLTree(self, tree, extras, True)
  1224         for attrname, attr in tree._attrs.iteritems():
  1408         for attrname, attr in tree._attrs.iteritems():
  1225             if attributes.has_key(attrname):
  1409             if attributes.has_key(attrname):
  1226                 if isinstance(attributes[attrname]["attr_type"], (UnicodeType, StringType)):
  1410                 attributes[attrname]["attr_type"] = FindTypeInfos(factory, attributes[attrname]["attr_type"])
  1227                     namespace, name = DecomposeQualifiedName(infos)
  1411                 object.__setattr__(self, attrname, attributes[attrname]["attr_type"]["extract"](attr))
  1228                     attributes[attrname]["attr_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1229                 setattr(self, attrname, attributes[attrname]["attr_type"]["extract"](attr))
       
  1230             elif not classinfos.has_key("base") and attrname not in extras:
  1412             elif not classinfos.has_key("base") and attrname not in extras:
  1231                 raise ValueError("Invalid attribute \"%s\" for \"%s\" element!" % (attrname, tree.nodeName))
  1413                 raise ValueError("Invalid attribute \"%s\" for \"%s\" element!" % (attrname, tree.nodeName))
  1232             required_attributes.pop(attrname, None)
  1414             required_attributes.pop(attrname, None)
  1233         if len(required_attributes) > 0:
  1415         if len(required_attributes) > 0:
  1234             raise ValueError("Required attributes %s missing for \"%s\" element!" % (", ".join(["\"%s\""%name for name in required_attributes]), tree.nodeName))
  1416             raise ValueError("Required attributes %s missing for \"%s\" element!" % (", ".join(["\"%s\""%name for name in required_attributes]), tree.nodeName))
  1235         first = {}
  1417         first = {}
  1236         for node in tree.childNodes:
  1418         for node in tree.childNodes:
  1237             name = node.nodeName
  1419             name = node.nodeName
  1238             if name in ["#text", "#comment"]:
  1420             if name in ["#text", "#comment"]:
  1239                 continue
  1421                 continue
  1240             if elements.has_key(name):
  1422             elif elements.has_key(name):
  1241                 if isinstance(elements[name]["elmt_type"], (UnicodeType, StringType)):
  1423                 elements[name]["elmt_type"] = FindTypeInfos(factory, elements[name]["elmt_type"])
  1242                     namespace, name = DecomposeQualifiedName(infos)
       
  1243                     elements[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1244                 if elements[name]["maxOccurs"] == "unbounded" or elements[name]["maxOccurs"] > 1:
  1424                 if elements[name]["maxOccurs"] == "unbounded" or elements[name]["maxOccurs"] > 1:
  1245                     if first.get(name, True):
  1425                     if first.get(name, True):
  1246                         setattr(self, name, [elements[name]["elmt_type"]["extract"](node)])
  1426                         object.__setattr__(self, name, [elements[name]["elmt_type"]["extract"](node)])
  1247                         first[name] = False
  1427                         first[name] = False
  1248                     else:
  1428                     else:
  1249                         getattr(self, name).append(elements[name]["elmt_type"]["extract"](node))
  1429                         getattr(self, name).append(elements[name]["elmt_type"]["extract"](node))
  1250                 else:
  1430                 else:
  1251                     setattr(self, name, elements[name]["elmt_type"]["extract"](node))
  1431                     object.__setattr__(self, name, elements[name]["elmt_type"]["extract"](node))
  1252             elif name == "#cdata-section" and elements.has_key("text"):
  1432             elif elements.has_key("text"):
  1253                 if elements["text"]["maxOccurs"] == "unbounded" or elements["text"]["maxOccurs"] > 1:
  1433                 if elements["text"]["maxOccurs"] == "unbounded" or elements["text"]["maxOccurs"] > 1:
  1254                     if first.get("text", True):
  1434                     if first.get("text", True):
  1255                         setattr(self, "text", [elements["text"]["elmt_type"]["extract"](node)])
  1435                         object.__setattr__(self, "text", [elements["text"]["elmt_type"]["extract"](node)])
  1256                         first["text"] = False
  1436                         first["text"] = False
  1257                     else:
  1437                     else:
  1258                         getattr(self, "text").append(elements["text"]["elmt_type"]["extract"](node))
  1438                         getattr(self, "text").append(elements["text"]["elmt_type"]["extract"](node))
  1259                 else:
  1439                 else:
  1260                     setattr(self, "text", elements["text"]["elmt_type"]["extract"](node))
  1440                     object.__setattr__(self, "text", elements["text"]["elmt_type"]["extract"](node))
  1261             elif elements.has_key("content"):
  1441             elif elements.has_key("content"):
  1262                 content = getattr(self, "content")
  1442                 if name == "#cdata-section":
  1263                 if elements["content"]["maxOccurs"] == "unbounded" or elements["content"]["maxOccurs"] > 1:
  1443                     if elements["content"]["elmt_type"]["type"] == SIMPLETYPE:
  1264                     if first.get("content", True):
  1444                         object.__setattr__(self, "content", elements["content"]["elmt_type"]["extract"](node.data, False))
  1265                         setattr(self, "content", [elements["content"]["elmt_type"]["extract"](node, None)])
  1445                 else:
  1266                         first["content"] = False
  1446                     content = getattr(self, "content")
       
  1447                     if elements["content"]["maxOccurs"] == "unbounded" or elements["content"]["maxOccurs"] > 1:
       
  1448                         if first.get("content", True):
       
  1449                             object.__setattr__(self, "content", [elements["content"]["elmt_type"]["extract"](node, None)])
       
  1450                             first["content"] = False
       
  1451                         else:
       
  1452                             content.append(elements["content"]["elmt_type"]["extract"](node, content))
  1267                     else:
  1453                     else:
  1268                         content.append(elements["content"]["elmt_type"]["extract"](node, content))
  1454                         object.__setattr__(self, "content", elements["content"]["elmt_type"]["extract"](node, content))
  1269                 else:
       
  1270                     setattr(self, "content", elements["content"]["elmt_type"]["extract"](node, content))
       
  1271     return loadXMLTreeMethod
  1455     return loadXMLTreeMethod
  1272         
  1456         
  1273 
  1457 
  1274 """
  1458 """
  1275 Method that generates the method for generating an xml text by following the
  1459 Method that generates the method for generating an xml text by following the
  1291                 text += u' %s=%s' % (attr, quoteattr(value))
  1475                 text += u' %s=%s' % (attr, quoteattr(value))
  1292                 first = False
  1476                 first = False
  1293             extras.clear()
  1477             extras.clear()
  1294         for attr in classinfos["attributes"]:
  1478         for attr in classinfos["attributes"]:
  1295             if attr["use"] != "prohibited":
  1479             if attr["use"] != "prohibited":
  1296                 if isinstance(attr["attr_type"], (UnicodeType, StringType)):
  1480                 attr["attr_type"] = FindTypeInfos(factory, attr["attr_type"])
  1297                     namespace, name = DecomposeQualifiedName(infos)
       
  1298                     attr["attr_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1299                 value = getattr(self, attr["name"], None)
  1481                 value = getattr(self, attr["name"], None)
  1300                 if value != None:
  1482                 if value != None:
  1301                     computed_value = attr["attr_type"]["generate"](value)
  1483                     computed_value = attr["attr_type"]["generate"](value)
  1302                 else:
  1484                 else:
  1303                     computed_value = None
  1485                     computed_value = None
  1314             first, new_text = classinfos["base"].generateXMLText(self, name, indent, extras, True)
  1496             first, new_text = classinfos["base"].generateXMLText(self, name, indent, extras, True)
  1315             text += new_text
  1497             text += new_text
  1316         else:
  1498         else:
  1317             first = True
  1499             first = True
  1318         for element in classinfos["elements"]:
  1500         for element in classinfos["elements"]:
  1319             if isinstance(element["elmt_type"], (UnicodeType, StringType)):
  1501             element["elmt_type"] = FindTypeInfos(factory, element["elmt_type"])
  1320                 namespace, name = DecomposeQualifiedName(infos)
       
  1321                 element["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1322             value = getattr(self, element["name"], None)
  1502             value = getattr(self, element["name"], None)
  1323             if element["minOccurs"] == 0 and element["maxOccurs"] == 1:
  1503             if element["minOccurs"] == 0 and element["maxOccurs"] == 1:
  1324                 if value is not None:
  1504                 if value is not None:
  1325                     if first:
  1505                     if first:
  1326                         text += u'>\n'
  1506                         text += u'>\n'
  1328                     text += element["elmt_type"]["generate"](value, element["name"], indent + 1)
  1508                     text += element["elmt_type"]["generate"](value, element["name"], indent + 1)
  1329             elif element["minOccurs"] == 1 and element["maxOccurs"] == 1:
  1509             elif element["minOccurs"] == 1 and element["maxOccurs"] == 1:
  1330                 if first:
  1510                 if first:
  1331                     text += u'>\n'
  1511                     text += u'>\n'
  1332                     first = False
  1512                     first = False
  1333                 text += element["elmt_type"]["generate"](value, element["name"], indent + 1)
  1513                 if element["name"] == "content" and element["elmt_type"]["type"] == SIMPLETYPE:
       
  1514                     text += element["elmt_type"]["generate"](value)
       
  1515                 else:
       
  1516                     text += element["elmt_type"]["generate"](value, element["name"], indent + 1)
  1334             else:
  1517             else:
  1335                 if first and len(value) > 0:
  1518                 if first and len(value) > 0:
  1336                     text += u'>\n'
  1519                     text += u'>\n'
  1337                     first = False
  1520                     first = False
  1338                 for item in value:
  1521                 for item in value:
  1420             if classinfos.has_key("base"):
  1603             if classinfos.has_key("base"):
  1421                 children.extend(classinfos["base"].getElementInfos(self, name, derived=True)["children"])
  1604                 children.extend(classinfos["base"].getElementInfos(self, name, derived=True)["children"])
  1422             for element_name, element in elements.items():
  1605             for element_name, element in elements.items():
  1423                 if element["minOccurs"] == 0:
  1606                 if element["minOccurs"] == 0:
  1424                     use = "optional"
  1607                     use = "optional"
  1425                 if element_name == "content":
  1608                 if element_name == "content" and element["type"] == CHOICE:
  1426                     attr_type = [(choice["name"], None) for choice in element["choices"]]
  1609                     attr_type = [(choice["name"], None) for choice in element["choices"]]
  1427                     if self.content is None:
  1610                     if self.content is None:
  1428                         value = ""
  1611                         value = ""
  1429                     else:
  1612                     else:
  1430                         value = self.content["name"]
  1613                         value = self.content["name"]
  1431                         if self.content["value"] is not None:
  1614                         if self.content["value"] is not None:
  1432                             children.extend(self.content["value"].getElementInfos(self.content["name"])["children"])
  1615                             if self.content["name"] == "sequence":
       
  1616                                 choices_dict = dict([(choice["name"], choice) for choice in element["choices"]])
       
  1617                                 sequence_infos = choices_dict.get("sequence", None)
       
  1618                                 if sequence_infos is not None:
       
  1619                                     children.extend([item.getElementInfos(infos["name"]) for item, infos in zip(self.content["value"], sequence_infos["elements"])])
       
  1620                             else:
       
  1621                                 children.extend(self.content["value"].getElementInfos(self.content["name"])["children"])
  1433                 elif element["elmt_type"]["type"] == SIMPLETYPE:
  1622                 elif element["elmt_type"]["type"] == SIMPLETYPE:
  1434                     children.append({"name": element_name, "require": element["minOccurs"] != 0, 
  1623                     children.append({"name": element_name, "require": element["minOccurs"] != 0, 
  1435                         "type": gettypeinfos(element["elmt_type"]["basename"], 
  1624                         "type": gettypeinfos(element["elmt_type"]["basename"], 
  1436                                               element["elmt_type"]["facets"]),
  1625                                               element["elmt_type"]["facets"]),
  1437                         "value": getattr(self, element_name, None)})
  1626                         "value": getattr(self, element_name, None)})
  1493 def generateInitMethod(factory, classinfos):
  1682 def generateInitMethod(factory, classinfos):
  1494     def initMethod(self):
  1683     def initMethod(self):
  1495         if classinfos.has_key("base"):
  1684         if classinfos.has_key("base"):
  1496             classinfos["base"].__init__(self)
  1685             classinfos["base"].__init__(self)
  1497         for attribute in classinfos["attributes"]:
  1686         for attribute in classinfos["attributes"]:
  1498             if isinstance(attribute["attr_type"], (UnicodeType, StringType)):
  1687             attribute["attr_type"] = FindTypeInfos(factory, attribute["attr_type"])
  1499                 namespace, name = DecomposeQualifiedName(attribute["attr_type"])
       
  1500                 attribute["attr_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1501             if attribute["use"] == "required":
  1688             if attribute["use"] == "required":
  1502                 setattr(self, attribute["name"], attribute["attr_type"]["initial"]())
  1689                 setattr(self, attribute["name"], attribute["attr_type"]["initial"]())
  1503             elif attribute["use"] == "optional":
  1690             elif attribute["use"] == "optional":
  1504                 if attribute.has_key("default"):
  1691                 if attribute.has_key("default"):
  1505                     setattr(self, attribute["name"], attribute["attr_type"]["extract"](attribute["default"], False))
  1692                     setattr(self, attribute["name"], attribute["attr_type"]["extract"](attribute["default"], False))
  1506                 else:
  1693                 else:
  1507                     setattr(self, attribute["name"], None)
  1694                     setattr(self, attribute["name"], None)
  1508         for element in classinfos["elements"]:
  1695         for element in classinfos["elements"]:
  1509             if isinstance(element["elmt_type"], (UnicodeType, StringType)):
  1696             setattr(self, element["name"], GetElementInitialValue(factory, element))
  1510                 namespace, name = DecomposeQualifiedName(element["elmt_type"])
       
  1511                 element["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1512             if element["minOccurs"] == 0 and element["maxOccurs"] == 1:
       
  1513                 if "default" in element:
       
  1514                     setattr(self, element["name"], element["elmt_type"]["extract"](element["default"], False))
       
  1515                 else:
       
  1516                     setattr(self, element["name"], None)
       
  1517             elif element["minOccurs"] == 1 and element["maxOccurs"] == 1:
       
  1518                 setattr(self, element["name"], element["elmt_type"]["initial"]())
       
  1519             else:
       
  1520                 value = []
       
  1521                 for i in xrange(element["minOccurs"]):
       
  1522                     value.append(element["elmt_type"]["initial"]())
       
  1523                 setattr(self, element["name"], value)
       
  1524     return initMethod
  1697     return initMethod
  1525 
  1698 
  1526 def generateSetMethod(attr):
  1699 def generateSetMethod(attr):
  1527     def setMethod(self, value):
  1700     def setMethod(self, value):
  1528         setattr(self, attr, value)
  1701         setattr(self, attr, value)
  1534     return getMethod
  1707     return getMethod
  1535 
  1708 
  1536 def generateAddMethod(attr, factory, infos):
  1709 def generateAddMethod(attr, factory, infos):
  1537     def addMethod(self):
  1710     def addMethod(self):
  1538         if infos["type"] == ATTRIBUTE:
  1711         if infos["type"] == ATTRIBUTE:
  1539             if isinstance(infos["attr_type"], (UnicodeType, StringType)):
  1712             infos["attr_type"] = FindTypeInfos(factory, infos["attr_type"])
  1540                 namespace, name = DecomposeQualifiedName(infos)
       
  1541                 infos["attr_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1542             initial = infos["attr_type"]["initial"]
  1713             initial = infos["attr_type"]["initial"]
  1543             extract = infos["attr_type"]["extract"]
  1714             extract = infos["attr_type"]["extract"]
  1544         elif infos["type"] == ELEMENT:
  1715         elif infos["type"] == ELEMENT:
  1545             if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
  1716             infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
  1546                 namespace, name = DecomposeQualifiedName(infos)
       
  1547                 infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1548             initial = infos["elmt_type"]["initial"]
  1717             initial = infos["elmt_type"]["initial"]
  1549             extract = infos["elmt_type"]["extract"]
  1718             extract = infos["elmt_type"]["extract"]
  1550         else:
  1719         else:
  1551             raise ValueError("Invalid class attribute!")
  1720             raise ValueError("Invalid class attribute!")
  1552         if infos.has_key("default"):
  1721         if infos.has_key("default"):
  1560         setattr(self, attr, None)
  1729         setattr(self, attr, None)
  1561     return deleteMethod
  1730     return deleteMethod
  1562 
  1731 
  1563 def generateAppendMethod(attr, maxOccurs, factory, infos):
  1732 def generateAppendMethod(attr, maxOccurs, factory, infos):
  1564     def appendMethod(self, value):
  1733     def appendMethod(self, value):
  1565         if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
  1734         infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
  1566             namespace, name = DecomposeQualifiedName(infos)
       
  1567             infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1568         attr_list = getattr(self, attr)
  1735         attr_list = getattr(self, attr)
  1569         if maxOccurs == "unbounded" or len(attr_list) < maxOccurs:
  1736         if maxOccurs == "unbounded" or len(attr_list) < maxOccurs:
  1570             if infos["elmt_type"]["check"](value):
  1737             if infos["elmt_type"]["check"](value):
  1571                 attr_list.append(value)
  1738                 attr_list.append(value)
  1572             else:
  1739             else:
  1575             raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr))
  1742             raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr))
  1576     return appendMethod
  1743     return appendMethod
  1577 
  1744 
  1578 def generateInsertMethod(attr, maxOccurs, factory, infos):
  1745 def generateInsertMethod(attr, maxOccurs, factory, infos):
  1579     def insertMethod(self, index, value):
  1746     def insertMethod(self, index, value):
  1580         if isinstance(infos["elmt_type"], (UnicodeType, StringType)):
  1747         infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
  1581             namespace, name = DecomposeQualifiedName(infos)
       
  1582             infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1583         attr_list = getattr(self, attr)
  1748         attr_list = getattr(self, attr)
  1584         if maxOccurs == "unbounded" or len(attr_list) < maxOccurs:
  1749         if maxOccurs == "unbounded" or len(attr_list) < maxOccurs:
  1585             if infos["elmt_type"]["check"](value):
  1750             if infos["elmt_type"]["check"](value):
  1586                 attr_list.insert(index, value)
  1751                 attr_list.insert(index, value)
  1587             else:
  1752             else:
  1598 def generateSetChoiceByTypeMethod(factory, choice_types):
  1763 def generateSetChoiceByTypeMethod(factory, choice_types):
  1599     choices = dict([(choice["name"], choice) for choice in choice_types])
  1764     choices = dict([(choice["name"], choice) for choice in choice_types])
  1600     def setChoiceMethod(self, type):
  1765     def setChoiceMethod(self, type):
  1601         if not choices.has_key(type):
  1766         if not choices.has_key(type):
  1602             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
  1767             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
  1603         if isinstance(choices[type]["elmt_type"], (UnicodeType, StringType)):
  1768         choices[type]["elmt_type"] = FindTypeInfos(factory, choices[type]["elmt_type"])
  1604             namespace, name = DecomposeQualifiedName(choices[type]["elmt_type"])
       
  1605             choices[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1606         new_element = choices[type]["elmt_type"]["initial"]()
  1769         new_element = choices[type]["elmt_type"]["initial"]()
  1607         self.content = {"name": type, "value": new_element}
  1770         self.content = {"name": type, "value": new_element}
  1608         return new_element
  1771         return new_element
  1609     return setChoiceMethod
  1772     return setChoiceMethod
  1610 
  1773 
  1611 def generateAppendChoiceByTypeMethod(maxOccurs, factory, choice_types):
  1774 def generateAppendChoiceByTypeMethod(maxOccurs, factory, choice_types):
  1612     choices = dict([(choice["name"], choice) for choice in choice_types])
  1775     choices = dict([(choice["name"], choice) for choice in choice_types])
  1613     def appendChoiceMethod(self, type):
  1776     def appendChoiceMethod(self, type):
  1614         if not choices.has_key(type):
  1777         if not choices.has_key(type):
  1615             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
  1778             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
  1616         if isinstance(choices[type]["elmt_type"], (UnicodeType, StringType)):
  1779         choices[type]["elmt_type"] = FindTypeInfos(factory, choices[type]["elmt_type"])
  1617             namespace, name = DecomposeQualifiedName(choices[type]["elmt_type"])
       
  1618             choices[type]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1619         if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
  1780         if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
  1620             new_element = choices[type]["elmt_type"]["initial"]()
  1781             new_element = choices[type]["elmt_type"]["initial"]()
  1621             self.content.append({"name": type, "value": new_element})
  1782             self.content.append({"name": type, "value": new_element})
  1622             return new_element
  1783             return new_element
  1623         else:
  1784         else:
  1627 def generateInsertChoiceByTypeMethod(maxOccurs, factory, choice_types):
  1788 def generateInsertChoiceByTypeMethod(maxOccurs, factory, choice_types):
  1628     choices = dict([(choice["name"], choice) for choice in choice_types])
  1789     choices = dict([(choice["name"], choice) for choice in choice_types])
  1629     def insertChoiceMethod(self, index, type):
  1790     def insertChoiceMethod(self, index, type):
  1630         if not choices.has_key(type):
  1791         if not choices.has_key(type):
  1631             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
  1792             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
  1632         if isinstance(choices[type]["elmt_type"], (UnicodeType, StringType)):
  1793         choices[type]["elmt_type"] = FindTypeInfos(factory, choices[type]["elmt_type"])
  1633             namespace, name = DecomposeQualifiedName(choices[type]["elmt_type"])
       
  1634             choices[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace)
       
  1635         if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
  1794         if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
  1636             new_element = choices[type]["elmt_type"]["initial"]()
  1795             new_element = choices[type]["elmt_type"]["initial"]()
  1637             self.content.insert(index, {"name" : type, "value" : new_element})
  1796             self.content.insert(index, {"name" : type, "value" : new_element})
  1638             return new_element
  1797             return new_element
  1639         else:
  1798         else:
  1663     if declare:
  1822     if declare:
  1664         for ClassName, Class in pluginClasses.items():
  1823         for ClassName, Class in pluginClasses.items():
  1665             sys._getframe(1).f_locals[ClassName] = Class
  1824             sys._getframe(1).f_locals[ClassName] = Class
  1666         for TypeName, Type in pluginTypes.items():
  1825         for TypeName, Type in pluginTypes.items():
  1667             sys._getframe(1).f_locals[TypeName] = Type
  1826             sys._getframe(1).f_locals[TypeName] = Type
  1668     globals().update(ComputedClasses)
  1827     if factory.FileName is not None and len(ComputedClasses) == 1:
  1669     return ComputedClasses
  1828         globals().update(ComputedClasses[factory.FileName])
  1670 
  1829         return ComputedClasses[factory.FileName]
       
  1830     else:
       
  1831         globals().update(ComputedClasses)
       
  1832         return ComputedClasses
       
  1833