xmlclass/xmlclass.py
changeset 1730 64d8f52bc8c8
parent 1571 486f94a8032c
child 1732 94ffe74e6895
equal deleted inserted replaced
1726:d51af006fa6b 1730:64d8f52bc8c8
    91         return self.__name
    91         return self.__name
    92 
    92 
    93     def dst(self, dt):
    93     def dst(self, dt):
    94         return ZERO
    94         return ZERO
    95 
    95 
    96 [SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE, 
    96 [SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE,
    97  ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG, CONSTRAINT,
    97  ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG, CONSTRAINT,
    98 ] = range(13)
    98 ] = range(13)
    99 
    99 
   100 def NotSupportedYet(type):
   100 def NotSupportedYet(type):
   101     """
   101     """
   138         return text
   138         return text
   139 
   139 
   140 
   140 
   141 def GetNormalizedString(attr, extract=True):
   141 def GetNormalizedString(attr, extract=True):
   142     """
   142     """
   143     Function that normalizes a string according to XML 1.0. Replace  
   143     Function that normalizes a string according to XML 1.0. Replace
   144     tabulations, line feed and carriage return by white space
   144     tabulations, line feed and carriage return by white space
   145     @param attr: tree node containing data to extract or data to normalize
   145     @param attr: tree node containing data to extract or data to normalize
   146     @param extract: attr is a tree node or not
   146     @param extract: attr is a tree node or not
   147     @return: data normalized as string
   147     @return: data normalized as string
   148     """
   148     """
   153     return value.replace("\t", " ").replace("\r", " ").replace("\n", " ")
   153     return value.replace("\t", " ").replace("\r", " ").replace("\n", " ")
   154 
   154 
   155 
   155 
   156 def GetToken(attr, extract=True):
   156 def GetToken(attr, extract=True):
   157     """
   157     """
   158     Function that tokenizes a string according to XML 1.0. Remove any leading  
   158     Function that tokenizes a string according to XML 1.0. Remove any leading
   159     and trailing white space and replace internal sequence of two or more 
   159     and trailing white space and replace internal sequence of two or more
   160     spaces by only one white space
   160     spaces by only one white space
   161     @param attr: tree node containing data to extract or data to tokenize
   161     @param attr: tree node containing data to extract or data to tokenize
   162     @param extract: attr is a tree node or not
   162     @param extract: attr is a tree node or not
   163     @return: data tokenized as string
   163     @return: data tokenized as string
   164     """
   164     """
   165     return " ".join([part for part in 
   165     return " ".join([part for part in
   166                      GetNormalizedString(attr, extract).split(" ")
   166                      GetNormalizedString(attr, extract).split(" ")
   167                      if part])
   167                      if part])
   168 
   168 
   169 
   169 
   170 def GetHexInteger(attr, extract=True):
   170 def GetHexInteger(attr, extract=True):
   184         return int(value, 16)
   184         return int(value, 16)
   185     except:
   185     except:
   186         raise ValueError("\"%s\" isn't a valid hexadecimal integer!" % value)
   186         raise ValueError("\"%s\" isn't a valid hexadecimal integer!" % value)
   187 
   187 
   188 
   188 
   189 def GenerateIntegerExtraction(minInclusive=None, maxInclusive=None, 
   189 def GenerateIntegerExtraction(minInclusive=None, maxInclusive=None,
   190                               minExclusive=None, maxExclusive=None):
   190                               minExclusive=None, maxExclusive=None):
   191     """
   191     """
   192     Function that generates an extraction function for integer defining min and
   192     Function that generates an extraction function for integer defining min and
   193     max of integer value
   193     max of integer value
   194     @param minInclusive: inclusive minimum
   194     @param minInclusive: inclusive minimum
   515         """
   515         """
   516         Function that extracts a list of string from a tree node or not and
   516         Function that extracts a list of string from a tree node or not and
   517         check that all extracted items match the model
   517         check that all extracted items match the model
   518         @param attr: tree node containing data to extract or data as a string
   518         @param attr: tree node containing data to extract or data as a string
   519         @param extract: attr is a tree node or not
   519         @param extract: attr is a tree node or not
   520         @return: data as a list of string if matching 
   520         @return: data as a list of string if matching
   521         """
   521         """
   522         if extract:
   522         if extract:
   523             value = GetAttributeValue(attr)
   523             value = GetAttributeValue(attr)
   524         else:
   524         else:
   525             value = attr
   525             value = attr
   533                                  (value, type))
   533                                  (value, type))
   534         return values
   534         return values
   535     return GetModelNameList
   535     return GetModelNameList
   536 
   536 
   537 def GenerateAnyInfos(infos):
   537 def GenerateAnyInfos(infos):
   538     
   538 
   539     def GetTextElement(tree):
   539     def GetTextElement(tree):
   540         if infos["namespace"][0] == "##any":
   540         if infos["namespace"][0] == "##any":
   541             return tree.xpath("p")[0]
   541             return tree.xpath("p")[0]
   542         return tree.xpath("ns:p", namespaces={"ns": infos["namespace"][0]})[0]
   542         return tree.xpath("ns:p", namespaces={"ns": infos["namespace"][0]})[0]
   543     
   543 
   544     def ExtractAny(tree):
   544     def ExtractAny(tree):
   545         return GetTextElement(tree).text
   545         return GetTextElement(tree).text
   546     
   546 
   547     def GenerateAny(tree, value):
   547     def GenerateAny(tree, value):
   548         GetTextElement(tree).text = etree.CDATA(value)
   548         GetTextElement(tree).text = etree.CDATA(value)
   549         
   549 
   550     def InitialAny():
   550     def InitialAny():
   551         if infos["namespace"][0] == "##any":
   551         if infos["namespace"][0] == "##any":
   552             element_name = "p"
   552             element_name = "p"
   553         else:
   553         else:
   554             element_name = "{%s}p" % infos["namespace"][0]
   554             element_name = "{%s}p" % infos["namespace"][0]
   555         p = etree.Element(element_name)
   555         p = etree.Element(element_name)
   556         p.text = etree.CDATA("")
   556         p.text = etree.CDATA("")
   557         return p
   557         return p
   558         
   558 
   559     return {
   559     return {
   560         "type": COMPLEXTYPE, 
   560         "type": COMPLEXTYPE,
   561         "extract": ExtractAny,
   561         "extract": ExtractAny,
   562         "generate": GenerateAny,
   562         "generate": GenerateAny,
   563         "initial": InitialAny,
   563         "initial": InitialAny,
   564         "check": lambda x: isinstance(x, (StringType, UnicodeType, etree.ElementBase))
   564         "check": lambda x: isinstance(x, (StringType, UnicodeType, etree.ElementBase))
   565     }
   565     }
   572             raise ValueError("\"%s\" musn't have children!" % infos["name"])
   572             raise ValueError("\"%s\" musn't have children!" % infos["name"])
   573         if infos["minOccurs"] == 0:
   573         if infos["minOccurs"] == 0:
   574             return True
   574             return True
   575         else:
   575         else:
   576             return None
   576             return None
   577     
   577 
   578     def GenerateTag(value, name=None, indent=0):
   578     def GenerateTag(value, name=None, indent=0):
   579         if name is not None and not (infos["minOccurs"] == 0 and value is None):
   579         if name is not None and not (infos["minOccurs"] == 0 and value is None):
   580             ind1, ind2 = getIndent(indent, name)
   580             ind1, ind2 = getIndent(indent, name)
   581             return ind1 + "<%s/>\n" % name
   581             return ind1 + "<%s/>\n" % name
   582         else:
   582         else:
   583             return ""
   583             return ""
   584     
   584 
   585     return {
   585     return {
   586         "type": TAG, 
   586         "type": TAG,
   587         "extract": ExtractTag,
   587         "extract": ExtractTag,
   588         "generate": GenerateTag,
   588         "generate": GenerateTag,
   589         "initial": lambda: None,
   589         "initial": lambda: None,
   590         "check": lambda x: x == None or infos["minOccurs"] == 0 and value == True
   590         "check": lambda x: x == None or infos["minOccurs"] == 0 and value == True
   591     }
   591     }
   593 def FindTypeInfos(factory, infos):
   593 def FindTypeInfos(factory, infos):
   594     if isinstance(infos, (UnicodeType, StringType)):
   594     if isinstance(infos, (UnicodeType, StringType)):
   595         namespace, name = DecomposeQualifiedName(infos)
   595         namespace, name = DecomposeQualifiedName(infos)
   596         return factory.GetQualifiedNameInfos(name, namespace)
   596         return factory.GetQualifiedNameInfos(name, namespace)
   597     return infos
   597     return infos
   598     
   598 
   599 def GetElementInitialValue(factory, infos):
   599 def GetElementInitialValue(factory, infos):
   600     infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
   600     infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
   601     if infos["minOccurs"] == 1:
   601     if infos["minOccurs"] == 1:
   602         element_name = factory.etreeNamespaceFormat % infos["name"]
   602         element_name = factory.etreeNamespaceFormat % infos["name"]
   603         if infos["elmt_type"]["type"] == SIMPLETYPE:
   603         if infos["elmt_type"]["type"] == SIMPLETYPE:
   665                 raise ValueError("'%s' element defined two times in choice" % choice_name)
   665                 raise ValueError("'%s' element defined two times in choice" % choice_name)
   666             choices_dict[choice_name] = infos
   666             choices_dict[choice_name] = infos
   667     prefix = ("%s:" % factory.TargetNamespace
   667     prefix = ("%s:" % factory.TargetNamespace
   668               if factory.TargetNamespace is not None else "")
   668               if factory.TargetNamespace is not None else "")
   669     choices_xpath = "|".join(map(lambda x: prefix + x, choices_dict.keys()))
   669     choices_xpath = "|".join(map(lambda x: prefix + x, choices_dict.keys()))
   670     
   670 
   671     def GetContentInitial():
   671     def GetContentInitial():
   672         content_name, infos = choices[0]
   672         content_name, infos = choices[0]
   673         if content_name == "sequence":
   673         if content_name == "sequence":
   674             content_value = []
   674             content_value = []
   675             for i in xrange(infos["minOccurs"]):
   675             for i in xrange(infos["minOccurs"]):
   676                 for element_infos in infos["elements"]:
   676                 for element_infos in infos["elements"]:
   677                     content_value.extend(GetElementInitialValue(factory, element_infos))
   677                     content_value.extend(GetElementInitialValue(factory, element_infos))
   678         else:
   678         else:
   679             content_value = GetElementInitialValue(factory, infos)
   679             content_value = GetElementInitialValue(factory, infos)
   680         return content_value
   680         return content_value
   681         
   681 
   682     return {
   682     return {
   683         "type": COMPLEXTYPE,
   683         "type": COMPLEXTYPE,
   684         "choices_xpath": etree.XPath(choices_xpath, namespaces=factory.NSMAP),
   684         "choices_xpath": etree.XPath(choices_xpath, namespaces=factory.NSMAP),
   685         "initial": GetContentInitial,
   685         "initial": GetContentInitial,
   686     }
   686     }
   691 
   691 
   692 
   692 
   693 def DecomposeQualifiedName(name):
   693 def DecomposeQualifiedName(name):
   694     result = QName_model.match(name)
   694     result = QName_model.match(name)
   695     if not result:
   695     if not result:
   696         raise ValueError("\"%s\" isn't a valid QName value!" % name) 
   696         raise ValueError("\"%s\" isn't a valid QName value!" % name)
   697     parts = result.groups()[0].split(':')
   697     parts = result.groups()[0].split(':')
   698     if len(parts) == 1:
   698     if len(parts) == 1:
   699         return None, parts[0]
   699         return None, parts[0]
   700     return parts
   700     return parts
   701     
   701 
   702 def GenerateElement(element_name, attributes, elements_model, 
   702 def GenerateElement(element_name, attributes, elements_model,
   703                     accept_text=False):
   703                     accept_text=False):
   704     def ExtractElement(factory, node):
   704     def ExtractElement(factory, node):
   705         attrs = factory.ExtractNodeAttrs(element_name, node, attributes)
   705         attrs = factory.ExtractNodeAttrs(element_name, node, attributes)
   706         children_structure = ""
   706         children_structure = ""
   707         children_infos = []
   707         children_infos = []
   744         if filepath is not None:
   744         if filepath is not None:
   745             self.BaseFolder, self.FileName = os.path.split(filepath)
   745             self.BaseFolder, self.FileName = os.path.split(filepath)
   746         else:
   746         else:
   747             self.BaseFolder = self.FileName = None
   747             self.BaseFolder = self.FileName = None
   748         self.Debug = debug
   748         self.Debug = debug
   749         
   749 
   750         # Dictionary for stocking Classes and Types definitions created from
   750         # Dictionary for stocking Classes and Types definitions created from
   751         # the XML tree
   751         # the XML tree
   752         self.XMLClassDefinitions = {}
   752         self.XMLClassDefinitions = {}
   753         
   753 
   754         self.DefinedNamespaces = {}
   754         self.DefinedNamespaces = {}
   755         self.NSMAP = {}
   755         self.NSMAP = {}
   756         self.Namespaces = {}
   756         self.Namespaces = {}
   757         self.SchemaNamespace = None
   757         self.SchemaNamespace = None
   758         self.TargetNamespace = None
   758         self.TargetNamespace = None
   759         self.etreeNamespaceFormat = "%s"
   759         self.etreeNamespaceFormat = "%s"
   760         
   760 
   761         self.CurrentCompilations = []
   761         self.CurrentCompilations = []
   762         
   762 
   763         # Dictionaries for stocking Classes and Types generated
   763         # Dictionaries for stocking Classes and Types generated
   764         self.ComputeAfter = []
   764         self.ComputeAfter = []
   765         if self.FileName is not None:
   765         if self.FileName is not None:
   766             self.ComputedClasses = {self.FileName: {}}
   766             self.ComputedClasses = {self.FileName: {}}
   767         else:
   767         else:
   918         else:
   918         else:
   919             raise ValueError("\"%s\" class already defined. Choose another name!" % typename)
   919             raise ValueError("\"%s\" class already defined. Choose another name!" % typename)
   920 
   920 
   921     def ParseSchema(self):
   921     def ParseSchema(self):
   922         pass
   922         pass
   923     
   923 
   924     def AddEquivalentClass(self, name, base):
   924     def AddEquivalentClass(self, name, base):
   925         if name != base:
   925         if name != base:
   926             equivalences = self.EquivalentClassesParent.setdefault(self.etreeNamespaceFormat % base, {})
   926             equivalences = self.EquivalentClassesParent.setdefault(self.etreeNamespaceFormat % base, {})
   927             equivalences[self.etreeNamespaceFormat % name] = True
   927             equivalences[self.etreeNamespaceFormat % name] = True
   928     
   928 
   929     def AddDistinctionBetweenParentsInLookupClass(
   929     def AddDistinctionBetweenParentsInLookupClass(
   930                                     self, lookup_classes, parent, typeinfos):
   930                                     self, lookup_classes, parent, typeinfos):
   931         parent = (self.etreeNamespaceFormat % parent 
   931         parent = (self.etreeNamespaceFormat % parent
   932                   if parent is not None else None)
   932                   if parent is not None else None)
   933         parent_class = lookup_classes.get(parent)
   933         parent_class = lookup_classes.get(parent)
   934         if parent_class is not None:
   934         if parent_class is not None:
   935             if isinstance(parent_class, ListType):
   935             if isinstance(parent_class, ListType):
   936                 if typeinfos not in parent_class:
   936                 if typeinfos not in parent_class:
   937                     lookup_classes[parent].append(typeinfos)
   937                     lookup_classes[parent].append(typeinfos)
   938             elif parent_class != typeinfos:
   938             elif parent_class != typeinfos:
   939                 lookup_classes[parent] = [typeinfos, parent_class]
   939                 lookup_classes[parent] = [typeinfos, parent_class]
   940         else:
   940         else:
   941             lookup_classes[parent] = typeinfos
   941             lookup_classes[parent] = typeinfos
   942     
   942 
   943     def AddToLookupClass(self, name, parent, typeinfos):
   943     def AddToLookupClass(self, name, parent, typeinfos):
   944         lookup_name = self.etreeNamespaceFormat % name
   944         lookup_name = self.etreeNamespaceFormat % name
   945         if isinstance(typeinfos, (StringType, UnicodeType)):
   945         if isinstance(typeinfos, (StringType, UnicodeType)):
   946             self.AddEquivalentClass(name, typeinfos)
   946             self.AddEquivalentClass(name, typeinfos)
   947             typeinfos = self.etreeNamespaceFormat % typeinfos
   947             typeinfos = self.etreeNamespaceFormat % typeinfos
   956                 self.etreeNamespaceFormat % lookup_classes[1]
   956                 self.etreeNamespaceFormat % lookup_classes[1]
   957                 if lookup_classes[1] is not None else None: lookup_classes[0]}
   957                 if lookup_classes[1] is not None else None: lookup_classes[0]}
   958             self.AddDistinctionBetweenParentsInLookupClass(
   958             self.AddDistinctionBetweenParentsInLookupClass(
   959                 lookup_classes, parent, typeinfos)
   959                 lookup_classes, parent, typeinfos)
   960             self.ComputedClassesLookUp[lookup_name] = lookup_classes
   960             self.ComputedClassesLookUp[lookup_name] = lookup_classes
   961     
   961 
   962     def ExtractTypeInfos(self, name, parent, typeinfos):
   962     def ExtractTypeInfos(self, name, parent, typeinfos):
   963         if isinstance(typeinfos, (StringType, UnicodeType)):
   963         if isinstance(typeinfos, (StringType, UnicodeType)):
   964             namespace, type_name = DecomposeQualifiedName(typeinfos)
   964             namespace, type_name = DecomposeQualifiedName(typeinfos)
   965             infos = self.GetQualifiedNameInfos(type_name, namespace)
   965             infos = self.GetQualifiedNameInfos(type_name, namespace)
   966             if name != "base":
   966             if name != "base":
   984                 return infos
   984                 return infos
   985         elif typeinfos["type"] == COMPLEXTYPE:
   985         elif typeinfos["type"] == COMPLEXTYPE:
   986             return self.CreateClass(name, parent, typeinfos)
   986             return self.CreateClass(name, parent, typeinfos)
   987         elif typeinfos["type"] == SIMPLETYPE:
   987         elif typeinfos["type"] == SIMPLETYPE:
   988             return typeinfos
   988             return typeinfos
   989     
   989 
   990     def GetEquivalentParents(self, parent):
   990     def GetEquivalentParents(self, parent):
   991         return reduce(lambda x, y: x + y,
   991         return reduce(lambda x, y: x + y,
   992             [[p] + self.GetEquivalentParents(p)
   992             [[p] + self.GetEquivalentParents(p)
   993              for p in self.EquivalentClassesParent.get(parent, {}).keys()], [])
   993              for p in self.EquivalentClassesParent.get(parent, {}).keys()], [])
   994     
   994 
   995     """
   995     """
   996     Methods that generates the classes
   996     Methods that generates the classes
   997     """
   997     """
   998     def CreateClasses(self):
   998     def CreateClasses(self):
   999         self.ParseSchema()
   999         self.ParseSchema()
  1026                         while len(self.ComputeAfter) > 0:
  1026                         while len(self.ComputeAfter) > 0:
  1027                             result = self.CreateClass(*self.ComputeAfter.pop(0))
  1027                             result = self.CreateClass(*self.ComputeAfter.pop(0))
  1028                             if result is not None and \
  1028                             if result is not None and \
  1029                                not isinstance(result, (UnicodeType, StringType)):
  1029                                not isinstance(result, (UnicodeType, StringType)):
  1030                                 self.Namespaces[self.TargetNamespace][result["name"]] = result
  1030                                 self.Namespaces[self.TargetNamespace][result["name"]] = result
  1031         
  1031 
  1032         for name, parents in self.ComputedClassesLookUp.iteritems():
  1032         for name, parents in self.ComputedClassesLookUp.iteritems():
  1033             if isinstance(parents, DictType):
  1033             if isinstance(parents, DictType):
  1034                 computed_classes = parents.items()
  1034                 computed_classes = parents.items()
  1035             elif parents[1] is not None:
  1035             elif parents[1] is not None:
  1036                 computed_classes = [(self.etreeNamespaceFormat % parents[1], parents[0])]
  1036                 computed_classes = [(self.etreeNamespaceFormat % parents[1], parents[0])]
  1040                 for equivalent_parent in self.GetEquivalentParents(parent):
  1040                 for equivalent_parent in self.GetEquivalentParents(parent):
  1041                     if not isinstance(parents, DictType):
  1041                     if not isinstance(parents, DictType):
  1042                         parents = dict(computed_classes)
  1042                         parents = dict(computed_classes)
  1043                         self.ComputedClassesLookUp[name] = parents
  1043                         self.ComputedClassesLookUp[name] = parents
  1044                     parents[equivalent_parent] = computed_class
  1044                     parents[equivalent_parent] = computed_class
  1045         
  1045 
  1046         return self.ComputedClasses
  1046         return self.ComputedClasses
  1047 
  1047 
  1048     def CreateClass(self, name, parent, classinfos, baseclass = False):
  1048     def CreateClass(self, name, parent, classinfos, baseclass = False):
  1049         if parent is not None:
  1049         if parent is not None:
  1050             classname = "%s_%s" % (parent, name)
  1050             classname = "%s_%s" % (parent, name)
  1051         else:
  1051         else:
  1052             classname = name
  1052             classname = name
  1053         
  1053 
  1054         # Checks that classe haven't been generated yet
  1054         # Checks that classe haven't been generated yet
  1055         if self.AlreadyComputed.get(classname, False):
  1055         if self.AlreadyComputed.get(classname, False):
  1056             return self.ComputedClassesInfos.get(classname, None)
  1056             return self.ComputedClassesInfos.get(classname, None)
  1057         
  1057 
  1058         # If base classes haven't been generated
  1058         # If base classes haven't been generated
  1059         bases = []
  1059         bases = []
  1060         base_infos = classinfos.get("base", None)
  1060         base_infos = classinfos.get("base", None)
  1061         if base_infos is not None:
  1061         if base_infos is not None:
  1062             namespace, base_name = DecomposeQualifiedName(base_infos)
  1062             namespace, base_name = DecomposeQualifiedName(base_infos)
  1086                     raise ValueError("No class found for base type")
  1086                     raise ValueError("No class found for base type")
  1087                 bases.append(classinfos["base"])
  1087                 bases.append(classinfos["base"])
  1088         bases.append(DefaultElementClass)
  1088         bases.append(DefaultElementClass)
  1089         bases = tuple(bases)
  1089         bases = tuple(bases)
  1090         classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass}
  1090         classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass}
  1091         
  1091 
  1092         self.AlreadyComputed[classname] = True
  1092         self.AlreadyComputed[classname] = True
  1093         
  1093 
  1094         for attribute in classinfos["attributes"]:
  1094         for attribute in classinfos["attributes"]:
  1095             infos = self.ExtractTypeInfos(attribute["name"], name, attribute["attr_type"])
  1095             infos = self.ExtractTypeInfos(attribute["name"], name, attribute["attr_type"])
  1096             if infos is not None:                    
  1096             if infos is not None:
  1097                 if infos["type"] != SIMPLETYPE:
  1097                 if infos["type"] != SIMPLETYPE:
  1098                     raise ValueError("\"%s\" type is not a simple type!" % attribute["attr_type"])
  1098                     raise ValueError("\"%s\" type is not a simple type!" % attribute["attr_type"])
  1099                 attrname = attribute["name"]
  1099                 attrname = attribute["name"]
  1100                 if attribute["use"] == "optional":
  1100                 if attribute["use"] == "optional":
  1101                     classmembers["add%s"%attrname] = generateAddMethod(attrname, self, attribute)
  1101                     classmembers["add%s"%attrname] = generateAddMethod(attrname, self, attribute)
  1103                 classmembers["set%s"%attrname] = generateSetMethod(attrname)
  1103                 classmembers["set%s"%attrname] = generateSetMethod(attrname)
  1104                 classmembers["get%s"%attrname] = generateGetMethod(attrname)
  1104                 classmembers["get%s"%attrname] = generateGetMethod(attrname)
  1105             else:
  1105             else:
  1106                 raise ValueError("\"%s\" type unrecognized!" % attribute["attr_type"])
  1106                 raise ValueError("\"%s\" type unrecognized!" % attribute["attr_type"])
  1107             attribute["attr_type"] = infos
  1107             attribute["attr_type"] = infos
  1108         
  1108 
  1109         for element in classinfos["elements"]:
  1109         for element in classinfos["elements"]:
  1110             if element["type"] == CHOICE:
  1110             if element["type"] == CHOICE:
  1111                 elmtname = element["name"]
  1111                 elmtname = element["name"]
  1112                 choices = ComputeContentChoices(self, name, element)
  1112                 choices = ComputeContentChoices(self, name, element)
  1113                 classmembers["get%schoices"%elmtname] = generateGetChoicesMethod(element["choices"])
  1113                 classmembers["get%schoices"%elmtname] = generateGetChoicesMethod(element["choices"])
  1139                 if element["minOccurs"] == 0:
  1139                 if element["minOccurs"] == 0:
  1140                     classmembers["add%s" % elmtname] = generateAddMethod(elmtname, self, element)
  1140                     classmembers["add%s" % elmtname] = generateAddMethod(elmtname, self, element)
  1141                     classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname)
  1141                     classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname)
  1142             classmembers["set%s" % elmtname] = generateSetMethod(elmtname)
  1142             classmembers["set%s" % elmtname] = generateSetMethod(elmtname)
  1143             classmembers["get%s" % elmtname] = generateGetMethod(elmtname)
  1143             classmembers["get%s" % elmtname] = generateGetMethod(elmtname)
  1144             
  1144 
  1145         classmembers["_init_"] = generateInitMethod(self, classinfos)
  1145         classmembers["_init_"] = generateInitMethod(self, classinfos)
  1146         classmembers["StructurePattern"] = GetStructurePattern(classinfos)
  1146         classmembers["StructurePattern"] = GetStructurePattern(classinfos)
  1147         classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos)
  1147         classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos)
  1148         classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos)
  1148         classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos)
  1149         classmembers["setElementValue"] = generateSetElementValue(self, classinfos)
  1149         classmembers["setElementValue"] = generateSetElementValue(self, classinfos)
  1150         
  1150 
  1151         class_definition = classobj(str(name), bases, classmembers)
  1151         class_definition = classobj(str(name), bases, classmembers)
  1152         setattr(class_definition, "__getattr__", generateGetattrMethod(self, class_definition, classinfos))
  1152         setattr(class_definition, "__getattr__", generateGetattrMethod(self, class_definition, classinfos))
  1153         setattr(class_definition, "__setattr__", generateSetattrMethod(self, class_definition, classinfos))
  1153         setattr(class_definition, "__setattr__", generateSetattrMethod(self, class_definition, classinfos))
  1154         class_infos = {"type": COMPILEDCOMPLEXTYPE,
  1154         class_infos = {"type": COMPILEDCOMPLEXTYPE,
  1155                        "name": classname,
  1155                        "name": classname,
  1156                        "initial": generateClassCreateFunction(class_definition),
  1156                        "initial": generateClassCreateFunction(class_definition),
  1157         }
  1157         }
  1158         
  1158 
  1159         if self.FileName is not None:
  1159         if self.FileName is not None:
  1160             self.ComputedClasses[self.FileName][classname] = class_definition
  1160             self.ComputedClasses[self.FileName][classname] = class_definition
  1161         else:
  1161         else:
  1162             self.ComputedClasses[classname] = class_definition
  1162             self.ComputedClasses[classname] = class_definition
  1163         self.ComputedClassesInfos[classname] = class_infos
  1163         self.ComputedClassesInfos[classname] = class_infos
  1164         
  1164 
  1165         self.AddToLookupClass(name, parent, class_definition)
  1165         self.AddToLookupClass(name, parent, class_definition)
  1166         self.AddToLookupClass(classname, None, class_definition)
  1166         self.AddToLookupClass(classname, None, class_definition)
  1167             
  1167 
  1168         return class_infos
  1168         return class_infos
  1169 
  1169 
  1170     """
  1170     """
  1171     Methods that print the classes generated
  1171     Methods that print the classes generated
  1172     """
  1172     """
  1181                 for classname, xmlclass in class_items:
  1181                 for classname, xmlclass in class_items:
  1182                     print "%s: %s" % (classname, str(xmlclass))
  1182                     print "%s: %s" % (classname, str(xmlclass))
  1183         else:
  1183         else:
  1184             for classname, xmlclass in items:
  1184             for classname, xmlclass in items:
  1185                 print "%s: %s" % (classname, str(xmlclass))
  1185                 print "%s: %s" % (classname, str(xmlclass))
  1186         
  1186 
  1187     def PrintClassNames(self):
  1187     def PrintClassNames(self):
  1188         classnames = self.XMLClassDefinitions.keys()
  1188         classnames = self.XMLClassDefinitions.keys()
  1189         classnames.sort()
  1189         classnames.sort()
  1190         for classname in classnames:
  1190         for classname in classnames:
  1191             print classname
  1191             print classname
  1192 
  1192 
  1193 """
  1193 """
  1194 Method that generate the method for generating the xml tree structure model by 
  1194 Method that generate the method for generating the xml tree structure model by
  1195 following the attributes list defined
  1195 following the attributes list defined
  1196 """
  1196 """
  1197 def ComputeMultiplicity(name, infos):
  1197 def ComputeMultiplicity(name, infos):
  1198     if infos["minOccurs"] == 0:
  1198     if infos["minOccurs"] == 0:
  1199         if infos["maxOccurs"] == "unbounded":
  1199         if infos["maxOccurs"] == "unbounded":
  1211             return "(?:%s){1,%d}" % (name, infos["maxOccurs"])
  1211             return "(?:%s){1,%d}" % (name, infos["maxOccurs"])
  1212     else:
  1212     else:
  1213         if infos["maxOccurs"] == "unbounded":
  1213         if infos["maxOccurs"] == "unbounded":
  1214             return "(?:%s){%d,}" % (name, infos["minOccurs"], name)
  1214             return "(?:%s){%d,}" % (name, infos["minOccurs"], name)
  1215         else:
  1215         else:
  1216             return "(?:%s){%d,%d}" % (name, infos["minOccurs"], 
  1216             return "(?:%s){%d,%d}" % (name, infos["minOccurs"],
  1217                                        infos["maxOccurs"])
  1217                                        infos["maxOccurs"])
  1218 
  1218 
  1219 def GetStructurePattern(classinfos):
  1219 def GetStructurePattern(classinfos):
  1220     base_structure_pattern = (
  1220     base_structure_pattern = (
  1221         classinfos["base"].StructurePattern.pattern[:-1]
  1221         classinfos["base"].StructurePattern.pattern[:-1]
  1254 
  1254 
  1255 def generateGetattrMethod(factory, class_definition, classinfos):
  1255 def generateGetattrMethod(factory, class_definition, classinfos):
  1256     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1256     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1257     optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
  1257     optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
  1258     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1258     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1259     
  1259 
  1260     def getattrMethod(self, name):
  1260     def getattrMethod(self, name):
  1261         if attributes.has_key(name):
  1261         if attributes.has_key(name):
  1262             attribute_infos = attributes[name]
  1262             attribute_infos = attributes[name]
  1263             attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"])
  1263             attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"])
  1264             value = self.get(name)
  1264             value = self.get(name)
  1267             elif attribute_infos.has_key("fixed"):
  1267             elif attribute_infos.has_key("fixed"):
  1268                 return attribute_infos["attr_type"]["extract"](attribute_infos["fixed"], extract=False)
  1268                 return attribute_infos["attr_type"]["extract"](attribute_infos["fixed"], extract=False)
  1269             elif attribute_infos.has_key("default"):
  1269             elif attribute_infos.has_key("default"):
  1270                 return attribute_infos["attr_type"]["extract"](attribute_infos["default"], extract=False)
  1270                 return attribute_infos["attr_type"]["extract"](attribute_infos["default"], extract=False)
  1271             return None
  1271             return None
  1272         
  1272 
  1273         elif elements.has_key(name):
  1273         elif elements.has_key(name):
  1274             element_infos = elements[name]
  1274             element_infos = elements[name]
  1275             element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
  1275             element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
  1276             if element_infos["type"] == CHOICE:
  1276             if element_infos["type"] == CHOICE:
  1277                 content = element_infos["elmt_type"]["choices_xpath"](self)
  1277                 content = element_infos["elmt_type"]["choices_xpath"](self)
  1278                 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
  1278                 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
  1279                     return content
  1279                     return content
  1280                 elif len(content) > 0:
  1280                 elif len(content) > 0:
  1281                     return content[0]
  1281                     return content[0]
  1282                 return None 
  1282                 return None
  1283             elif element_infos["type"] == ANY:
  1283             elif element_infos["type"] == ANY:
  1284                 return element_infos["elmt_type"]["extract"](self)
  1284                 return element_infos["elmt_type"]["extract"](self)
  1285             elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1285             elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1286                 return element_infos["elmt_type"]["extract"](self.text, extract=False)
  1286                 return element_infos["elmt_type"]["extract"](self.text, extract=False)
  1287             else:
  1287             else:
  1288                 element_name = factory.etreeNamespaceFormat % name
  1288                 element_name = factory.etreeNamespaceFormat % name
  1289                 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
  1289                 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
  1290                     values = self.findall(element_name)
  1290                     values = self.findall(element_name)
  1291                     if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1291                     if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1292                         return map(lambda value:
  1292                         return map(lambda value:
  1293                             element_infos["elmt_type"]["extract"](value.text, extract=False), 
  1293                             element_infos["elmt_type"]["extract"](value.text, extract=False),
  1294                             values)
  1294                             values)
  1295                     return values
  1295                     return values
  1296                 else:
  1296                 else:
  1297                     value = self.find(element_name)
  1297                     value = self.find(element_name)
  1298                     if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1298                     if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1299                         return element_infos["elmt_type"]["extract"](value.text, extract=False)
  1299                         return element_infos["elmt_type"]["extract"](value.text, extract=False)
  1300                     return value
  1300                     return value
  1301             
  1301 
  1302         elif classinfos.has_key("base"):
  1302         elif classinfos.has_key("base"):
  1303             return classinfos["base"].__getattr__(self, name)
  1303             return classinfos["base"].__getattr__(self, name)
  1304         
  1304 
  1305         return DefaultElementClass.__getattribute__(self, name)
  1305         return DefaultElementClass.__getattribute__(self, name)
  1306     
  1306 
  1307     return getattrMethod
  1307     return getattrMethod
  1308 
  1308 
  1309 def generateSetattrMethod(factory, class_definition, classinfos):
  1309 def generateSetattrMethod(factory, class_definition, classinfos):
  1310     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1310     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1311     optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
  1311     optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
  1312     elements = OrderedDict([(element["name"], element) for element in classinfos["elements"]])
  1312     elements = OrderedDict([(element["name"], element) for element in classinfos["elements"]])
  1313     
  1313 
  1314     def setattrMethod(self, name, value):
  1314     def setattrMethod(self, name, value):
  1315         if attributes.has_key(name):
  1315         if attributes.has_key(name):
  1316             attribute_infos = attributes[name]
  1316             attribute_infos = attributes[name]
  1317             attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"])
  1317             attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"])
  1318             if optional_attributes.get(name, False):
  1318             if optional_attributes.get(name, False):
  1321                     self.attrib.pop(name, None)
  1321                     self.attrib.pop(name, None)
  1322                     return
  1322                     return
  1323             elif attribute_infos.has_key("fixed"):
  1323             elif attribute_infos.has_key("fixed"):
  1324                 return
  1324                 return
  1325             return self.set(name, attribute_infos["attr_type"]["generate"](value))
  1325             return self.set(name, attribute_infos["attr_type"]["generate"](value))
  1326         
  1326 
  1327         elif elements.has_key(name):
  1327         elif elements.has_key(name):
  1328             element_infos = elements[name]
  1328             element_infos = elements[name]
  1329             element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
  1329             element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
  1330             if element_infos["type"] == ANY:
  1330             if element_infos["type"] == ANY:
  1331                 element_infos["elmt_type"]["generate"](self, value)
  1331                 element_infos["elmt_type"]["generate"](self, value)
  1332             
  1332 
  1333             elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1333             elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1334                 self.text = element_infos["elmt_type"]["generate"](value)
  1334                 self.text = element_infos["elmt_type"]["generate"](value)
  1335             
  1335 
  1336             else:
  1336             else:
  1337                 prefix = ("%s:" % factory.TargetNamespace
  1337                 prefix = ("%s:" % factory.TargetNamespace
  1338                           if factory.TargetNamespace is not None else "")
  1338                           if factory.TargetNamespace is not None else "")
  1339                 element_xpath = (prefix + name
  1339                 element_xpath = (prefix + name
  1340                                  if name != "content"
  1340                                  if name != "content"
  1341                                  else elements["content"]["elmt_type"]["choices_xpath"].path)
  1341                                  else elements["content"]["elmt_type"]["choices_xpath"].path)
  1342                 
  1342 
  1343                 for element in self.xpath(element_xpath, namespaces=factory.NSMAP):
  1343                 for element in self.xpath(element_xpath, namespaces=factory.NSMAP):
  1344                     self.remove(element)
  1344                     self.remove(element)
  1345                 
  1345 
  1346                 if value is not None:
  1346                 if value is not None:
  1347                     element_idx = elements.keys().index(name)
  1347                     element_idx = elements.keys().index(name)
  1348                     if element_idx > 0:
  1348                     if element_idx > 0:
  1349                         previous_elements_xpath = "|".join(map(
  1349                         previous_elements_xpath = "|".join(map(
  1350                             lambda x: prefix + x
  1350                             lambda x: prefix + x
  1351                                       if x != "content"
  1351                                       if x != "content"
  1352                                       else elements["content"]["elmt_type"]["choices_xpath"].path,
  1352                                       else elements["content"]["elmt_type"]["choices_xpath"].path,
  1353                             elements.keys()[:element_idx]))
  1353                             elements.keys()[:element_idx]))
  1354                         
  1354 
  1355                         insertion_point = len(self.xpath(previous_elements_xpath, namespaces=factory.NSMAP))
  1355                         insertion_point = len(self.xpath(previous_elements_xpath, namespaces=factory.NSMAP))
  1356                     else:
  1356                     else:
  1357                         insertion_point = 0
  1357                         insertion_point = 0
  1358                     
  1358 
  1359                     if not isinstance(value, ListType):
  1359                     if not isinstance(value, ListType):
  1360                         value = [value]
  1360                         value = [value]
  1361                     
  1361 
  1362                     for element in reversed(value):
  1362                     for element in reversed(value):
  1363                         if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1363                         if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1364                             tmp_element = etree.Element(factory.etreeNamespaceFormat % name)
  1364                             tmp_element = etree.Element(factory.etreeNamespaceFormat % name)
  1365                             tmp_element.text = element_infos["elmt_type"]["generate"](element)
  1365                             tmp_element.text = element_infos["elmt_type"]["generate"](element)
  1366                             element = tmp_element
  1366                             element = tmp_element
  1367                         self.insert(insertion_point, element)
  1367                         self.insert(insertion_point, element)
  1368         
  1368 
  1369         elif classinfos.has_key("base"):
  1369         elif classinfos.has_key("base"):
  1370             return classinfos["base"].__setattr__(self, name, value)
  1370             return classinfos["base"].__setattr__(self, name, value)
  1371         
  1371 
  1372         else:
  1372         else:
  1373             raise AttributeError("'%s' can't have an attribute '%s'." % (self.__class__.__name__, name))
  1373             raise AttributeError("'%s' can't have an attribute '%s'." % (self.__class__.__name__, name))
  1374         
  1374 
  1375     return setattrMethod
  1375     return setattrMethod
  1376 
  1376 
  1377 def gettypeinfos(name, facets):
  1377 def gettypeinfos(name, facets):
  1378     if facets.has_key("enumeration") and facets["enumeration"][0] is not None:
  1378     if facets.has_key("enumeration") and facets["enumeration"][0] is not None:
  1379         return facets["enumeration"][0]
  1379         return facets["enumeration"][0]
  1396         attr_list = []
  1396         attr_list = []
  1397         if classinfos.has_key("base"):
  1397         if classinfos.has_key("base"):
  1398             attr_list.extend(classinfos["base"].getElementAttributes(self))
  1398             attr_list.extend(classinfos["base"].getElementAttributes(self))
  1399         for attr in classinfos["attributes"]:
  1399         for attr in classinfos["attributes"]:
  1400             if attr["use"] != "prohibited":
  1400             if attr["use"] != "prohibited":
  1401                 attr_params = {"name" : attr["name"], "use" : attr["use"], 
  1401                 attr_params = {"name" : attr["name"], "use" : attr["use"],
  1402                     "type" : gettypeinfos(attr["attr_type"]["basename"], attr["attr_type"]["facets"]),
  1402                     "type" : gettypeinfos(attr["attr_type"]["basename"], attr["attr_type"]["facets"]),
  1403                     "value" : getattr(self, attr["name"], "")}
  1403                     "value" : getattr(self, attr["name"], "")}
  1404                 attr_list.append(attr_params)
  1404                 attr_list.append(attr_params)
  1405         return attr_list
  1405         return attr_list
  1406     return getElementAttributes
  1406     return getElementAttributes
  1407 
  1407 
  1408 def generateGetElementInfos(factory, classinfos):
  1408 def generateGetElementInfos(factory, classinfos):
  1409     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1409     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1410     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1410     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1411     
  1411 
  1412     def getElementInfos(self, name, path=None, derived=False):
  1412     def getElementInfos(self, name, path=None, derived=False):
  1413         attr_type = "element"
  1413         attr_type = "element"
  1414         value = None
  1414         value = None
  1415         use = "required"
  1415         use = "required"
  1416         children = []
  1416         children = []
  1417         if path is not None:
  1417         if path is not None:
  1418             parts = path.split(".", 1)
  1418             parts = path.split(".", 1)
  1419             if attributes.has_key(parts[0]):
  1419             if attributes.has_key(parts[0]):
  1420                 if len(parts) != 1:
  1420                 if len(parts) != 1:
  1421                     raise ValueError("Wrong path!")
  1421                     raise ValueError("Wrong path!")
  1422                 attr_type = gettypeinfos(attributes[parts[0]]["attr_type"]["basename"], 
  1422                 attr_type = gettypeinfos(attributes[parts[0]]["attr_type"]["basename"],
  1423                                          attributes[parts[0]]["attr_type"]["facets"])
  1423                                          attributes[parts[0]]["attr_type"]["facets"])
  1424                 value = getattr(self, parts[0], "")
  1424                 value = getattr(self, parts[0], "")
  1425             elif elements.has_key(parts[0]):
  1425             elif elements.has_key(parts[0]):
  1426                 if elements[parts[0]]["elmt_type"]["type"] == SIMPLETYPE:
  1426                 if elements[parts[0]]["elmt_type"]["type"] == SIMPLETYPE:
  1427                     if len(parts) != 1:
  1427                     if len(parts) != 1:
  1428                         raise ValueError("Wrong path!")
  1428                         raise ValueError("Wrong path!")
  1429                     attr_type = gettypeinfos(elements[parts[0]]["elmt_type"]["basename"], 
  1429                     attr_type = gettypeinfos(elements[parts[0]]["elmt_type"]["basename"],
  1430                                              elements[parts[0]]["elmt_type"]["facets"])
  1430                                              elements[parts[0]]["elmt_type"]["facets"])
  1431                     value = getattr(self, parts[0], "")
  1431                     value = getattr(self, parts[0], "")
  1432                 elif parts[0] == "content":
  1432                 elif parts[0] == "content":
  1433                     return self.content.getElementInfos(self.content.getLocalTag(), path)
  1433                     return self.content.getElementInfos(self.content.getLocalTag(), path)
  1434                 else:
  1434                 else:
  1461                     else:
  1461                     else:
  1462                         value = self.content.getLocalTag()
  1462                         value = self.content.getLocalTag()
  1463                         if self.content is not None:
  1463                         if self.content is not None:
  1464                             children.extend(self.content.getElementInfos(value)["children"])
  1464                             children.extend(self.content.getElementInfos(value)["children"])
  1465                 elif element["elmt_type"]["type"] == SIMPLETYPE:
  1465                 elif element["elmt_type"]["type"] == SIMPLETYPE:
  1466                     children.append({"name": element_name, "require": element["minOccurs"] != 0, 
  1466                     children.append({"name": element_name, "require": element["minOccurs"] != 0,
  1467                         "type": gettypeinfos(element["elmt_type"]["basename"], 
  1467                         "type": gettypeinfos(element["elmt_type"]["basename"],
  1468                                              element["elmt_type"]["facets"]),
  1468                                              element["elmt_type"]["facets"]),
  1469                         "value": getattr(self, element_name, None)})
  1469                         "value": getattr(self, element_name, None)})
  1470                 else:
  1470                 else:
  1471                     instance = getattr(self, element_name, None)
  1471                     instance = getattr(self, element_name, None)
  1472                     if instance is None:
  1472                     if instance is None:
  1476     return getElementInfos
  1476     return getElementInfos
  1477 
  1477 
  1478 def generateSetElementValue(factory, classinfos):
  1478 def generateSetElementValue(factory, classinfos):
  1479     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1479     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1480     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1480     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1481     
  1481 
  1482     def setElementValue(self, path, value):
  1482     def setElementValue(self, path, value):
  1483         if path is not None:
  1483         if path is not None:
  1484             parts = path.split(".", 1)
  1484             parts = path.split(".", 1)
  1485             if attributes.has_key(parts[0]):
  1485             if attributes.has_key(parts[0]):
  1486                 if len(parts) != 1:
  1486                 if len(parts) != 1:
  1487                     raise ValueError("Wrong path!")
  1487                     raise ValueError("Wrong path!")
  1488                 if attributes[parts[0]]["attr_type"]["basename"] == "boolean":
  1488                 if attributes[parts[0]]["attr_type"]["basename"] == "boolean":
  1489                     setattr(self, parts[0], value)
  1489                     setattr(self, parts[0], value)
  1490                 elif attributes[parts[0]]["use"] == "optional" and value == "":
  1490                 elif attributes[parts[0]]["use"] == "optional" and value == "":
  1491                     if attributes[parts[0]].has_key("default"):
  1491                     if attributes[parts[0]].has_key("default"):
  1492                         setattr(self, parts[0], 
  1492                         setattr(self, parts[0],
  1493                             attributes[parts[0]]["attr_type"]["extract"](
  1493                             attributes[parts[0]]["attr_type"]["extract"](
  1494                                 attributes[parts[0]]["default"], False))
  1494                                 attributes[parts[0]]["default"], False))
  1495                     else:
  1495                     else:
  1496                         setattr(self, parts[0], None)
  1496                         setattr(self, parts[0], None)
  1497                 else:
  1497                 else:
  1678 """
  1678 """
  1679 
  1679 
  1680 NAMESPACE_PATTERN = re.compile("xmlns(?:\:[^\=]*)?=\"[^\"]*\" ")
  1680 NAMESPACE_PATTERN = re.compile("xmlns(?:\:[^\=]*)?=\"[^\"]*\" ")
  1681 
  1681 
  1682 class DefaultElementClass(etree.ElementBase):
  1682 class DefaultElementClass(etree.ElementBase):
  1683     
  1683 
  1684     StructurePattern = re.compile("$")
  1684     StructurePattern = re.compile("$")
  1685     
  1685 
  1686     def _init_(self):
  1686     def _init_(self):
  1687         pass
  1687         pass
  1688     
  1688 
  1689     def getLocalTag(self):
  1689     def getLocalTag(self):
  1690         return etree.QName(self.tag).localname
  1690         return etree.QName(self.tag).localname
  1691         
  1691 
  1692     def tostring(self):
  1692     def tostring(self):
  1693         return NAMESPACE_PATTERN.sub("", etree.tostring(self, pretty_print=True, encoding='utf-8')).decode('utf-8')
  1693         return NAMESPACE_PATTERN.sub("", etree.tostring(self, pretty_print=True, encoding='utf-8')).decode('utf-8')
  1694 
  1694 
  1695 class XMLElementClassLookUp(etree.PythonElementClassLookup):
  1695 class XMLElementClassLookUp(etree.PythonElementClassLookup):
  1696     
  1696 
  1697     def __init__(self, classes, *args, **kwargs):
  1697     def __init__(self, classes, *args, **kwargs):
  1698         etree.PythonElementClassLookup.__init__(self, *args, **kwargs)
  1698         etree.PythonElementClassLookup.__init__(self, *args, **kwargs)
  1699         self.LookUpClasses = classes
  1699         self.LookUpClasses = classes
  1700     
  1700 
  1701     def GetElementClass(self, element_tag, parent_tag=None, default=DefaultElementClass):
  1701     def GetElementClass(self, element_tag, parent_tag=None, default=DefaultElementClass):
  1702         element_class = self.LookUpClasses.get(element_tag, (default, None))
  1702         element_class = self.LookUpClasses.get(element_tag, (default, None))
  1703         if not isinstance(element_class, DictType):
  1703         if not isinstance(element_class, DictType):
  1704             if isinstance(element_class[0], (StringType, UnicodeType)):
  1704             if isinstance(element_class[0], (StringType, UnicodeType)):
  1705                 return self.GetElementClass(element_class[0], default=default)
  1705                 return self.GetElementClass(element_class[0], default=default)
  1706             return element_class[0]
  1706             return element_class[0]
  1707         
  1707 
  1708         element_with_parent_class = element_class.get(parent_tag, default)
  1708         element_with_parent_class = element_class.get(parent_tag, default)
  1709         if isinstance(element_with_parent_class, (StringType, UnicodeType)):
  1709         if isinstance(element_with_parent_class, (StringType, UnicodeType)):
  1710             return self.GetElementClass(element_with_parent_class, default=default)
  1710             return self.GetElementClass(element_with_parent_class, default=default)
  1711         return element_with_parent_class
  1711         return element_with_parent_class
  1712         
  1712 
  1713     def lookup(self, document, element):
  1713     def lookup(self, document, element):
  1714         parent = element.getparent()
  1714         parent = element.getparent()
  1715         element_class = self.GetElementClass(element.tag, 
  1715         element_class = self.GetElementClass(element.tag,
  1716             parent.tag if parent is not None else None)
  1716             parent.tag if parent is not None else None)
  1717         if isinstance(element_class, ListType):
  1717         if isinstance(element_class, ListType):
  1718             children = "".join([
  1718             children = "".join([
  1719                 "%s " % etree.QName(child.tag).localname
  1719                 "%s " % etree.QName(child.tag).localname
  1720                 for child in element])
  1720                 for child in element])
  1739                 for name, uri in namespaces.iteritems()}
  1739                 for name, uri in namespaces.iteritems()}
  1740         else:
  1740         else:
  1741             self.RootNSMAP = namespaces
  1741             self.RootNSMAP = namespaces
  1742         self.BaseClass = base_class
  1742         self.BaseClass = base_class
  1743         self.XSDSchema = xsd_schema
  1743         self.XSDSchema = xsd_schema
  1744     
  1744 
  1745     def set_element_class_lookup(self, class_lookup):
  1745     def set_element_class_lookup(self, class_lookup):
  1746         etree.XMLParser.set_element_class_lookup(self, class_lookup)
  1746         etree.XMLParser.set_element_class_lookup(self, class_lookup)
  1747         self.ClassLookup = class_lookup
  1747         self.ClassLookup = class_lookup
  1748     
  1748 
  1749     def LoadXMLString(self, xml_string):
  1749     def LoadXMLString(self, xml_string):
  1750         tree = etree.fromstring(xml_string, self)
  1750         tree = etree.fromstring(xml_string, self)
  1751         if not self.XSDSchema.validate(tree):
  1751         if not self.XSDSchema.validate(tree):
  1752             error = self.XSDSchema.error_log.last_error
  1752             error = self.XSDSchema.error_log.last_error
  1753             return tree, (error.line, error.message)
  1753             return tree, (error.line, error.message)
  1754         return tree, None 
  1754         return tree, None
  1755     
  1755 
  1756     def Dumps(self, xml_obj):
  1756     def Dumps(self, xml_obj):
  1757         return etree.tostring(xml_obj, encoding='utf-8')
  1757         return etree.tostring(xml_obj, encoding='utf-8')
  1758     
  1758 
  1759     def Loads(self, xml_string):
  1759     def Loads(self, xml_string):
  1760         return etree.fromstring(xml_string, self)
  1760         return etree.fromstring(xml_string, self)
  1761     
  1761 
  1762     def CreateRoot(self):
  1762     def CreateRoot(self):
  1763         if self.BaseClass is not None:
  1763         if self.BaseClass is not None:
  1764             root = self.makeelement(
  1764             root = self.makeelement(
  1765                 self.DefaultNamespaceFormat % self.BaseClass[0],
  1765                 self.DefaultNamespaceFormat % self.BaseClass[0],
  1766                 nsmap=self.RootNSMAP)
  1766                 nsmap=self.RootNSMAP)
  1767             root._init_()
  1767             root._init_()
  1768             return root
  1768             return root
  1769         return None
  1769         return None
  1770     
  1770 
  1771     def GetElementClass(self, element_tag, parent_tag=None):
  1771     def GetElementClass(self, element_tag, parent_tag=None):
  1772         return self.ClassLookup.GetElementClass(
  1772         return self.ClassLookup.GetElementClass(
  1773             self.DefaultNamespaceFormat % element_tag, 
  1773             self.DefaultNamespaceFormat % element_tag,
  1774             self.DefaultNamespaceFormat % parent_tag 
  1774             self.DefaultNamespaceFormat % parent_tag
  1775             if parent_tag is not None else parent_tag, 
  1775             if parent_tag is not None else parent_tag,
  1776             None)
  1776             None)
  1777     
  1777 
  1778     def CreateElement(self, element_tag, parent_tag=None, class_idx=None):
  1778     def CreateElement(self, element_tag, parent_tag=None, class_idx=None):
  1779         element_class = self.GetElementClass(element_tag, parent_tag)
  1779         element_class = self.GetElementClass(element_tag, parent_tag)
  1780         if isinstance(element_class, ListType):
  1780         if isinstance(element_class, ListType):
  1781             if class_idx is not None and class_idx < len(element_class):
  1781             if class_idx is not None and class_idx < len(element_class):
  1782                 new_element = element_class[class_idx]()
  1782                 new_element = element_class[class_idx]()
  1785         else:
  1785         else:
  1786             new_element = element_class()
  1786             new_element = element_class()
  1787         DefaultElementClass.__setattr__(new_element, "tag", self.DefaultNamespaceFormat % element_tag)
  1787         DefaultElementClass.__setattr__(new_element, "tag", self.DefaultNamespaceFormat % element_tag)
  1788         new_element._init_()
  1788         new_element._init_()
  1789         return new_element
  1789         return new_element
  1790     
  1790 
  1791 def GenerateParser(factory, xsdstring):
  1791 def GenerateParser(factory, xsdstring):
  1792     ComputedClasses = factory.CreateClasses()
  1792     ComputedClasses = factory.CreateClasses()
  1793     
  1793 
  1794     if factory.FileName is not None:
  1794     if factory.FileName is not None:
  1795         ComputedClasses = ComputedClasses[factory.FileName]
  1795         ComputedClasses = ComputedClasses[factory.FileName]
  1796     BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass]
  1796     BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass]
  1797        
  1797 
  1798     parser = XMLClassParser(
  1798     parser = XMLClassParser(
  1799         factory.NSMAP,
  1799         factory.NSMAP,
  1800         factory.etreeNamespaceFormat,
  1800         factory.etreeNamespaceFormat,
  1801         BaseClass[0] if len(BaseClass) == 1 else None,
  1801         BaseClass[0] if len(BaseClass) == 1 else None,
  1802         etree.XMLSchema(etree.fromstring(xsdstring)),
  1802         etree.XMLSchema(etree.fromstring(xsdstring)),
  1803         strip_cdata = False, remove_blank_text=True)
  1803         strip_cdata = False, remove_blank_text=True)
  1804     class_lookup = XMLElementClassLookUp(factory.ComputedClassesLookUp)
  1804     class_lookup = XMLElementClassLookUp(factory.ComputedClassesLookUp)
  1805     parser.set_element_class_lookup(class_lookup)
  1805     parser.set_element_class_lookup(class_lookup)
  1806     
  1806 
  1807     return parser
  1807     return parser
  1808