xmlclass/xmlclass.py
changeset 1784 64beb9e9c749
parent 1782 5b6ad7a7fd9d
child 1826 91796f408540
equal deleted inserted replaced
1729:31e63e25b4cc 1784:64beb9e9c749
    20 #
    20 #
    21 # You should have received a copy of the GNU General Public License
    21 # You should have received a copy of the GNU General Public License
    22 # along with this program; if not, write to the Free Software
    22 # along with this program; if not, write to the Free Software
    23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    24 
    24 
    25 import os, sys
    25 import os
       
    26 import sys
    26 import re
    27 import re
    27 import datetime
    28 import datetime
    28 from types import *
    29 from types import *
    29 from xml.dom import minidom
    30 from xml.dom import minidom
    30 from xml.sax.saxutils import escape, unescape, quoteattr
    31 from xml.sax.saxutils import escape, unescape, quoteattr
    31 from lxml import etree
    32 from lxml import etree
    32 from new import classobj
    33 from new import classobj
    33 from collections import OrderedDict
    34 from collections import OrderedDict
    34 
    35 
       
    36 
    35 def CreateNode(name):
    37 def CreateNode(name):
    36     node = minidom.Node()
    38     node = minidom.Node()
    37     node.nodeName = name
    39     node.nodeName = name
    38     node._attrs = {}
    40     node._attrs = {}
    39     node.childNodes = []
    41     node.childNodes = []
    40     return node
    42     return node
    41 
    43 
       
    44 
    42 def NodeRenameAttr(node, old_name, new_name):
    45 def NodeRenameAttr(node, old_name, new_name):
    43     node._attrs[new_name] = node._attrs.pop(old_name)
    46     node._attrs[new_name] = node._attrs.pop(old_name)
       
    47 
    44 
    48 
    45 def NodeSetAttr(node, name, value):
    49 def NodeSetAttr(node, name, value):
    46     attr = minidom.Attr(name)
    50     attr = minidom.Attr(name)
    47     text = minidom.Text()
    51     text = minidom.Text()
    48     text.data = value
    52     text.data = value
    49     attr.childNodes[0] = text
    53     attr.childNodes[0] = text
    50     node._attrs[name] = attr
    54     node._attrs[name] = attr
       
    55 
    51 
    56 
    52 """
    57 """
    53 Regular expression models for checking all kind of string values defined in XML
    58 Regular expression models for checking all kind of string values defined in XML
    54 standard
    59 standard
    55 """
    60 """
    70 """
    75 """
    71 time_model = re.compile('([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)(?:Z)?$')
    76 time_model = re.compile('([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)(?:Z)?$')
    72 date_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$')
    77 date_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$')
    73 datetime_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})[ T]([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$')
    78 datetime_model = re.compile('([0-9]{4})-([0-9]{2})-([0-9]{2})[ T]([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]*)?)((?:[\-\+][0-9]{2}:[0-9]{2})|Z)?$')
    74 
    79 
       
    80 
    75 class xml_timezone(datetime.tzinfo):
    81 class xml_timezone(datetime.tzinfo):
    76 
    82 
    77     def SetOffset(self, offset):
    83     def SetOffset(self, offset):
    78         if offset == "Z":
    84         if offset == "Z":
    79             self.__offset = timedelta(minutes = 0)
    85             self.__offset = timedelta(minutes=0)
    80             self.__name = "UTC"
    86             self.__name = "UTC"
    81         else:
    87         else:
    82             sign = {"-" : -1, "+" : 1}[offset[0]]
    88             sign = {"-": -1, "+": 1}[offset[0]]
    83             hours, minutes = [int(val) for val in offset[1:].split(":")]
    89             hours, minutes = [int(val) for val in offset[1:].split(":")]
    84             self.__offset = timedelta(minutes=sign * (hours * 60 + minutes))
    90             self.__offset = timedelta(minutes=sign * (hours * 60 + minutes))
    85             self.__name = ""
    91             self.__name = ""
    86 
    92 
    87     def utcoffset(self, dt):
    93     def utcoffset(self, dt):
    91         return self.__name
    97         return self.__name
    92 
    98 
    93     def dst(self, dt):
    99     def dst(self, dt):
    94         return ZERO
   100         return ZERO
    95 
   101 
    96 [SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE, 
   102 
    97  ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG, CONSTRAINT,
   103 [
       
   104     SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE,
       
   105     ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG, CONSTRAINT,
    98 ] = range(13)
   106 ] = range(13)
       
   107 
    99 
   108 
   100 def NotSupportedYet(type):
   109 def NotSupportedYet(type):
   101     """
   110     """
   102     Function that generates a function that point out to user that datatype
   111     Function that generates a function that point out to user that datatype
   103     used is not supported by xmlclass yet
   112     used is not supported by xmlclass yet
   104     @param type: data type
   113     @param type: data type
   105     @return: function generated
   114     @return: function generated
   106     """
   115     """
   107     def GetUnknownValue(attr):
   116     def GetUnknownValue(attr):
   108         raise ValueError("\"%s\" type isn't supported by \"xmlclass\" yet!" % \
   117         raise ValueError("\"%s\" type isn't supported by \"xmlclass\" yet!" % type)
   109                          type)
       
   110     return GetUnknownValue
   118     return GetUnknownValue
   111 
   119 
   112 """
   120 
   113 This function calculates the number of whitespace for indentation
       
   114 """
       
   115 def getIndent(indent, balise):
   121 def getIndent(indent, balise):
       
   122     """
       
   123     This function calculates the number of whitespace for indentation
       
   124     """
   116     first = indent * 2
   125     first = indent * 2
   117     second = first + len(balise) + 1
   126     second = first + len(balise) + 1
   118     return u'\t'.expandtabs(first), u'\t'.expandtabs(second)
   127     return u'\t'.expandtabs(first), u'\t'.expandtabs(second)
   119 
   128 
   120 
   129 
   138         return text
   147         return text
   139 
   148 
   140 
   149 
   141 def GetNormalizedString(attr, extract=True):
   150 def GetNormalizedString(attr, extract=True):
   142     """
   151     """
   143     Function that normalizes a string according to XML 1.0. Replace  
   152     Function that normalizes a string according to XML 1.0. Replace
   144     tabulations, line feed and carriage return by white space
   153     tabulations, line feed and carriage return by white space
   145     @param attr: tree node containing data to extract or data to normalize
   154     @param attr: tree node containing data to extract or data to normalize
   146     @param extract: attr is a tree node or not
   155     @param extract: attr is a tree node or not
   147     @return: data normalized as string
   156     @return: data normalized as string
   148     """
   157     """
   153     return value.replace("\t", " ").replace("\r", " ").replace("\n", " ")
   162     return value.replace("\t", " ").replace("\r", " ").replace("\n", " ")
   154 
   163 
   155 
   164 
   156 def GetToken(attr, extract=True):
   165 def GetToken(attr, extract=True):
   157     """
   166     """
   158     Function that tokenizes a string according to XML 1.0. Remove any leading  
   167     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 
   168     and trailing white space and replace internal sequence of two or more
   160     spaces by only one white space
   169     spaces by only one white space
   161     @param attr: tree node containing data to extract or data to tokenize
   170     @param attr: tree node containing data to extract or data to tokenize
   162     @param extract: attr is a tree node or not
   171     @param extract: attr is a tree node or not
   163     @return: data tokenized as string
   172     @return: data tokenized as string
   164     """
   173     """
   165     return " ".join([part for part in 
   174     return " ".join([part for part in
   166                      GetNormalizedString(attr, extract).split(" ")
   175                      GetNormalizedString(attr, extract).split(" ")
   167                      if part])
   176                      if part])
   168 
   177 
   169 
   178 
   170 def GetHexInteger(attr, extract=True):
   179 def GetHexInteger(attr, extract=True):
   180         value = attr
   189         value = attr
   181     if len(value) % 2 != 0:
   190     if len(value) % 2 != 0:
   182         raise ValueError("\"%s\" isn't a valid hexadecimal integer!" % value)
   191         raise ValueError("\"%s\" isn't a valid hexadecimal integer!" % value)
   183     try:
   192     try:
   184         return int(value, 16)
   193         return int(value, 16)
   185     except:
   194     except Exception:
   186         raise ValueError("\"%s\" isn't a valid hexadecimal integer!" % value)
   195         raise ValueError("\"%s\" isn't a valid hexadecimal integer!" % value)
   187 
   196 
   188 
   197 
   189 def GenerateIntegerExtraction(minInclusive=None, maxInclusive=None, 
   198 def GenerateIntegerExtraction(minInclusive=None, maxInclusive=None,
   190                               minExclusive=None, maxExclusive=None):
   199                               minExclusive=None, maxExclusive=None):
   191     """
   200     """
   192     Function that generates an extraction function for integer defining min and
   201     Function that generates an extraction function for integer defining min and
   193     max of integer value
   202     max of integer value
   194     @param minInclusive: inclusive minimum
   203     @param minInclusive: inclusive minimum
   210         else:
   219         else:
   211             value = attr
   220             value = attr
   212         try:
   221         try:
   213             # TODO: permit to write value like 1E2
   222             # TODO: permit to write value like 1E2
   214             value = int(value)
   223             value = int(value)
   215         except:
   224         except Exception:
   216             raise ValueError("\"%s\" isn't a valid integer!" % value)
   225             raise ValueError("\"%s\" isn't a valid integer!" % value)
   217         if minInclusive is not None and value < minInclusive:
   226         if minInclusive is not None and value < minInclusive:
   218             raise ValueError("\"%d\" isn't greater or equal to %d!" % \
   227             raise ValueError("\"%d\" isn't greater or equal to %d!" %
   219                              (value, minInclusive))
   228                              (value, minInclusive))
   220         if maxInclusive is not None and value > maxInclusive:
   229         if maxInclusive is not None and value > maxInclusive:
   221             raise ValueError("\"%d\" isn't lesser or equal to %d!" % \
   230             raise ValueError("\"%d\" isn't lesser or equal to %d!" %
   222                              (value, maxInclusive))
   231                              (value, maxInclusive))
   223         if minExclusive is not None and value <= minExclusive:
   232         if minExclusive is not None and value <= minExclusive:
   224             raise ValueError("\"%d\" isn't greater than %d!" % \
   233             raise ValueError("\"%d\" isn't greater than %d!" %
   225                              (value, minExclusive))
   234                              (value, minExclusive))
   226         if maxExclusive is not None and value >= maxExclusive:
   235         if maxExclusive is not None and value >= maxExclusive:
   227             raise ValueError("\"%d\" isn't lesser than %d!" % \
   236             raise ValueError("\"%d\" isn't lesser than %d!" %
   228                              (value, maxExclusive))
   237                              (value, maxExclusive))
   229         return value
   238         return value
   230     return GetInteger
   239     return GetInteger
   231 
   240 
   232 
   241 
   234     """
   243     """
   235     Function that generates an extraction function for float
   244     Function that generates an extraction function for float
   236     @param type: name of the type of float
   245     @param type: name of the type of float
   237     @return: function generated
   246     @return: function generated
   238     """
   247     """
   239     def GetFloat(attr, extract = True):
   248     def GetFloat(attr, extract=True):
   240         """
   249         """
   241         Function that extracts a float from a tree node or a string
   250         Function that extracts a float from a tree node or a string
   242         @param attr: tree node containing data to extract or data as a string
   251         @param attr: tree node containing data to extract or data as a string
   243         @param extract: attr is a tree node or not
   252         @param extract: attr is a tree node or not
   244         @return: data as a float
   253         @return: data as a float
   249             value = attr
   258             value = attr
   250         if value in extra_values:
   259         if value in extra_values:
   251             return value
   260             return value
   252         try:
   261         try:
   253             return float(value)
   262             return float(value)
   254         except:
   263         except Exception:
   255             raise ValueError("\"%s\" isn't a valid %s!" % (value, type))
   264             raise ValueError("\"%s\" isn't a valid %s!" % (value, type))
   256     return GetFloat
   265     return GetFloat
   257 
   266 
   258 
   267 
   259 def GetBoolean(attr, extract=True):
   268 def GetBoolean(attr, extract=True):
   399                 return value
   408                 return value
   400             else:
   409             else:
   401                 raise ValueError("Member limit can't be defined to \"unbounded\"!")
   410                 raise ValueError("Member limit can't be defined to \"unbounded\"!")
   402         try:
   411         try:
   403             limit = int(value)
   412             limit = int(value)
   404         except:
   413         except Exception:
   405             raise ValueError("\"%s\" isn't a valid value for this member limit!" % value)
   414             raise ValueError("\"%s\" isn't a valid value for this member limit!" % value)
   406         if limit < 0:
   415         if limit < 0:
   407             raise ValueError("Member limit can't be negative!")
   416             raise ValueError("Member limit can't be negative!")
   408         elif min is not None and limit < min:
   417         elif min is not None and limit < min:
   409             raise ValueError("Member limit can't be lower than \"%d\"!" % min)
   418             raise ValueError("Member limit can't be lower than \"%d\"!" % min)
   433         else:
   442         else:
   434             value = attr
   443             value = attr
   435         if value in list:
   444         if value in list:
   436             return value
   445             return value
   437         else:
   446         else:
   438             raise ValueError("\"%s\" isn't a valid value for %s!" % \
   447             raise ValueError(
   439                              (value, type))
   448                 "\"%s\" isn't a valid value for %s!" % (value, type))
   440     return GetEnumerated
   449     return GetEnumerated
   441 
   450 
   442 
   451 
   443 def GetNamespaces(attr, extract=True):
   452 def GetNamespaces(attr, extract=True):
   444     """
   453     """
   495             values = []
   504             values = []
   496             for item in value.split(" "):
   505             for item in value.split(" "):
   497                 if item in list:
   506                 if item in list:
   498                     values.append(item)
   507                     values.append(item)
   499                 else:
   508                 else:
   500                     raise ValueError("\"%s\" isn't a valid value for %s!" % \
   509                     raise ValueError(
   501                                      (value, type))
   510                         "\"%s\" isn't a valid value for %s!" % (value, type))
   502             return values
   511             return values
   503     return GetLists
   512     return GetLists
   504 
   513 
   505 
   514 
   506 def GenerateModelNameListExtraction(type, model):
   515 def GenerateModelNameListExtraction(type, model):
   515         """
   524         """
   516         Function that extracts a list of string from a tree node or not and
   525         Function that extracts a list of string from a tree node or not and
   517         check that all extracted items match the model
   526         check that all extracted items match the model
   518         @param attr: tree node containing data to extract or data as a string
   527         @param attr: tree node containing data to extract or data as a string
   519         @param extract: attr is a tree node or not
   528         @param extract: attr is a tree node or not
   520         @return: data as a list of string if matching 
   529         @return: data as a list of string if matching
   521         """
   530         """
   522         if extract:
   531         if extract:
   523             value = GetAttributeValue(attr)
   532             value = GetAttributeValue(attr)
   524         else:
   533         else:
   525             value = attr
   534             value = attr
   527         for item in value.split(" "):
   536         for item in value.split(" "):
   528             result = model.match(item)
   537             result = model.match(item)
   529             if result is not None:
   538             if result is not None:
   530                 values.append(item)
   539                 values.append(item)
   531             else:
   540             else:
   532                 raise ValueError("\"%s\" isn't a valid value for %s!" % \
   541                 raise ValueError("\"%s\" isn't a valid value for %s!" % (value, type))
   533                                  (value, type))
       
   534         return values
   542         return values
   535     return GetModelNameList
   543     return GetModelNameList
   536 
   544 
       
   545 
   537 def GenerateAnyInfos(infos):
   546 def GenerateAnyInfos(infos):
   538     
   547 
   539     def GetTextElement(tree):
   548     def GetTextElement(tree):
   540         if infos["namespace"][0] == "##any":
   549         if infos["namespace"][0] == "##any":
   541             return tree.xpath("p")[0]
   550             return tree.xpath("p")[0]
   542         return tree.xpath("ns:p", namespaces={"ns": infos["namespace"][0]})[0]
   551         return tree.xpath("ns:p", namespaces={"ns": infos["namespace"][0]})[0]
   543     
   552 
   544     def ExtractAny(tree):
   553     def ExtractAny(tree):
   545         return GetTextElement(tree).text
   554         return GetTextElement(tree).text
   546     
   555 
   547     def GenerateAny(tree, value):
   556     def GenerateAny(tree, value):
   548         GetTextElement(tree).text = etree.CDATA(value)
   557         GetTextElement(tree).text = etree.CDATA(value)
   549         
   558 
   550     def InitialAny():
   559     def InitialAny():
   551         if infos["namespace"][0] == "##any":
   560         if infos["namespace"][0] == "##any":
   552             element_name = "p"
   561             element_name = "p"
   553         else:
   562         else:
   554             element_name = "{%s}p" % infos["namespace"][0]
   563             element_name = "{%s}p" % infos["namespace"][0]
   555         p = etree.Element(element_name)
   564         p = etree.Element(element_name)
   556         p.text = etree.CDATA("")
   565         p.text = etree.CDATA("")
   557         return p
   566         return p
   558         
   567 
   559     return {
   568     return {
   560         "type": COMPLEXTYPE, 
   569         "type": COMPLEXTYPE,
   561         "extract": ExtractAny,
   570         "extract": ExtractAny,
   562         "generate": GenerateAny,
   571         "generate": GenerateAny,
   563         "initial": InitialAny,
   572         "initial": InitialAny,
   564         "check": lambda x: isinstance(x, (StringType, UnicodeType, etree.ElementBase))
   573         "check": lambda x: isinstance(x, (StringType, UnicodeType, etree.ElementBase))
   565     }
   574     }
       
   575 
   566 
   576 
   567 def GenerateTagInfos(infos):
   577 def GenerateTagInfos(infos):
   568     def ExtractTag(tree):
   578     def ExtractTag(tree):
   569         if len(tree._attrs) > 0:
   579         if len(tree._attrs) > 0:
   570             raise ValueError("\"%s\" musn't have attributes!" % infos["name"])
   580             raise ValueError("\"%s\" musn't have attributes!" % infos["name"])
   572             raise ValueError("\"%s\" musn't have children!" % infos["name"])
   582             raise ValueError("\"%s\" musn't have children!" % infos["name"])
   573         if infos["minOccurs"] == 0:
   583         if infos["minOccurs"] == 0:
   574             return True
   584             return True
   575         else:
   585         else:
   576             return None
   586             return None
   577     
   587 
   578     def GenerateTag(value, name=None, indent=0):
   588     def GenerateTag(value, name=None, indent=0):
   579         if name is not None and not (infos["minOccurs"] == 0 and value is None):
   589         if name is not None and not (infos["minOccurs"] == 0 and value is None):
   580             ind1, ind2 = getIndent(indent, name)
   590             ind1, ind2 = getIndent(indent, name)
   581             return ind1 + "<%s/>\n" % name
   591             return ind1 + "<%s/>\n" % name
   582         else:
   592         else:
   583             return ""
   593             return ""
   584     
   594 
   585     return {
   595     return {
   586         "type": TAG, 
   596         "type": TAG,
   587         "extract": ExtractTag,
   597         "extract": ExtractTag,
   588         "generate": GenerateTag,
   598         "generate": GenerateTag,
   589         "initial": lambda: None,
   599         "initial": lambda: None,
   590         "check": lambda x: x == None or infos["minOccurs"] == 0 and value == True
   600         "check": lambda x: x is None or infos["minOccurs"] == 0 and value
   591     }
   601     }
       
   602 
   592 
   603 
   593 def FindTypeInfos(factory, infos):
   604 def FindTypeInfos(factory, infos):
   594     if isinstance(infos, (UnicodeType, StringType)):
   605     if isinstance(infos, (UnicodeType, StringType)):
   595         namespace, name = DecomposeQualifiedName(infos)
   606         namespace, name = DecomposeQualifiedName(infos)
   596         return factory.GetQualifiedNameInfos(name, namespace)
   607         return factory.GetQualifiedNameInfos(name, namespace)
   597     return infos
   608     return infos
   598     
   609 
       
   610 
   599 def GetElementInitialValue(factory, infos):
   611 def GetElementInitialValue(factory, infos):
   600     infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
   612     infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
   601     if infos["minOccurs"] == 1:
   613     if infos["minOccurs"] == 1:
   602         element_name = factory.etreeNamespaceFormat % infos["name"]
   614         element_name = factory.etreeNamespaceFormat % infos["name"]
   603         if infos["elmt_type"]["type"] == SIMPLETYPE:
   615         if infos["elmt_type"]["type"] == SIMPLETYPE:
   613                     value._init_()
   625                     value._init_()
   614                 return value
   626                 return value
   615         return [initial_value() for i in xrange(infos["minOccurs"])]
   627         return [initial_value() for i in xrange(infos["minOccurs"])]
   616     else:
   628     else:
   617         return []
   629         return []
       
   630 
   618 
   631 
   619 def GetContentInfos(name, choices):
   632 def GetContentInfos(name, choices):
   620     for choice_infos in choices:
   633     for choice_infos in choices:
   621         if choices_infos["type"] == "sequence":
   634         if choices_infos["type"] == "sequence":
   622             for element_infos in choices_infos["elements"]:
   635             for element_infos in choices_infos["elements"]:
   626                 elif element_infos["name"] == name:
   639                 elif element_infos["name"] == name:
   627                     return choices_infos
   640                     return choices_infos
   628         elif choice_infos["name"] == name:
   641         elif choice_infos["name"] == name:
   629             return choices_infos
   642             return choices_infos
   630     return None
   643     return None
       
   644 
   631 
   645 
   632 def ComputeContentChoices(factory, name, infos):
   646 def ComputeContentChoices(factory, name, infos):
   633     choices = []
   647     choices = []
   634     for choice in infos["choices"]:
   648     for choice in infos["choices"]:
   635         if choice["type"] == "sequence":
   649         if choice["type"] == "sequence":
   647             if choice_infos is not None:
   661             if choice_infos is not None:
   648                 choice["elmt_type"] = choice_infos
   662                 choice["elmt_type"] = choice_infos
   649         choices.append((choice["name"], choice))
   663         choices.append((choice["name"], choice))
   650     return choices
   664     return choices
   651 
   665 
       
   666 
   652 def GenerateContentInfos(factory, name, choices):
   667 def GenerateContentInfos(factory, name, choices):
   653     choices_dict = {}
   668     choices_dict = {}
   654     for choice_name, infos in choices:
   669     for choice_name, infos in choices:
   655         if choice_name == "sequence":
   670         if choice_name == "sequence":
   656             for element in infos["elements"]:
   671             for element in infos["elements"]:
   657                 if element["type"] == CHOICE:
   672                 if element["type"] == CHOICE:
   658                     element["elmt_type"] = GenerateContentInfos(factory, name, ComputeContentChoices(factory, name, element))
   673                     element["elmt_type"] = GenerateContentInfos(factory, name, ComputeContentChoices(factory, name, element))
   659                 elif choices_dict.has_key(element["name"]):
   674                 elif element["name"] in choices_dict:
   660                     raise ValueError("'%s' element defined two times in choice" % choice_name)
   675                     raise ValueError("'%s' element defined two times in choice" % choice_name)
   661                 else:
   676                 else:
   662                     choices_dict[element["name"]] = infos
   677                     choices_dict[element["name"]] = infos
   663         else:
   678         else:
   664             if choices_dict.has_key(choice_name):
   679             if choice_name in choices_dict:
   665                 raise ValueError("'%s' element defined two times in choice" % choice_name)
   680                 raise ValueError("'%s' element defined two times in choice" % choice_name)
   666             choices_dict[choice_name] = infos
   681             choices_dict[choice_name] = infos
   667     prefix = ("%s:" % factory.TargetNamespace
   682     prefix = ("%s:" % factory.TargetNamespace
   668               if factory.TargetNamespace is not None else "")
   683               if factory.TargetNamespace is not None else "")
   669     choices_xpath = "|".join(map(lambda x: prefix + x, choices_dict.keys()))
   684     choices_xpath = "|".join(map(lambda x: prefix + x, choices_dict.keys()))
   670     
   685 
   671     def GetContentInitial():
   686     def GetContentInitial():
   672         content_name, infos = choices[0]
   687         content_name, infos = choices[0]
   673         if content_name == "sequence":
   688         if content_name == "sequence":
   674             content_value = []
   689             content_value = []
   675             for i in xrange(infos["minOccurs"]):
   690             for i in xrange(infos["minOccurs"]):
   676                 for element_infos in infos["elements"]:
   691                 for element_infos in infos["elements"]:
   677                     content_value.extend(GetElementInitialValue(factory, element_infos))
   692                     content_value.extend(GetElementInitialValue(factory, element_infos))
   678         else:
   693         else:
   679             content_value = GetElementInitialValue(factory, infos)
   694             content_value = GetElementInitialValue(factory, infos)
   680         return content_value
   695         return content_value
   681         
   696 
   682     return {
   697     return {
   683         "type": COMPLEXTYPE,
   698         "type": COMPLEXTYPE,
   684         "choices_xpath": etree.XPath(choices_xpath, namespaces=factory.NSMAP),
   699         "choices_xpath": etree.XPath(choices_xpath, namespaces=factory.NSMAP),
   685         "initial": GetContentInitial,
   700         "initial": GetContentInitial,
   686     }
   701     }
   687 
   702 
   688 #-------------------------------------------------------------------------------
   703 # -------------------------------------------------------------------------------
   689 #                           Structure extraction functions
   704 #                           Structure extraction functions
   690 #-------------------------------------------------------------------------------
   705 # -------------------------------------------------------------------------------
   691 
   706 
   692 
   707 
   693 def DecomposeQualifiedName(name):
   708 def DecomposeQualifiedName(name):
   694     result = QName_model.match(name)
   709     result = QName_model.match(name)
   695     if not result:
   710     if not result:
   696         raise ValueError("\"%s\" isn't a valid QName value!" % name) 
   711         raise ValueError("\"%s\" isn't a valid QName value!" % name)
   697     parts = result.groups()[0].split(':')
   712     parts = result.groups()[0].split(':')
   698     if len(parts) == 1:
   713     if len(parts) == 1:
   699         return None, parts[0]
   714         return None, parts[0]
   700     return parts
   715     return parts
   701     
   716 
   702 def GenerateElement(element_name, attributes, elements_model, 
   717 
       
   718 def GenerateElement(element_name, attributes, elements_model,
   703                     accept_text=False):
   719                     accept_text=False):
   704     def ExtractElement(factory, node):
   720     def ExtractElement(factory, node):
   705         attrs = factory.ExtractNodeAttrs(element_name, node, attributes)
   721         attrs = factory.ExtractNodeAttrs(element_name, node, attributes)
   706         children_structure = ""
   722         children_structure = ""
   707         children_infos = []
   723         children_infos = []
   708         children = []
   724         children = []
   709         for child in node.childNodes:
   725         for child in node.childNodes:
   710             if child.nodeName not in ["#comment", "#text"]:
   726             if child.nodeName not in ["#comment", "#text"]:
   711                 namespace, childname = DecomposeQualifiedName(child.nodeName)
   727                 namespace, childname = DecomposeQualifiedName(child.nodeName)
   712                 children_structure += "%s "%childname
   728                 children_structure += "%s " % childname
   713         result = elements_model.match(children_structure)
   729         result = elements_model.match(children_structure)
   714         if not result:
   730         if not result:
   715             raise ValueError("Invalid structure for \"%s\" children!. First element invalid." % node.nodeName)
   731             raise ValueError("Invalid structure for \"%s\" children!. First element invalid." % node.nodeName)
   716         valid = result.groups()[0]
   732         valid = result.groups()[0]
   717         if len(valid) < len(children_structure):
   733         if len(valid) < len(children_structure):
   724                 else:
   740                 else:
   725                     namespace, childname = DecomposeQualifiedName(child.nodeName)
   741                     namespace, childname = DecomposeQualifiedName(child.nodeName)
   726                     infos = factory.GetQualifiedNameInfos(childname, namespace)
   742                     infos = factory.GetQualifiedNameInfos(childname, namespace)
   727                     if infos["type"] != SYNTAXELEMENT:
   743                     if infos["type"] != SYNTAXELEMENT:
   728                         raise ValueError("\"%s\" can't be a member child!" % name)
   744                         raise ValueError("\"%s\" can't be a member child!" % name)
   729                     if infos["extract"].has_key(element_name):
   745                     if element_name in infos["extract"]:
   730                         children.append(infos["extract"][element_name](factory, child))
   746                         children.append(infos["extract"][element_name](factory, child))
   731                     else:
   747                     else:
   732                         children.append(infos["extract"]["default"](factory, child))
   748                         children.append(infos["extract"]["default"](factory, child))
   733         return node.nodeName, attrs, children
   749         return node.nodeName, attrs, children
   734     return ExtractElement
   750     return ExtractElement
   735 
   751 
   736 
   752 
   737 """
       
   738 Class that generate class from an XML Tree
       
   739 """
       
   740 class ClassFactory:
   753 class ClassFactory:
       
   754     """
       
   755     Class that generate class from an XML Tree
       
   756     """
   741 
   757 
   742     def __init__(self, document, filepath=None, debug=False):
   758     def __init__(self, document, filepath=None, debug=False):
   743         self.Document = document
   759         self.Document = document
   744         if filepath is not None:
   760         if filepath is not None:
   745             self.BaseFolder, self.FileName = os.path.split(filepath)
   761             self.BaseFolder, self.FileName = os.path.split(filepath)
   746         else:
   762         else:
   747             self.BaseFolder = self.FileName = None
   763             self.BaseFolder = self.FileName = None
   748         self.Debug = debug
   764         self.Debug = debug
   749         
   765 
   750         # Dictionary for stocking Classes and Types definitions created from
   766         # Dictionary for stocking Classes and Types definitions created from
   751         # the XML tree
   767         # the XML tree
   752         self.XMLClassDefinitions = {}
   768         self.XMLClassDefinitions = {}
   753         
   769 
   754         self.DefinedNamespaces = {}
   770         self.DefinedNamespaces = {}
   755         self.NSMAP = {}
   771         self.NSMAP = {}
   756         self.Namespaces = {}
   772         self.Namespaces = {}
   757         self.SchemaNamespace = None
   773         self.SchemaNamespace = None
   758         self.TargetNamespace = None
   774         self.TargetNamespace = None
   759         self.etreeNamespaceFormat = "%s"
   775         self.etreeNamespaceFormat = "%s"
   760         
   776 
   761         self.CurrentCompilations = []
   777         self.CurrentCompilations = []
   762         
   778 
   763         # Dictionaries for stocking Classes and Types generated
   779         # Dictionaries for stocking Classes and Types generated
   764         self.ComputeAfter = []
   780         self.ComputeAfter = []
   765         if self.FileName is not None:
   781         if self.FileName is not None:
   766             self.ComputedClasses = {self.FileName: {}}
   782             self.ComputedClasses = {self.FileName: {}}
   767         else:
   783         else:
   771         self.EquivalentClassesParent = {}
   787         self.EquivalentClassesParent = {}
   772         self.AlreadyComputed = {}
   788         self.AlreadyComputed = {}
   773 
   789 
   774     def GetQualifiedNameInfos(self, name, namespace=None, canbenone=False):
   790     def GetQualifiedNameInfos(self, name, namespace=None, canbenone=False):
   775         if namespace is None:
   791         if namespace is None:
   776             if self.Namespaces[self.SchemaNamespace].has_key(name):
   792             if name in self.Namespaces[self.SchemaNamespace]:
   777                 return self.Namespaces[self.SchemaNamespace][name]
   793                 return self.Namespaces[self.SchemaNamespace][name]
   778             for space, elements in self.Namespaces.iteritems():
   794             for space, elements in self.Namespaces.iteritems():
   779                 if space != self.SchemaNamespace and elements.has_key(name):
   795                 if space != self.SchemaNamespace and name in elements:
   780                     return elements[name]
   796                     return elements[name]
   781             parts = name.split("_", 1)
   797             parts = name.split("_", 1)
   782             if len(parts) > 1:
   798             if len(parts) > 1:
   783                 group = self.GetQualifiedNameInfos(parts[0], namespace)
   799                 group = self.GetQualifiedNameInfos(parts[0], namespace)
   784                 if group is not None and group["type"] == ELEMENTSGROUP:
   800                 if group is not None and group["type"] == ELEMENTSGROUP:
   785                     elements = []
   801                     elements = []
   786                     if group.has_key("elements"):
   802                     if "elements" in group:
   787                         elements = group["elements"]
   803                         elements = group["elements"]
   788                     elif group.has_key("choices"):
   804                     elif "choices" in group:
   789                         elements = group["choices"]
   805                         elements = group["choices"]
   790                     for element in elements:
   806                     for element in elements:
   791                         if element["name"] == parts[1]:
   807                         if element["name"] == parts[1]:
   792                             return element
   808                             return element
   793             if not canbenone:
   809             if not canbenone:
   794                 raise ValueError("Unknown element \"%s\" for any defined namespaces!" % name)
   810                 raise ValueError("Unknown element \"%s\" for any defined namespaces!" % name)
   795         elif self.Namespaces.has_key(namespace):
   811         elif namespace in self.Namespaces:
   796             if self.Namespaces[namespace].has_key(name):
   812             if name in self.Namespaces[namespace]:
   797                 return self.Namespaces[namespace][name]
   813                 return self.Namespaces[namespace][name]
   798             parts = name.split("_", 1)
   814             parts = name.split("_", 1)
   799             if len(parts) > 1:
   815             if len(parts) > 1:
   800                 group = self.GetQualifiedNameInfos(parts[0], namespace)
   816                 group = self.GetQualifiedNameInfos(parts[0], namespace)
   801                 if group is not None and group["type"] == ELEMENTSGROUP:
   817                 if group is not None and group["type"] == ELEMENTSGROUP:
   802                     elements = []
   818                     elements = []
   803                     if group.has_key("elements"):
   819                     if "elements" in group:
   804                         elements = group["elements"]
   820                         elements = group["elements"]
   805                     elif group.has_key("choices"):
   821                     elif "choices" in group:
   806                         elements = group["choices"]
   822                         elements = group["choices"]
   807                     for element in elements:
   823                     for element in elements:
   808                         if element["name"] == parts[1]:
   824                         if element["name"] == parts[1]:
   809                             return element
   825                             return element
   810             if not canbenone:
   826             if not canbenone:
   813             raise ValueError("Unknown namespace \"%s\"!" % namespace)
   829             raise ValueError("Unknown namespace \"%s\"!" % namespace)
   814         return None
   830         return None
   815 
   831 
   816     def SplitQualifiedName(self, name, namespace=None, canbenone=False):
   832     def SplitQualifiedName(self, name, namespace=None, canbenone=False):
   817         if namespace is None:
   833         if namespace is None:
   818             if self.Namespaces[self.SchemaNamespace].has_key(name):
   834             if name in self.Namespaces[self.SchemaNamespace]:
   819                 return name, None
   835                 return name, None
   820             for space, elements in self.Namespaces.items():
   836             for space, elements in self.Namespaces.items():
   821                 if space != self.SchemaNamespace and elements.has_key(name):
   837                 if space != self.SchemaNamespace and name in elements:
   822                     return name, None
   838                     return name, None
   823             parts = name.split("_", 1)
   839             parts = name.split("_", 1)
   824             if len(parts) > 1:
   840             if len(parts) > 1:
   825                 group = self.GetQualifiedNameInfos(parts[0], namespace)
   841                 group = self.GetQualifiedNameInfos(parts[0], namespace)
   826                 if group is not None and group["type"] == ELEMENTSGROUP:
   842                 if group is not None and group["type"] == ELEMENTSGROUP:
   827                     elements = []
   843                     elements = []
   828                     if group.has_key("elements"):
   844                     if "elements" in group:
   829                         elements = group["elements"]
   845                         elements = group["elements"]
   830                     elif group.has_key("choices"):
   846                     elif "choices" in group:
   831                         elements = group["choices"]
   847                         elements = group["choices"]
   832                     for element in elements:
   848                     for element in elements:
   833                         if element["name"] == parts[1]:
   849                         if element["name"] == parts[1]:
   834                             return part[1], part[0]
   850                             return part[1], part[0]
   835             if not canbenone:
   851             if not canbenone:
   836                 raise ValueError("Unknown element \"%s\" for any defined namespaces!" % name)
   852                 raise ValueError("Unknown element \"%s\" for any defined namespaces!" % name)
   837         elif self.Namespaces.has_key(namespace):
   853         elif namespace in self.Namespaces:
   838             if self.Namespaces[namespace].has_key(name):
   854             if name in self.Namespaces[namespace]:
   839                 return name, None
   855                 return name, None
   840             parts = name.split("_", 1)
   856             parts = name.split("_", 1)
   841             if len(parts) > 1:
   857             if len(parts) > 1:
   842                 group = self.GetQualifiedNameInfos(parts[0], namespace)
   858                 group = self.GetQualifiedNameInfos(parts[0], namespace)
   843                 if group is not None and group["type"] == ELEMENTSGROUP:
   859                 if group is not None and group["type"] == ELEMENTSGROUP:
   844                     elements = []
   860                     elements = []
   845                     if group.has_key("elements"):
   861                     if "elements" in group:
   846                         elements = group["elements"]
   862                         elements = group["elements"]
   847                     elif group.has_key("choices"):
   863                     elif "choices" in group:
   848                         elements = group["choices"]
   864                         elements = group["choices"]
   849                     for element in elements:
   865                     for element in elements:
   850                         if element["name"] == parts[1]:
   866                         if element["name"] == parts[1]:
   851                             return parts[1], parts[0]
   867                             return parts[1], parts[0]
   852             if not canbenone:
   868             if not canbenone:
   856         return None, None
   872         return None, None
   857 
   873 
   858     def ExtractNodeAttrs(self, element_name, node, valid_attrs):
   874     def ExtractNodeAttrs(self, element_name, node, valid_attrs):
   859         attrs = {}
   875         attrs = {}
   860         for qualified_name, attr in node._attrs.items():
   876         for qualified_name, attr in node._attrs.items():
   861             namespace, name =  DecomposeQualifiedName(qualified_name)
   877             namespace, name = DecomposeQualifiedName(qualified_name)
   862             if name in valid_attrs:
   878             if name in valid_attrs:
   863                 infos = self.GetQualifiedNameInfos(name, namespace)
   879                 infos = self.GetQualifiedNameInfos(name, namespace)
   864                 if infos["type"] != SYNTAXATTRIBUTE:
   880                 if infos["type"] != SYNTAXATTRIBUTE:
   865                     raise ValueError("\"%s\" can't be a member attribute!" % name)
   881                     raise ValueError("\"%s\" can't be a member attribute!" % name)
   866                 elif name in attrs:
   882                 elif name in attrs:
   876                 self.NSMAP[name] = value
   892                 self.NSMAP[name] = value
   877             else:
   893             else:
   878                 raise ValueError("Invalid attribute \"%s\" for member \"%s\"!" % (qualified_name, node.nodeName))
   894                 raise ValueError("Invalid attribute \"%s\" for member \"%s\"!" % (qualified_name, node.nodeName))
   879         for attr in valid_attrs:
   895         for attr in valid_attrs:
   880             if attr not in attrs and \
   896             if attr not in attrs and \
   881                self.Namespaces[self.SchemaNamespace].has_key(attr) and \
   897                attr in self.Namespaces[self.SchemaNamespace] and \
   882                self.Namespaces[self.SchemaNamespace][attr].has_key("default"):
   898                "default" in self.Namespaces[self.SchemaNamespace][attr]:
   883                 if self.Namespaces[self.SchemaNamespace][attr]["default"].has_key(element_name):
   899                 if element_name in self.Namespaces[self.SchemaNamespace][attr]["default"]:
   884                     default = self.Namespaces[self.SchemaNamespace][attr]["default"][element_name]
   900                     default = self.Namespaces[self.SchemaNamespace][attr]["default"][element_name]
   885                 else:
   901                 else:
   886                     default = self.Namespaces[self.SchemaNamespace][attr]["default"]["default"]
   902                     default = self.Namespaces[self.SchemaNamespace][attr]["default"]["default"]
   887                 if default is not None:
   903                 if default is not None:
   888                     attrs[attr] = default
   904                     attrs[attr] = default
   890 
   906 
   891     def ReduceElements(self, elements, schema=False):
   907     def ReduceElements(self, elements, schema=False):
   892         result = []
   908         result = []
   893         for child_infos in elements:
   909         for child_infos in elements:
   894             if child_infos is not None:
   910             if child_infos is not None:
   895                 if child_infos[1].has_key("name") and schema:
   911                 if "name" in child_infos[1] and schema:
   896                     self.CurrentCompilations.append(child_infos[1]["name"])
   912                     self.CurrentCompilations.append(child_infos[1]["name"])
   897                 namespace, name = DecomposeQualifiedName(child_infos[0])
   913                 namespace, name = DecomposeQualifiedName(child_infos[0])
   898                 infos = self.GetQualifiedNameInfos(name, namespace)
   914                 infos = self.GetQualifiedNameInfos(name, namespace)
   899                 if infos["type"] != SYNTAXELEMENT:
   915                 if infos["type"] != SYNTAXELEMENT:
   900                     raise ValueError("\"%s\" can't be a member child!" % name)
   916                     raise ValueError("\"%s\" can't be a member child!" % name)
   901                 element = infos["reduce"](self, child_infos[1], child_infos[2])
   917                 element = infos["reduce"](self, child_infos[1], child_infos[2])
   902                 if element is not None:
   918                 if element is not None:
   903                     result.append(element)
   919                     result.append(element)
   904                 if child_infos[1].has_key("name") and schema:
   920                 if "name" in child_infos[1] and schema:
   905                     self.CurrentCompilations.pop(-1)
   921                     self.CurrentCompilations.pop(-1)
   906         annotations = []
   922         annotations = []
   907         children = []
   923         children = []
   908         for element in result:
   924         for element in result:
   909             if element["type"] == "annotation":
   925             if element["type"] == "annotation":
   911             else:
   927             else:
   912                 children.append(element)
   928                 children.append(element)
   913         return annotations, children
   929         return annotations, children
   914 
   930 
   915     def AddComplexType(self, typename, infos):
   931     def AddComplexType(self, typename, infos):
   916         if not self.XMLClassDefinitions.has_key(typename):
   932         if typename not in self.XMLClassDefinitions:
   917             self.XMLClassDefinitions[typename] = infos
   933             self.XMLClassDefinitions[typename] = infos
   918         else:
   934         else:
   919             raise ValueError("\"%s\" class already defined. Choose another name!" % typename)
   935             raise ValueError("\"%s\" class already defined. Choose another name!" % typename)
   920 
   936 
   921     def ParseSchema(self):
   937     def ParseSchema(self):
   922         pass
   938         pass
   923     
   939 
   924     def AddEquivalentClass(self, name, base):
   940     def AddEquivalentClass(self, name, base):
   925         if name != base:
   941         if name != base:
   926             equivalences = self.EquivalentClassesParent.setdefault(self.etreeNamespaceFormat % base, {})
   942             equivalences = self.EquivalentClassesParent.setdefault(self.etreeNamespaceFormat % base, {})
   927             equivalences[self.etreeNamespaceFormat % name] = True
   943             equivalences[self.etreeNamespaceFormat % name] = True
   928     
   944 
   929     def AddDistinctionBetweenParentsInLookupClass(
   945     def AddDistinctionBetweenParentsInLookupClass(
   930                                     self, lookup_classes, parent, typeinfos):
   946                                     self, lookup_classes, parent, typeinfos):
   931         parent = (self.etreeNamespaceFormat % parent 
   947         parent = (self.etreeNamespaceFormat % parent
   932                   if parent is not None else None)
   948                   if parent is not None else None)
   933         parent_class = lookup_classes.get(parent)
   949         parent_class = lookup_classes.get(parent)
   934         if parent_class is not None:
   950         if parent_class is not None:
   935             if isinstance(parent_class, ListType):
   951             if isinstance(parent_class, ListType):
   936                 if typeinfos not in parent_class:
   952                 if typeinfos not in parent_class:
   937                     lookup_classes[parent].append(typeinfos)
   953                     lookup_classes[parent].append(typeinfos)
   938             elif parent_class != typeinfos:
   954             elif parent_class != typeinfos:
   939                 lookup_classes[parent] = [typeinfos, parent_class]
   955                 lookup_classes[parent] = [typeinfos, parent_class]
   940         else:
   956         else:
   941             lookup_classes[parent] = typeinfos
   957             lookup_classes[parent] = typeinfos
   942     
   958 
   943     def AddToLookupClass(self, name, parent, typeinfos):
   959     def AddToLookupClass(self, name, parent, typeinfos):
   944         lookup_name = self.etreeNamespaceFormat % name
   960         lookup_name = self.etreeNamespaceFormat % name
   945         if isinstance(typeinfos, (StringType, UnicodeType)):
   961         if isinstance(typeinfos, (StringType, UnicodeType)):
   946             self.AddEquivalentClass(name, typeinfos)
   962             self.AddEquivalentClass(name, typeinfos)
   947             typeinfos = self.etreeNamespaceFormat % typeinfos
   963             typeinfos = self.etreeNamespaceFormat % typeinfos
   956                 self.etreeNamespaceFormat % lookup_classes[1]
   972                 self.etreeNamespaceFormat % lookup_classes[1]
   957                 if lookup_classes[1] is not None else None: lookup_classes[0]}
   973                 if lookup_classes[1] is not None else None: lookup_classes[0]}
   958             self.AddDistinctionBetweenParentsInLookupClass(
   974             self.AddDistinctionBetweenParentsInLookupClass(
   959                 lookup_classes, parent, typeinfos)
   975                 lookup_classes, parent, typeinfos)
   960             self.ComputedClassesLookUp[lookup_name] = lookup_classes
   976             self.ComputedClassesLookUp[lookup_name] = lookup_classes
   961     
   977 
   962     def ExtractTypeInfos(self, name, parent, typeinfos):
   978     def ExtractTypeInfos(self, name, parent, typeinfos):
   963         if isinstance(typeinfos, (StringType, UnicodeType)):
   979         if isinstance(typeinfos, (StringType, UnicodeType)):
   964             namespace, type_name = DecomposeQualifiedName(typeinfos)
   980             namespace, type_name = DecomposeQualifiedName(typeinfos)
   965             infos = self.GetQualifiedNameInfos(type_name, namespace)
   981             infos = self.GetQualifiedNameInfos(type_name, namespace)
   966             if name != "base":
   982             if name != "base":
   984                 return infos
  1000                 return infos
   985         elif typeinfos["type"] == COMPLEXTYPE:
  1001         elif typeinfos["type"] == COMPLEXTYPE:
   986             return self.CreateClass(name, parent, typeinfos)
  1002             return self.CreateClass(name, parent, typeinfos)
   987         elif typeinfos["type"] == SIMPLETYPE:
  1003         elif typeinfos["type"] == SIMPLETYPE:
   988             return typeinfos
  1004             return typeinfos
   989     
  1005 
   990     def GetEquivalentParents(self, parent):
  1006     def GetEquivalentParents(self, parent):
   991         return reduce(lambda x, y: x + y,
  1007         return reduce(lambda x, y: x + y,
   992             [[p] + self.GetEquivalentParents(p)
  1008                       [[p] + self.GetEquivalentParents(p)
   993              for p in self.EquivalentClassesParent.get(parent, {}).keys()], [])
  1009                        for p in self.EquivalentClassesParent.get(parent, {}).keys()], [])
   994     
  1010 
   995     """
  1011     """
   996     Methods that generates the classes
  1012     Methods that generates the classes
   997     """
  1013     """
   998     def CreateClasses(self):
  1014     def CreateClasses(self):
   999         self.ParseSchema()
  1015         self.ParseSchema()
  1013                     if result is not None and \
  1029                     if result is not None and \
  1014                        not isinstance(result, (UnicodeType, StringType)):
  1030                        not isinstance(result, (UnicodeType, StringType)):
  1015                         self.Namespaces[self.TargetNamespace][result["name"]] = result
  1031                         self.Namespaces[self.TargetNamespace][result["name"]] = result
  1016             elif infos["type"] == ELEMENTSGROUP:
  1032             elif infos["type"] == ELEMENTSGROUP:
  1017                 elements = []
  1033                 elements = []
  1018                 if infos.has_key("elements"):
  1034                 if "elements" in infos:
  1019                     elements = infos["elements"]
  1035                     elements = infos["elements"]
  1020                 elif infos.has_key("choices"):
  1036                 elif "choices" in infos:
  1021                     elements = infos["choices"]
  1037                     elements = infos["choices"]
  1022                 for element in elements:
  1038                 for element in elements:
  1023                     if not isinstance(element["elmt_type"], (UnicodeType, StringType)) and \
  1039                     if not isinstance(element["elmt_type"], (UnicodeType, StringType)) and \
  1024                        element["elmt_type"]["type"] == COMPLEXTYPE:
  1040                        element["elmt_type"]["type"] == COMPLEXTYPE:
  1025                         self.ComputeAfter.append((element["name"], infos["name"], element["elmt_type"]))
  1041                         self.ComputeAfter.append((element["name"], infos["name"], element["elmt_type"]))
  1026                         while len(self.ComputeAfter) > 0:
  1042                         while len(self.ComputeAfter) > 0:
  1027                             result = self.CreateClass(*self.ComputeAfter.pop(0))
  1043                             result = self.CreateClass(*self.ComputeAfter.pop(0))
  1028                             if result is not None and \
  1044                             if result is not None and \
  1029                                not isinstance(result, (UnicodeType, StringType)):
  1045                                not isinstance(result, (UnicodeType, StringType)):
  1030                                 self.Namespaces[self.TargetNamespace][result["name"]] = result
  1046                                 self.Namespaces[self.TargetNamespace][result["name"]] = result
  1031         
  1047 
  1032         for name, parents in self.ComputedClassesLookUp.iteritems():
  1048         for name, parents in self.ComputedClassesLookUp.iteritems():
  1033             if isinstance(parents, DictType):
  1049             if isinstance(parents, DictType):
  1034                 computed_classes = parents.items()
  1050                 computed_classes = parents.items()
  1035             elif parents[1] is not None:
  1051             elif parents[1] is not None:
  1036                 computed_classes = [(self.etreeNamespaceFormat % parents[1], parents[0])]
  1052                 computed_classes = [(self.etreeNamespaceFormat % parents[1], parents[0])]
  1040                 for equivalent_parent in self.GetEquivalentParents(parent):
  1056                 for equivalent_parent in self.GetEquivalentParents(parent):
  1041                     if not isinstance(parents, DictType):
  1057                     if not isinstance(parents, DictType):
  1042                         parents = dict(computed_classes)
  1058                         parents = dict(computed_classes)
  1043                         self.ComputedClassesLookUp[name] = parents
  1059                         self.ComputedClassesLookUp[name] = parents
  1044                     parents[equivalent_parent] = computed_class
  1060                     parents[equivalent_parent] = computed_class
  1045         
  1061 
  1046         return self.ComputedClasses
  1062         return self.ComputedClasses
  1047 
  1063 
  1048     def CreateClass(self, name, parent, classinfos, baseclass = False):
  1064     def CreateClass(self, name, parent, classinfos, baseclass=False):
  1049         if parent is not None:
  1065         if parent is not None:
  1050             classname = "%s_%s" % (parent, name)
  1066             classname = "%s_%s" % (parent, name)
  1051         else:
  1067         else:
  1052             classname = name
  1068             classname = name
  1053         
  1069 
  1054         # Checks that classe haven't been generated yet
  1070         # Checks that classe haven't been generated yet
  1055         if self.AlreadyComputed.get(classname, False):
  1071         if self.AlreadyComputed.get(classname, False):
  1056             return self.ComputedClassesInfos.get(classname, None)
  1072             return self.ComputedClassesInfos.get(classname, None)
  1057         
  1073 
  1058         # If base classes haven't been generated
  1074         # If base classes haven't been generated
  1059         bases = []
  1075         bases = []
  1060         base_infos = classinfos.get("base", None)
  1076         base_infos = classinfos.get("base", None)
  1061         if base_infos is not None:
  1077         if base_infos is not None:
  1062             namespace, base_name = DecomposeQualifiedName(base_infos)
  1078             namespace, base_name = DecomposeQualifiedName(base_infos)
  1086                     raise ValueError("No class found for base type")
  1102                     raise ValueError("No class found for base type")
  1087                 bases.append(classinfos["base"])
  1103                 bases.append(classinfos["base"])
  1088         bases.append(DefaultElementClass)
  1104         bases.append(DefaultElementClass)
  1089         bases = tuple(bases)
  1105         bases = tuple(bases)
  1090         classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass}
  1106         classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass}
  1091         
  1107 
  1092         self.AlreadyComputed[classname] = True
  1108         self.AlreadyComputed[classname] = True
  1093         
  1109 
  1094         for attribute in classinfos["attributes"]:
  1110         for attribute in classinfos["attributes"]:
  1095             infos = self.ExtractTypeInfos(attribute["name"], name, attribute["attr_type"])
  1111             infos = self.ExtractTypeInfos(attribute["name"], name, attribute["attr_type"])
  1096             if infos is not None:                    
  1112             if infos is not None:
  1097                 if infos["type"] != SIMPLETYPE:
  1113                 if infos["type"] != SIMPLETYPE:
  1098                     raise ValueError("\"%s\" type is not a simple type!" % attribute["attr_type"])
  1114                     raise ValueError("\"%s\" type is not a simple type!" % attribute["attr_type"])
  1099                 attrname = attribute["name"]
  1115                 attrname = attribute["name"]
  1100                 if attribute["use"] == "optional":
  1116                 if attribute["use"] == "optional":
  1101                     classmembers["add%s"%attrname] = generateAddMethod(attrname, self, attribute)
  1117                     classmembers["add%s" % attrname] = generateAddMethod(attrname, self, attribute)
  1102                     classmembers["delete%s"%attrname] = generateDeleteMethod(attrname)
  1118                     classmembers["delete%s" % attrname] = generateDeleteMethod(attrname)
  1103                 classmembers["set%s"%attrname] = generateSetMethod(attrname)
  1119                 classmembers["set%s" % attrname] = generateSetMethod(attrname)
  1104                 classmembers["get%s"%attrname] = generateGetMethod(attrname)
  1120                 classmembers["get%s" % attrname] = generateGetMethod(attrname)
  1105             else:
  1121             else:
  1106                 raise ValueError("\"%s\" type unrecognized!" % attribute["attr_type"])
  1122                 raise ValueError("\"%s\" type unrecognized!" % attribute["attr_type"])
  1107             attribute["attr_type"] = infos
  1123             attribute["attr_type"] = infos
  1108         
  1124 
  1109         for element in classinfos["elements"]:
  1125         for element in classinfos["elements"]:
  1110             if element["type"] == CHOICE:
  1126             if element["type"] == CHOICE:
  1111                 elmtname = element["name"]
  1127                 elmtname = element["name"]
  1112                 choices = ComputeContentChoices(self, name, element)
  1128                 choices = ComputeContentChoices(self, name, element)
  1113                 classmembers["get%schoices"%elmtname] = generateGetChoicesMethod(element["choices"])
  1129                 classmembers["get%schoices" % elmtname] = generateGetChoicesMethod(element["choices"])
  1114                 if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1:
  1130                 if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1:
  1115                     classmembers["append%sbytype" % elmtname] = generateAppendChoiceByTypeMethod(element["maxOccurs"], self, element["choices"])
  1131                     classmembers["append%sbytype" % elmtname] = generateAppendChoiceByTypeMethod(element["maxOccurs"], self, element["choices"])
  1116                     classmembers["insert%sbytype" % elmtname] = generateInsertChoiceByTypeMethod(element["maxOccurs"], self, element["choices"])
  1132                     classmembers["insert%sbytype" % elmtname] = generateInsertChoiceByTypeMethod(element["maxOccurs"], self, element["choices"])
  1117                 else:
  1133                 else:
  1118                     classmembers["set%sbytype" % elmtname] = generateSetChoiceByTypeMethod(self, element["choices"])
  1134                     classmembers["set%sbytype" % elmtname] = generateSetChoiceByTypeMethod(self, element["choices"])
  1139                 if element["minOccurs"] == 0:
  1155                 if element["minOccurs"] == 0:
  1140                     classmembers["add%s" % elmtname] = generateAddMethod(elmtname, self, element)
  1156                     classmembers["add%s" % elmtname] = generateAddMethod(elmtname, self, element)
  1141                     classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname)
  1157                     classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname)
  1142             classmembers["set%s" % elmtname] = generateSetMethod(elmtname)
  1158             classmembers["set%s" % elmtname] = generateSetMethod(elmtname)
  1143             classmembers["get%s" % elmtname] = generateGetMethod(elmtname)
  1159             classmembers["get%s" % elmtname] = generateGetMethod(elmtname)
  1144             
  1160 
  1145         classmembers["_init_"] = generateInitMethod(self, classinfos)
  1161         classmembers["_init_"] = generateInitMethod(self, classinfos)
  1146         classmembers["StructurePattern"] = GetStructurePattern(classinfos)
  1162         classmembers["StructurePattern"] = GetStructurePattern(classinfos)
  1147         classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos)
  1163         classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos)
  1148         classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos)
  1164         classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos)
  1149         classmembers["setElementValue"] = generateSetElementValue(self, classinfos)
  1165         classmembers["setElementValue"] = generateSetElementValue(self, classinfos)
  1150         
  1166 
  1151         class_definition = classobj(str(name), bases, classmembers)
  1167         class_definition = classobj(str(name), bases, classmembers)
  1152         setattr(class_definition, "__getattr__", generateGetattrMethod(self, class_definition, classinfos))
  1168         setattr(class_definition, "__getattr__", generateGetattrMethod(self, class_definition, classinfos))
  1153         setattr(class_definition, "__setattr__", generateSetattrMethod(self, class_definition, classinfos))
  1169         setattr(class_definition, "__setattr__", generateSetattrMethod(self, class_definition, classinfos))
  1154         class_infos = {"type": COMPILEDCOMPLEXTYPE,
  1170         class_infos = {
  1155                        "name": classname,
  1171             "type": COMPILEDCOMPLEXTYPE,
  1156                        "initial": generateClassCreateFunction(class_definition),
  1172             "name": classname,
       
  1173             "initial": generateClassCreateFunction(class_definition),
  1157         }
  1174         }
  1158         
  1175 
  1159         if self.FileName is not None:
  1176         if self.FileName is not None:
  1160             self.ComputedClasses[self.FileName][classname] = class_definition
  1177             self.ComputedClasses[self.FileName][classname] = class_definition
  1161         else:
  1178         else:
  1162             self.ComputedClasses[classname] = class_definition
  1179             self.ComputedClasses[classname] = class_definition
  1163         self.ComputedClassesInfos[classname] = class_infos
  1180         self.ComputedClassesInfos[classname] = class_infos
  1164         
  1181 
  1165         self.AddToLookupClass(name, parent, class_definition)
  1182         self.AddToLookupClass(name, parent, class_definition)
  1166         self.AddToLookupClass(classname, None, class_definition)
  1183         self.AddToLookupClass(classname, None, class_definition)
  1167             
  1184 
  1168         return class_infos
  1185         return class_infos
  1169 
  1186 
  1170     """
  1187     """
  1171     Methods that print the classes generated
  1188     Methods that print the classes generated
  1172     """
  1189     """
  1181                 for classname, xmlclass in class_items:
  1198                 for classname, xmlclass in class_items:
  1182                     print "%s: %s" % (classname, str(xmlclass))
  1199                     print "%s: %s" % (classname, str(xmlclass))
  1183         else:
  1200         else:
  1184             for classname, xmlclass in items:
  1201             for classname, xmlclass in items:
  1185                 print "%s: %s" % (classname, str(xmlclass))
  1202                 print "%s: %s" % (classname, str(xmlclass))
  1186         
  1203 
  1187     def PrintClassNames(self):
  1204     def PrintClassNames(self):
  1188         classnames = self.XMLClassDefinitions.keys()
  1205         classnames = self.XMLClassDefinitions.keys()
  1189         classnames.sort()
  1206         classnames.sort()
  1190         for classname in classnames:
  1207         for classname in classnames:
  1191             print classname
  1208             print classname
  1192 
  1209 
  1193 """
  1210 
  1194 Method that generate the method for generating the xml tree structure model by 
       
  1195 following the attributes list defined
       
  1196 """
       
  1197 def ComputeMultiplicity(name, infos):
  1211 def ComputeMultiplicity(name, infos):
       
  1212     """
       
  1213     Method that generate the method for generating the xml tree structure model by
       
  1214     following the attributes list defined
       
  1215     """
  1198     if infos["minOccurs"] == 0:
  1216     if infos["minOccurs"] == 0:
  1199         if infos["maxOccurs"] == "unbounded":
  1217         if infos["maxOccurs"] == "unbounded":
  1200             return "(?:%s)*" % name
  1218             return "(?:%s)*" % name
  1201         elif infos["maxOccurs"] == 1:
  1219         elif infos["maxOccurs"] == 1:
  1202             return "(?:%s)?" % name
  1220             return "(?:%s)?" % name
  1211             return "(?:%s){1,%d}" % (name, infos["maxOccurs"])
  1229             return "(?:%s){1,%d}" % (name, infos["maxOccurs"])
  1212     else:
  1230     else:
  1213         if infos["maxOccurs"] == "unbounded":
  1231         if infos["maxOccurs"] == "unbounded":
  1214             return "(?:%s){%d,}" % (name, infos["minOccurs"], name)
  1232             return "(?:%s){%d,}" % (name, infos["minOccurs"], name)
  1215         else:
  1233         else:
  1216             return "(?:%s){%d,%d}" % (name, infos["minOccurs"], 
  1234             return "(?:%s){%d,%d}" % (name,
  1217                                        infos["maxOccurs"])
  1235                                       infos["minOccurs"],
       
  1236                                       infos["maxOccurs"])
       
  1237 
  1218 
  1238 
  1219 def GetStructurePattern(classinfos):
  1239 def GetStructurePattern(classinfos):
  1220     base_structure_pattern = (
  1240     base_structure_pattern = (
  1221         classinfos["base"].StructurePattern.pattern[:-1]
  1241         classinfos["base"].StructurePattern.pattern[:-1]
  1222         if classinfos.has_key("base") else "")
  1242         if "base" in classinfos else "")
  1223     elements = []
  1243     elements = []
  1224     for element in classinfos["elements"]:
  1244     for element in classinfos["elements"]:
  1225         if element["type"] == ANY:
  1245         if element["type"] == ANY:
  1226             infos = element.copy()
  1246             infos = element.copy()
  1227             infos["minOccurs"] = 0
  1247             infos["minOccurs"] = 0
  1242     if classinfos.get("order", True) or len(elements) == 0:
  1262     if classinfos.get("order", True) or len(elements) == 0:
  1243         return re.compile(base_structure_pattern + "".join(elements) + "$")
  1263         return re.compile(base_structure_pattern + "".join(elements) + "$")
  1244     else:
  1264     else:
  1245         raise ValueError("XSD structure not yet supported!")
  1265         raise ValueError("XSD structure not yet supported!")
  1246 
  1266 
  1247 """
  1267 
  1248 Method that generate the method for creating a class instance
       
  1249 """
       
  1250 def generateClassCreateFunction(class_definition):
  1268 def generateClassCreateFunction(class_definition):
       
  1269     """
       
  1270     Method that generate the method for creating a class instance
       
  1271     """
  1251     def classCreatefunction():
  1272     def classCreatefunction():
  1252         return class_definition()
  1273         return class_definition()
  1253     return classCreatefunction
  1274     return classCreatefunction
       
  1275 
  1254 
  1276 
  1255 def generateGetattrMethod(factory, class_definition, classinfos):
  1277 def generateGetattrMethod(factory, class_definition, classinfos):
  1256     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1278     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"])
  1279     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"]])
  1280     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1259     
  1281 
  1260     def getattrMethod(self, name):
  1282     def getattrMethod(self, name):
  1261         if attributes.has_key(name):
  1283         if name in attributes:
  1262             attribute_infos = attributes[name]
  1284             attribute_infos = attributes[name]
  1263             attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"])
  1285             attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"])
  1264             value = self.get(name)
  1286             value = self.get(name)
  1265             if value is not None:
  1287             if value is not None:
  1266                 return attribute_infos["attr_type"]["extract"](value, extract=False)
  1288                 return attribute_infos["attr_type"]["extract"](value, extract=False)
  1267             elif attribute_infos.has_key("fixed"):
  1289             elif "fixed" in attribute_infos:
  1268                 return attribute_infos["attr_type"]["extract"](attribute_infos["fixed"], extract=False)
  1290                 return attribute_infos["attr_type"]["extract"](attribute_infos["fixed"], extract=False)
  1269             elif attribute_infos.has_key("default"):
  1291             elif "default" in attribute_infos:
  1270                 return attribute_infos["attr_type"]["extract"](attribute_infos["default"], extract=False)
  1292                 return attribute_infos["attr_type"]["extract"](attribute_infos["default"], extract=False)
  1271             return None
  1293             return None
  1272         
  1294 
  1273         elif elements.has_key(name):
  1295         elif name in elements:
  1274             element_infos = elements[name]
  1296             element_infos = elements[name]
  1275             element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
  1297             element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
  1276             if element_infos["type"] == CHOICE:
  1298             if element_infos["type"] == CHOICE:
  1277                 content = element_infos["elmt_type"]["choices_xpath"](self)
  1299                 content = element_infos["elmt_type"]["choices_xpath"](self)
  1278                 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
  1300                 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
  1279                     return content
  1301                     return content
  1280                 elif len(content) > 0:
  1302                 elif len(content) > 0:
  1281                     return content[0]
  1303                     return content[0]
  1282                 return None 
  1304                 return None
  1283             elif element_infos["type"] == ANY:
  1305             elif element_infos["type"] == ANY:
  1284                 return element_infos["elmt_type"]["extract"](self)
  1306                 return element_infos["elmt_type"]["extract"](self)
  1285             elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1307             elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1286                 return element_infos["elmt_type"]["extract"](self.text, extract=False)
  1308                 return element_infos["elmt_type"]["extract"](self.text, extract=False)
  1287             else:
  1309             else:
  1288                 element_name = factory.etreeNamespaceFormat % name
  1310                 element_name = factory.etreeNamespaceFormat % name
  1289                 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
  1311                 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
  1290                     values = self.findall(element_name)
  1312                     values = self.findall(element_name)
  1291                     if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1313                     if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1292                         return map(lambda value:
  1314                         return map(lambda value:
  1293                             element_infos["elmt_type"]["extract"](value.text, extract=False), 
  1315                                    element_infos["elmt_type"]["extract"](value.text, extract=False),
  1294                             values)
  1316                                    values)
  1295                     return values
  1317                     return values
  1296                 else:
  1318                 else:
  1297                     value = self.find(element_name)
  1319                     value = self.find(element_name)
  1298                     if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1320                     if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1299                         return element_infos["elmt_type"]["extract"](value.text, extract=False)
  1321                         return element_infos["elmt_type"]["extract"](value.text, extract=False)
  1300                     return value
  1322                     return value
  1301             
  1323 
  1302         elif classinfos.has_key("base"):
  1324         elif "base" in classinfos:
  1303             return classinfos["base"].__getattr__(self, name)
  1325             return classinfos["base"].__getattr__(self, name)
  1304         
  1326 
  1305         return DefaultElementClass.__getattribute__(self, name)
  1327         return DefaultElementClass.__getattribute__(self, name)
  1306     
  1328 
  1307     return getattrMethod
  1329     return getattrMethod
       
  1330 
  1308 
  1331 
  1309 def generateSetattrMethod(factory, class_definition, classinfos):
  1332 def generateSetattrMethod(factory, class_definition, classinfos):
  1310     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1333     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"])
  1334     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"]])
  1335     elements = OrderedDict([(element["name"], element) for element in classinfos["elements"]])
  1313     
  1336 
  1314     def setattrMethod(self, name, value):
  1337     def setattrMethod(self, name, value):
  1315         if attributes.has_key(name):
  1338         if name in attributes:
  1316             attribute_infos = attributes[name]
  1339             attribute_infos = attributes[name]
  1317             attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"])
  1340             attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"])
  1318             if optional_attributes.get(name, False):
  1341             if optional_attributes.get(name, False):
  1319                 default = attribute_infos.get("default", None)
  1342                 default = attribute_infos.get("default", None)
  1320                 if value is None or value == default:
  1343                 if value is None or value == default:
  1321                     self.attrib.pop(name, None)
  1344                     self.attrib.pop(name, None)
  1322                     return
  1345                     return
  1323             elif attribute_infos.has_key("fixed"):
  1346             elif "fixed" in attribute_infos:
  1324                 return
  1347                 return
  1325             return self.set(name, attribute_infos["attr_type"]["generate"](value))
  1348             return self.set(name, attribute_infos["attr_type"]["generate"](value))
  1326         
  1349 
  1327         elif elements.has_key(name):
  1350         elif name in elements:
  1328             element_infos = elements[name]
  1351             element_infos = elements[name]
  1329             element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
  1352             element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
  1330             if element_infos["type"] == ANY:
  1353             if element_infos["type"] == ANY:
  1331                 element_infos["elmt_type"]["generate"](self, value)
  1354                 element_infos["elmt_type"]["generate"](self, value)
  1332             
  1355 
  1333             elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1356             elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1334                 self.text = element_infos["elmt_type"]["generate"](value)
  1357                 self.text = element_infos["elmt_type"]["generate"](value)
  1335             
  1358 
  1336             else:
  1359             else:
  1337                 prefix = ("%s:" % factory.TargetNamespace
  1360                 prefix = ("%s:" % factory.TargetNamespace
  1338                           if factory.TargetNamespace is not None else "")
  1361                           if factory.TargetNamespace is not None else "")
  1339                 element_xpath = (prefix + name
  1362                 element_xpath = (prefix + name
  1340                                  if name != "content"
  1363                                  if name != "content"
  1341                                  else elements["content"]["elmt_type"]["choices_xpath"].path)
  1364                                  else elements["content"]["elmt_type"]["choices_xpath"].path)
  1342                 
  1365 
  1343                 for element in self.xpath(element_xpath, namespaces=factory.NSMAP):
  1366                 for element in self.xpath(element_xpath, namespaces=factory.NSMAP):
  1344                     self.remove(element)
  1367                     self.remove(element)
  1345                 
  1368 
  1346                 if value is not None:
  1369                 if value is not None:
  1347                     element_idx = elements.keys().index(name)
  1370                     element_idx = elements.keys().index(name)
  1348                     if element_idx > 0:
  1371                     if element_idx > 0:
  1349                         previous_elements_xpath = "|".join(map(
  1372                         previous_elements_xpath = "|".join(map(
  1350                             lambda x: prefix + x
  1373                             lambda x: prefix + x
  1351                                       if x != "content"
  1374                             if x != "content"
  1352                                       else elements["content"]["elmt_type"]["choices_xpath"].path,
  1375                             else elements["content"]["elmt_type"]["choices_xpath"].path,
  1353                             elements.keys()[:element_idx]))
  1376                             elements.keys()[:element_idx]))
  1354                         
  1377 
  1355                         insertion_point = len(self.xpath(previous_elements_xpath, namespaces=factory.NSMAP))
  1378                         insertion_point = len(self.xpath(previous_elements_xpath, namespaces=factory.NSMAP))
  1356                     else:
  1379                     else:
  1357                         insertion_point = 0
  1380                         insertion_point = 0
  1358                     
  1381 
  1359                     if not isinstance(value, ListType):
  1382                     if not isinstance(value, ListType):
  1360                         value = [value]
  1383                         value = [value]
  1361                     
  1384 
  1362                     for element in reversed(value):
  1385                     for element in reversed(value):
  1363                         if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1386                         if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1364                             tmp_element = etree.Element(factory.etreeNamespaceFormat % name)
  1387                             tmp_element = etree.Element(factory.etreeNamespaceFormat % name)
  1365                             tmp_element.text = element_infos["elmt_type"]["generate"](element)
  1388                             tmp_element.text = element_infos["elmt_type"]["generate"](element)
  1366                             element = tmp_element
  1389                             element = tmp_element
  1367                         self.insert(insertion_point, element)
  1390                         self.insert(insertion_point, element)
  1368         
  1391 
  1369         elif classinfos.has_key("base"):
  1392         elif "base" in classinfos:
  1370             return classinfos["base"].__setattr__(self, name, value)
  1393             return classinfos["base"].__setattr__(self, name, value)
  1371         
  1394 
  1372         else:
  1395         else:
  1373             raise AttributeError("'%s' can't have an attribute '%s'." % (self.__class__.__name__, name))
  1396             raise AttributeError("'%s' can't have an attribute '%s'." % (self.__class__.__name__, name))
  1374         
  1397 
  1375     return setattrMethod
  1398     return setattrMethod
  1376 
  1399 
       
  1400 
  1377 def gettypeinfos(name, facets):
  1401 def gettypeinfos(name, facets):
  1378     if facets.has_key("enumeration") and facets["enumeration"][0] is not None:
  1402     if "enumeration" in facets and facets["enumeration"][0] is not None:
  1379         return facets["enumeration"][0]
  1403         return facets["enumeration"][0]
  1380     elif facets.has_key("maxInclusive"):
  1404     elif "maxInclusive" in facets:
  1381         limits = {"max" : None, "min" : None}
  1405         limits = {"max": None, "min": None}
  1382         if facets["maxInclusive"][0] is not None:
  1406         if facets["maxInclusive"][0] is not None:
  1383             limits["max"] = facets["maxInclusive"][0]
  1407             limits["max"] = facets["maxInclusive"][0]
  1384         elif facets["maxExclusive"][0] is not None:
  1408         elif facets["maxExclusive"][0] is not None:
  1385             limits["max"] = facets["maxExclusive"][0] - 1
  1409             limits["max"] = facets["maxExclusive"][0] - 1
  1386         if facets["minInclusive"][0] is not None:
  1410         if facets["minInclusive"][0] is not None:
  1389             limits["min"] = facets["minExclusive"][0] + 1
  1413             limits["min"] = facets["minExclusive"][0] + 1
  1390         if limits["max"] is not None or limits["min"] is not None:
  1414         if limits["max"] is not None or limits["min"] is not None:
  1391             return limits
  1415             return limits
  1392     return name
  1416     return name
  1393 
  1417 
       
  1418 
  1394 def generateGetElementAttributes(factory, classinfos):
  1419 def generateGetElementAttributes(factory, classinfos):
  1395     def getElementAttributes(self):
  1420     def getElementAttributes(self):
  1396         attr_list = []
  1421         attr_list = []
  1397         if classinfos.has_key("base"):
  1422         if "base" in classinfos:
  1398             attr_list.extend(classinfos["base"].getElementAttributes(self))
  1423             attr_list.extend(classinfos["base"].getElementAttributes(self))
  1399         for attr in classinfos["attributes"]:
  1424         for attr in classinfos["attributes"]:
  1400             if attr["use"] != "prohibited":
  1425             if attr["use"] != "prohibited":
  1401                 attr_params = {"name" : attr["name"], "use" : attr["use"], 
  1426                 attr_params = {
  1402                     "type" : gettypeinfos(attr["attr_type"]["basename"], attr["attr_type"]["facets"]),
  1427                     "name": attr["name"],
  1403                     "value" : getattr(self, attr["name"], "")}
  1428                     "use": attr["use"],
       
  1429                     "type": gettypeinfos(attr["attr_type"]["basename"], attr["attr_type"]["facets"]),
       
  1430                     "value": getattr(self, attr["name"], "")}
  1404                 attr_list.append(attr_params)
  1431                 attr_list.append(attr_params)
  1405         return attr_list
  1432         return attr_list
  1406     return getElementAttributes
  1433     return getElementAttributes
  1407 
  1434 
       
  1435 
  1408 def generateGetElementInfos(factory, classinfos):
  1436 def generateGetElementInfos(factory, classinfos):
  1409     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1437     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"]])
  1438     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1411     
  1439 
  1412     def getElementInfos(self, name, path=None, derived=False):
  1440     def getElementInfos(self, name, path=None, derived=False):
  1413         attr_type = "element"
  1441         attr_type = "element"
  1414         value = None
  1442         value = None
  1415         use = "required"
  1443         use = "required"
  1416         children = []
  1444         children = []
  1417         if path is not None:
  1445         if path is not None:
  1418             parts = path.split(".", 1)
  1446             parts = path.split(".", 1)
  1419             if attributes.has_key(parts[0]):
  1447             if parts[0] in attributes:
  1420                 if len(parts) != 1:
  1448                 if len(parts) != 1:
  1421                     raise ValueError("Wrong path!")
  1449                     raise ValueError("Wrong path!")
  1422                 attr_type = gettypeinfos(attributes[parts[0]]["attr_type"]["basename"], 
  1450                 attr_type = gettypeinfos(attributes[parts[0]]["attr_type"]["basename"],
  1423                                          attributes[parts[0]]["attr_type"]["facets"])
  1451                                          attributes[parts[0]]["attr_type"]["facets"])
  1424                 value = getattr(self, parts[0], "")
  1452                 value = getattr(self, parts[0], "")
  1425             elif elements.has_key(parts[0]):
  1453             elif parts[0] in elements:
  1426                 if elements[parts[0]]["elmt_type"]["type"] == SIMPLETYPE:
  1454                 if elements[parts[0]]["elmt_type"]["type"] == SIMPLETYPE:
  1427                     if len(parts) != 1:
  1455                     if len(parts) != 1:
  1428                         raise ValueError("Wrong path!")
  1456                         raise ValueError("Wrong path!")
  1429                     attr_type = gettypeinfos(elements[parts[0]]["elmt_type"]["basename"], 
  1457                     attr_type = gettypeinfos(elements[parts[0]]["elmt_type"]["basename"],
  1430                                              elements[parts[0]]["elmt_type"]["facets"])
  1458                                              elements[parts[0]]["elmt_type"]["facets"])
  1431                     value = getattr(self, parts[0], "")
  1459                     value = getattr(self, parts[0], "")
  1432                 elif parts[0] == "content":
  1460                 elif parts[0] == "content":
  1433                     return self.content.getElementInfos(self.content.getLocalTag(), path)
  1461                     return self.content.getElementInfos(self.content.getLocalTag(), path)
  1434                 else:
  1462                 else:
  1437                         raise ValueError("Wrong path!")
  1465                         raise ValueError("Wrong path!")
  1438                     if len(parts) == 1:
  1466                     if len(parts) == 1:
  1439                         return attr.getElementInfos(parts[0])
  1467                         return attr.getElementInfos(parts[0])
  1440                     else:
  1468                     else:
  1441                         return attr.getElementInfos(parts[0], parts[1])
  1469                         return attr.getElementInfos(parts[0], parts[1])
  1442             elif elements.has_key("content"):
  1470             elif "content" in elements:
  1443                 if len(parts) > 0:
  1471                 if len(parts) > 0:
  1444                     return self.content.getElementInfos(name, path)
  1472                     return self.content.getElementInfos(name, path)
  1445             elif classinfos.has_key("base"):
  1473             elif "base" in classinfos:
  1446                 classinfos["base"].getElementInfos(name, path)
  1474                 classinfos["base"].getElementInfos(name, path)
  1447             else:
  1475             else:
  1448                 raise ValueError("Wrong path!")
  1476                 raise ValueError("Wrong path!")
  1449         else:
  1477         else:
  1450             if not derived:
  1478             if not derived:
  1451                 children.extend(self.getElementAttributes())
  1479                 children.extend(self.getElementAttributes())
  1452             if classinfos.has_key("base"):
  1480             if "base" in classinfos:
  1453                 children.extend(classinfos["base"].getElementInfos(self, name, derived=True)["children"])
  1481                 children.extend(classinfos["base"].getElementInfos(self, name, derived=True)["children"])
  1454             for element_name, element in elements.items():
  1482             for element_name, element in elements.items():
  1455                 if element["minOccurs"] == 0:
  1483                 if element["minOccurs"] == 0:
  1456                     use = "optional"
  1484                     use = "optional"
  1457                 if element_name == "content" and element["type"] == CHOICE:
  1485                 if element_name == "content" and element["type"] == CHOICE:
  1461                     else:
  1489                     else:
  1462                         value = self.content.getLocalTag()
  1490                         value = self.content.getLocalTag()
  1463                         if self.content is not None:
  1491                         if self.content is not None:
  1464                             children.extend(self.content.getElementInfos(value)["children"])
  1492                             children.extend(self.content.getElementInfos(value)["children"])
  1465                 elif element["elmt_type"]["type"] == SIMPLETYPE:
  1493                 elif element["elmt_type"]["type"] == SIMPLETYPE:
  1466                     children.append({"name": element_name, "require": element["minOccurs"] != 0, 
  1494                     children.append({
  1467                         "type": gettypeinfos(element["elmt_type"]["basename"], 
  1495                         "name": element_name,
       
  1496                         "require": element["minOccurs"] != 0,
       
  1497                         "type": gettypeinfos(element["elmt_type"]["basename"],
  1468                                              element["elmt_type"]["facets"]),
  1498                                              element["elmt_type"]["facets"]),
  1469                         "value": getattr(self, element_name, None)})
  1499                         "value": getattr(self, element_name, None)})
  1470                 else:
  1500                 else:
  1471                     instance = getattr(self, element_name, None)
  1501                     instance = getattr(self, element_name, None)
  1472                     if instance is None:
  1502                     if instance is None:
  1473                         instance = element["elmt_type"]["initial"]()
  1503                         instance = element["elmt_type"]["initial"]()
  1474                     children.append(instance.getElementInfos(element_name))
  1504                     children.append(instance.getElementInfos(element_name))
  1475         return {"name": name, "type": attr_type, "value": value, "use": use, "children": children}
  1505         return {"name": name, "type": attr_type, "value": value, "use": use, "children": children}
  1476     return getElementInfos
  1506     return getElementInfos
  1477 
  1507 
       
  1508 
  1478 def generateSetElementValue(factory, classinfos):
  1509 def generateSetElementValue(factory, classinfos):
  1479     attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
  1510     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"]])
  1511     elements = dict([(element["name"], element) for element in classinfos["elements"]])
  1481     
  1512 
  1482     def setElementValue(self, path, value):
  1513     def setElementValue(self, path, value):
  1483         if path is not None:
  1514         if path is not None:
  1484             parts = path.split(".", 1)
  1515             parts = path.split(".", 1)
  1485             if attributes.has_key(parts[0]):
  1516             if parts[0] in attributes:
  1486                 if len(parts) != 1:
  1517                 if len(parts) != 1:
  1487                     raise ValueError("Wrong path!")
  1518                     raise ValueError("Wrong path!")
  1488                 if attributes[parts[0]]["attr_type"]["basename"] == "boolean":
  1519                 if attributes[parts[0]]["attr_type"]["basename"] == "boolean":
  1489                     setattr(self, parts[0], value)
  1520                     setattr(self, parts[0], value)
  1490                 elif attributes[parts[0]]["use"] == "optional" and value == "":
  1521                 elif attributes[parts[0]]["use"] == "optional" and value == "":
  1491                     if attributes[parts[0]].has_key("default"):
  1522                     if "default" in attributes[parts[0]]:
  1492                         setattr(self, parts[0], 
  1523                         setattr(self, parts[0],
  1493                             attributes[parts[0]]["attr_type"]["extract"](
  1524                                 attributes[parts[0]]["attr_type"]["extract"](
  1494                                 attributes[parts[0]]["default"], False))
  1525                                     attributes[parts[0]]["default"], False))
  1495                     else:
  1526                     else:
  1496                         setattr(self, parts[0], None)
  1527                         setattr(self, parts[0], None)
  1497                 else:
  1528                 else:
  1498                     setattr(self, parts[0], attributes[parts[0]]["attr_type"]["extract"](value, False))
  1529                     setattr(self, parts[0], attributes[parts[0]]["attr_type"]["extract"](value, False))
  1499             elif elements.has_key(parts[0]):
  1530             elif parts[0] in elements:
  1500                 if elements[parts[0]]["elmt_type"]["type"] == SIMPLETYPE:
  1531                 if elements[parts[0]]["elmt_type"]["type"] == SIMPLETYPE:
  1501                     if len(parts) != 1:
  1532                     if len(parts) != 1:
  1502                         raise ValueError("Wrong path!")
  1533                         raise ValueError("Wrong path!")
  1503                     if elements[parts[0]]["elmt_type"]["basename"] == "boolean":
  1534                     if elements[parts[0]]["elmt_type"]["basename"] == "boolean":
  1504                         setattr(self, parts[0], value)
  1535                         setattr(self, parts[0], value)
  1509                 else:
  1540                 else:
  1510                     instance = getattr(self, parts[0], None)
  1541                     instance = getattr(self, parts[0], None)
  1511                     if instance is None and elements[parts[0]]["minOccurs"] == 0:
  1542                     if instance is None and elements[parts[0]]["minOccurs"] == 0:
  1512                         instance = elements[parts[0]]["elmt_type"]["initial"]()
  1543                         instance = elements[parts[0]]["elmt_type"]["initial"]()
  1513                         setattr(self, parts[0], instance)
  1544                         setattr(self, parts[0], instance)
  1514                     if instance != None:
  1545                     if instance is not None:
  1515                         if len(parts) > 1:
  1546                         if len(parts) > 1:
  1516                             instance.setElementValue(parts[1], value)
  1547                             instance.setElementValue(parts[1], value)
  1517                         else:
  1548                         else:
  1518                             instance.setElementValue(None, value)
  1549                             instance.setElementValue(None, value)
  1519             elif elements.has_key("content"):
  1550             elif "content" in elements:
  1520                 if len(parts) > 0:
  1551                 if len(parts) > 0:
  1521                     self.content.setElementValue(path, value)
  1552                     self.content.setElementValue(path, value)
  1522             elif classinfos.has_key("base"):
  1553             elif "base" in classinfos:
  1523                 classinfos["base"].setElementValue(self, path, value)
  1554                 classinfos["base"].setElementValue(self, path, value)
  1524         elif elements.has_key("content"):
  1555         elif "content" in elements:
  1525             if value == "":
  1556             if value == "":
  1526                 if elements["content"]["minOccurs"] == 0:
  1557                 if elements["content"]["minOccurs"] == 0:
  1527                     self.setcontent([])
  1558                     self.setcontent([])
  1528                 else:
  1559                 else:
  1529                     raise ValueError("\"content\" element is required!")
  1560                     raise ValueError("\"content\" element is required!")
  1530             else:
  1561             else:
  1531                 self.setcontentbytype(value)
  1562                 self.setcontentbytype(value)
  1532     return setElementValue
  1563     return setElementValue
  1533 
  1564 
  1534 """
  1565 
  1535 Methods that generates the different methods for setting and getting the attributes
       
  1536 """
       
  1537 def generateInitMethod(factory, classinfos):
  1566 def generateInitMethod(factory, classinfos):
       
  1567     """
       
  1568     Methods that generates the different methods for setting and getting the attributes
       
  1569     """
       
  1570 
  1538     def initMethod(self):
  1571     def initMethod(self):
  1539         if classinfos.has_key("base"):
  1572         if "base" in classinfos:
  1540             classinfos["base"]._init_(self)
  1573             classinfos["base"]._init_(self)
  1541         for attribute in classinfos["attributes"]:
  1574         for attribute in classinfos["attributes"]:
  1542             attribute["attr_type"] = FindTypeInfos(factory, attribute["attr_type"])
  1575             attribute["attr_type"] = FindTypeInfos(factory, attribute["attr_type"])
  1543             if attribute["use"] == "required":
  1576             if attribute["use"] == "required":
  1544                 self.set(attribute["name"], attribute["attr_type"]["generate"](attribute["attr_type"]["initial"]()))
  1577                 self.set(attribute["name"], attribute["attr_type"]["generate"](attribute["attr_type"]["initial"]()))
  1551                 initial = GetElementInitialValue(factory, element)
  1584                 initial = GetElementInitialValue(factory, element)
  1552                 if initial is not None:
  1585                 if initial is not None:
  1553                     map(self.append, initial)
  1586                     map(self.append, initial)
  1554     return initMethod
  1587     return initMethod
  1555 
  1588 
       
  1589 
  1556 def generateSetMethod(attr):
  1590 def generateSetMethod(attr):
  1557     def setMethod(self, value):
  1591     def setMethod(self, value):
  1558         setattr(self, attr, value)
  1592         setattr(self, attr, value)
  1559     return setMethod
  1593     return setMethod
  1560 
  1594 
       
  1595 
  1561 def generateGetMethod(attr):
  1596 def generateGetMethod(attr):
  1562     def getMethod(self):
  1597     def getMethod(self):
  1563         return getattr(self, attr, None)
  1598         return getattr(self, attr, None)
  1564     return getMethod
  1599     return getMethod
  1565 
  1600 
       
  1601 
  1566 def generateAddMethod(attr, factory, infos):
  1602 def generateAddMethod(attr, factory, infos):
  1567     def addMethod(self):
  1603     def addMethod(self):
  1568         if infos["type"] == ATTRIBUTE:
  1604         if infos["type"] == ATTRIBUTE:
  1569             infos["attr_type"] = FindTypeInfos(factory, infos["attr_type"])
  1605             infos["attr_type"] = FindTypeInfos(factory, infos["attr_type"])
  1570             if not infos.has_key("default"):
  1606             if "default" not in infos:
  1571                 setattr(self, attr, infos["attr_type"]["initial"]())
  1607                 setattr(self, attr, infos["attr_type"]["initial"]())
  1572         elif infos["type"] == ELEMENT:
  1608         elif infos["type"] == ELEMENT:
  1573             infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
  1609             infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
  1574             value = infos["elmt_type"]["initial"]()
  1610             value = infos["elmt_type"]["initial"]()
  1575             DefaultElementClass.__setattr__(value, "tag", factory.etreeNamespaceFormat % attr)
  1611             DefaultElementClass.__setattr__(value, "tag", factory.etreeNamespaceFormat % attr)
  1577             value._init_()
  1613             value._init_()
  1578         else:
  1614         else:
  1579             raise ValueError("Invalid class attribute!")
  1615             raise ValueError("Invalid class attribute!")
  1580     return addMethod
  1616     return addMethod
  1581 
  1617 
       
  1618 
  1582 def generateDeleteMethod(attr):
  1619 def generateDeleteMethod(attr):
  1583     def deleteMethod(self):
  1620     def deleteMethod(self):
  1584         setattr(self, attr, None)
  1621         setattr(self, attr, None)
  1585     return deleteMethod
  1622     return deleteMethod
       
  1623 
  1586 
  1624 
  1587 def generateAppendMethod(attr, maxOccurs, factory, infos):
  1625 def generateAppendMethod(attr, maxOccurs, factory, infos):
  1588     def appendMethod(self, value):
  1626     def appendMethod(self, value):
  1589         infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
  1627         infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
  1590         attr_list = getattr(self, attr)
  1628         attr_list = getattr(self, attr)
  1594             else:
  1632             else:
  1595                 attr_list[-1].addnext(value)
  1633                 attr_list[-1].addnext(value)
  1596         else:
  1634         else:
  1597             raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr))
  1635             raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr))
  1598     return appendMethod
  1636     return appendMethod
       
  1637 
  1599 
  1638 
  1600 def generateInsertMethod(attr, maxOccurs, factory, infos):
  1639 def generateInsertMethod(attr, maxOccurs, factory, infos):
  1601     def insertMethod(self, index, value):
  1640     def insertMethod(self, index, value):
  1602         infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
  1641         infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
  1603         attr_list = getattr(self, attr)
  1642         attr_list = getattr(self, attr)
  1610                 attr_list[min(index - 1, len(attr_list) - 1)].addnext(value)
  1649                 attr_list[min(index - 1, len(attr_list) - 1)].addnext(value)
  1611         else:
  1650         else:
  1612             raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr))
  1651             raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr))
  1613     return insertMethod
  1652     return insertMethod
  1614 
  1653 
       
  1654 
  1615 def generateGetChoicesMethod(choice_types):
  1655 def generateGetChoicesMethod(choice_types):
  1616     def getChoicesMethod(self):
  1656     def getChoicesMethod(self):
  1617         return [choice["name"] for choice in choice_types]
  1657         return [choice["name"] for choice in choice_types]
  1618     return getChoicesMethod
  1658     return getChoicesMethod
  1619 
  1659 
       
  1660 
  1620 def generateSetChoiceByTypeMethod(factory, choice_types):
  1661 def generateSetChoiceByTypeMethod(factory, choice_types):
  1621     choices = dict([(choice["name"], choice) for choice in choice_types])
  1662     choices = dict([(choice["name"], choice) for choice in choice_types])
       
  1663 
  1622     def setChoiceMethod(self, content_type):
  1664     def setChoiceMethod(self, content_type):
  1623         if not choices.has_key(content_type):
  1665         if content_type not in choices:
  1624             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type)
  1666             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type)
  1625         choices[content_type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
  1667         choices[content_type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
  1626         new_content = choices[content_type]["elmt_type"]["initial"]()
  1668         new_content = choices[content_type]["elmt_type"]["initial"]()
  1627         DefaultElementClass.__setattr__(new_content, "tag", factory.etreeNamespaceFormat % content_type)
  1669         DefaultElementClass.__setattr__(new_content, "tag", factory.etreeNamespaceFormat % content_type)
  1628         self.content = new_content
  1670         self.content = new_content
  1629         return new_content
  1671         return new_content
  1630     return setChoiceMethod
  1672     return setChoiceMethod
  1631 
  1673 
       
  1674 
  1632 def generateAppendChoiceByTypeMethod(maxOccurs, factory, choice_types):
  1675 def generateAppendChoiceByTypeMethod(maxOccurs, factory, choice_types):
  1633     choices = dict([(choice["name"], choice) for choice in choice_types])
  1676     choices = dict([(choice["name"], choice) for choice in choice_types])
       
  1677 
  1634     def appendChoiceMethod(self, content_type):
  1678     def appendChoiceMethod(self, content_type):
  1635         if not choices.has_key(content_type):
  1679         if content_type not in choices:
  1636             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type)
  1680             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type)
  1637         choices[content_type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
  1681         choices[content_type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
  1638         if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
  1682         if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
  1639             new_element = choices[content_type]["elmt_type"]["initial"]()
  1683             new_element = choices[content_type]["elmt_type"]["initial"]()
  1640             DefaultElementClass.__setattr__(new_element, "tag", factory.etreeNamespaceFormat % content_type)
  1684             DefaultElementClass.__setattr__(new_element, "tag", factory.etreeNamespaceFormat % content_type)
  1642             return new_element
  1686             return new_element
  1643         else:
  1687         else:
  1644             raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs)
  1688             raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs)
  1645     return appendChoiceMethod
  1689     return appendChoiceMethod
  1646 
  1690 
       
  1691 
  1647 def generateInsertChoiceByTypeMethod(maxOccurs, factory, choice_types):
  1692 def generateInsertChoiceByTypeMethod(maxOccurs, factory, choice_types):
  1648     choices = dict([(choice["name"], choice) for choice in choice_types])
  1693     choices = dict([(choice["name"], choice) for choice in choice_types])
       
  1694 
  1649     def insertChoiceMethod(self, index, content_type):
  1695     def insertChoiceMethod(self, index, content_type):
  1650         if not choices.has_key(content_type):
  1696         if content_type not in choices:
  1651             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type)
  1697             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type)
  1652         choices[type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
  1698         choices[type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
  1653         if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
  1699         if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
  1654             new_element = choices[content_type]["elmt_type"]["initial"]()
  1700             new_element = choices[content_type]["elmt_type"]["initial"]()
  1655             DefaultElementClass.__setattr__(new_element, "tag", factory.etreeNamespaceFormat % content_type)
  1701             DefaultElementClass.__setattr__(new_element, "tag", factory.etreeNamespaceFormat % content_type)
  1657             return new_element
  1703             return new_element
  1658         else:
  1704         else:
  1659             raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs)
  1705             raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs)
  1660     return insertChoiceMethod
  1706     return insertChoiceMethod
  1661 
  1707 
       
  1708 
  1662 def generateRemoveMethod(attr, minOccurs):
  1709 def generateRemoveMethod(attr, minOccurs):
  1663     def removeMethod(self, index):
  1710     def removeMethod(self, index):
  1664         attr_list = getattr(self, attr)
  1711         attr_list = getattr(self, attr)
  1665         if len(attr_list) > minOccurs:
  1712         if len(attr_list) > minOccurs:
  1666             self.remove(attr_list[index])
  1713             self.remove(attr_list[index])
  1667         else:
  1714         else:
  1668             raise ValueError("There can't be less than %d values in \"%s\"!" % (minOccurs, attr))
  1715             raise ValueError("There can't be less than %d values in \"%s\"!" % (minOccurs, attr))
  1669     return removeMethod
  1716     return removeMethod
  1670 
  1717 
       
  1718 
  1671 def generateCountMethod(attr):
  1719 def generateCountMethod(attr):
  1672     def countMethod(self):
  1720     def countMethod(self):
  1673         return len(getattr(self, attr))
  1721         return len(getattr(self, attr))
  1674     return countMethod
  1722     return countMethod
  1675 
  1723 
       
  1724 
  1676 """
  1725 """
  1677 This function generate a xml parser from a class factory
  1726 This function generate a xml parser from a class factory
  1678 """
  1727 """
  1679 
  1728 
  1680 NAMESPACE_PATTERN = re.compile("xmlns(?:\:[^\=]*)?=\"[^\"]*\" ")
  1729 NAMESPACE_PATTERN = re.compile("xmlns(?:\:[^\=]*)?=\"[^\"]*\" ")
  1681 
  1730 
       
  1731 
  1682 class DefaultElementClass(etree.ElementBase):
  1732 class DefaultElementClass(etree.ElementBase):
  1683     
  1733 
  1684     StructurePattern = re.compile("$")
  1734     StructurePattern = re.compile("$")
  1685     
  1735 
  1686     def _init_(self):
  1736     def _init_(self):
  1687         pass
  1737         pass
  1688     
  1738 
  1689     def getLocalTag(self):
  1739     def getLocalTag(self):
  1690         return etree.QName(self.tag).localname
  1740         return etree.QName(self.tag).localname
  1691         
  1741 
  1692     def tostring(self):
  1742     def tostring(self):
  1693         return NAMESPACE_PATTERN.sub("", etree.tostring(self, pretty_print=True, encoding='utf-8')).decode('utf-8')
  1743         return NAMESPACE_PATTERN.sub("", etree.tostring(self, pretty_print=True, encoding='utf-8')).decode('utf-8')
  1694 
  1744 
       
  1745 
  1695 class XMLElementClassLookUp(etree.PythonElementClassLookup):
  1746 class XMLElementClassLookUp(etree.PythonElementClassLookup):
  1696     
  1747 
  1697     def __init__(self, classes, *args, **kwargs):
  1748     def __init__(self, classes, *args, **kwargs):
  1698         etree.PythonElementClassLookup.__init__(self, *args, **kwargs)
  1749         etree.PythonElementClassLookup.__init__(self, *args, **kwargs)
  1699         self.LookUpClasses = classes
  1750         self.LookUpClasses = classes
  1700     
  1751 
  1701     def GetElementClass(self, element_tag, parent_tag=None, default=DefaultElementClass):
  1752     def GetElementClass(self, element_tag, parent_tag=None, default=DefaultElementClass):
  1702         element_class = self.LookUpClasses.get(element_tag, (default, None))
  1753         element_class = self.LookUpClasses.get(element_tag, (default, None))
  1703         if not isinstance(element_class, DictType):
  1754         if not isinstance(element_class, DictType):
  1704             if isinstance(element_class[0], (StringType, UnicodeType)):
  1755             if isinstance(element_class[0], (StringType, UnicodeType)):
  1705                 return self.GetElementClass(element_class[0], default=default)
  1756                 return self.GetElementClass(element_class[0], default=default)
  1706             return element_class[0]
  1757             return element_class[0]
  1707         
  1758 
  1708         element_with_parent_class = element_class.get(parent_tag, default)
  1759         element_with_parent_class = element_class.get(parent_tag, default)
  1709         if isinstance(element_with_parent_class, (StringType, UnicodeType)):
  1760         if isinstance(element_with_parent_class, (StringType, UnicodeType)):
  1710             return self.GetElementClass(element_with_parent_class, default=default)
  1761             return self.GetElementClass(element_with_parent_class, default=default)
  1711         return element_with_parent_class
  1762         return element_with_parent_class
  1712         
  1763 
  1713     def lookup(self, document, element):
  1764     def lookup(self, document, element):
  1714         parent = element.getparent()
  1765         parent = element.getparent()
  1715         element_class = self.GetElementClass(element.tag, 
  1766         element_class = self.GetElementClass(
  1716             parent.tag if parent is not None else None)
  1767             element.tag, parent.tag if parent is not None else None)
  1717         if isinstance(element_class, ListType):
  1768         if isinstance(element_class, ListType):
  1718             children = "".join([
  1769             children = "".join([
  1719                 "%s " % etree.QName(child.tag).localname
  1770                 "%s " % etree.QName(child.tag).localname
  1720                 for child in element])
  1771                 for child in element])
  1721             for possible_class in element_class:
  1772             for possible_class in element_class:
  1724                 if possible_class.StructurePattern.match(children) is not None:
  1775                 if possible_class.StructurePattern.match(children) is not None:
  1725                     return possible_class
  1776                     return possible_class
  1726             return element_class[0]
  1777             return element_class[0]
  1727         return element_class
  1778         return element_class
  1728 
  1779 
       
  1780 
  1729 class XMLClassParser(etree.XMLParser):
  1781 class XMLClassParser(etree.XMLParser):
  1730 
  1782 
  1731     def __init__(self, namespaces, default_namespace_format, base_class, xsd_schema, *args, **kwargs):
  1783     def __init__(self, namespaces, default_namespace_format, base_class, xsd_schema, *args, **kwargs):
  1732         etree.XMLParser.__init__(self, *args, **kwargs)
  1784         etree.XMLParser.__init__(self, *args, **kwargs)
  1733         self.DefaultNamespaceFormat = default_namespace_format
  1785         self.DefaultNamespaceFormat = default_namespace_format
  1739                 for name, uri in namespaces.iteritems()}
  1791                 for name, uri in namespaces.iteritems()}
  1740         else:
  1792         else:
  1741             self.RootNSMAP = namespaces
  1793             self.RootNSMAP = namespaces
  1742         self.BaseClass = base_class
  1794         self.BaseClass = base_class
  1743         self.XSDSchema = xsd_schema
  1795         self.XSDSchema = xsd_schema
  1744     
  1796 
  1745     def set_element_class_lookup(self, class_lookup):
  1797     def set_element_class_lookup(self, class_lookup):
  1746         etree.XMLParser.set_element_class_lookup(self, class_lookup)
  1798         etree.XMLParser.set_element_class_lookup(self, class_lookup)
  1747         self.ClassLookup = class_lookup
  1799         self.ClassLookup = class_lookup
  1748     
  1800 
  1749     def LoadXMLString(self, xml_string):
  1801     def LoadXMLString(self, xml_string):
  1750         tree = etree.fromstring(xml_string, self)
  1802         tree = etree.fromstring(xml_string, self)
  1751         if not self.XSDSchema.validate(tree):
  1803         if not self.XSDSchema.validate(tree):
  1752             error = self.XSDSchema.error_log.last_error
  1804             error = self.XSDSchema.error_log.last_error
  1753             return tree, (error.line, error.message)
  1805             return tree, (error.line, error.message)
  1754         return tree, None 
  1806         return tree, None
  1755     
  1807 
  1756     def Dumps(self, xml_obj):
  1808     def Dumps(self, xml_obj):
  1757         return etree.tostring(xml_obj, encoding='utf-8')
  1809         return etree.tostring(xml_obj, encoding='utf-8')
  1758     
  1810 
  1759     def Loads(self, xml_string):
  1811     def Loads(self, xml_string):
  1760         return etree.fromstring(xml_string, self)
  1812         return etree.fromstring(xml_string, self)
  1761     
  1813 
  1762     def CreateRoot(self):
  1814     def CreateRoot(self):
  1763         if self.BaseClass is not None:
  1815         if self.BaseClass is not None:
  1764             root = self.makeelement(
  1816             root = self.makeelement(
  1765                 self.DefaultNamespaceFormat % self.BaseClass[0],
  1817                 self.DefaultNamespaceFormat % self.BaseClass[0],
  1766                 nsmap=self.RootNSMAP)
  1818                 nsmap=self.RootNSMAP)
  1767             root._init_()
  1819             root._init_()
  1768             return root
  1820             return root
  1769         return None
  1821         return None
  1770     
  1822 
  1771     def GetElementClass(self, element_tag, parent_tag=None):
  1823     def GetElementClass(self, element_tag, parent_tag=None):
  1772         return self.ClassLookup.GetElementClass(
  1824         return self.ClassLookup.GetElementClass(
  1773             self.DefaultNamespaceFormat % element_tag, 
  1825             self.DefaultNamespaceFormat % element_tag,
  1774             self.DefaultNamespaceFormat % parent_tag 
  1826             self.DefaultNamespaceFormat % parent_tag
  1775             if parent_tag is not None else parent_tag, 
  1827             if parent_tag is not None else parent_tag,
  1776             None)
  1828             None)
  1777     
  1829 
  1778     def CreateElement(self, element_tag, parent_tag=None, class_idx=None):
  1830     def CreateElement(self, element_tag, parent_tag=None, class_idx=None):
  1779         element_class = self.GetElementClass(element_tag, parent_tag)
  1831         element_class = self.GetElementClass(element_tag, parent_tag)
  1780         if isinstance(element_class, ListType):
  1832         if isinstance(element_class, ListType):
  1781             if class_idx is not None and class_idx < len(element_class):
  1833             if class_idx is not None and class_idx < len(element_class):
  1782                 new_element = element_class[class_idx]()
  1834                 new_element = element_class[class_idx]()
  1783             else:
  1835             else:
  1784                 raise ValueError, "No corresponding class found!"
  1836                 raise ValueError("No corresponding class found!")
  1785         else:
  1837         else:
  1786             new_element = element_class()
  1838             new_element = element_class()
  1787         DefaultElementClass.__setattr__(new_element, "tag", self.DefaultNamespaceFormat % element_tag)
  1839         DefaultElementClass.__setattr__(new_element, "tag", self.DefaultNamespaceFormat % element_tag)
  1788         new_element._init_()
  1840         new_element._init_()
  1789         return new_element
  1841         return new_element
  1790     
  1842 
       
  1843 
  1791 def GenerateParser(factory, xsdstring):
  1844 def GenerateParser(factory, xsdstring):
  1792     ComputedClasses = factory.CreateClasses()
  1845     ComputedClasses = factory.CreateClasses()
  1793     
  1846 
  1794     if factory.FileName is not None:
  1847     if factory.FileName is not None:
  1795         ComputedClasses = ComputedClasses[factory.FileName]
  1848         ComputedClasses = ComputedClasses[factory.FileName]
  1796     BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass]
  1849     BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass]
  1797        
  1850 
  1798     parser = XMLClassParser(
  1851     parser = XMLClassParser(
  1799         factory.NSMAP,
  1852         factory.NSMAP,
  1800         factory.etreeNamespaceFormat,
  1853         factory.etreeNamespaceFormat,
  1801         BaseClass[0] if len(BaseClass) == 1 else None,
  1854         BaseClass[0] if len(BaseClass) == 1 else None,
  1802         etree.XMLSchema(etree.fromstring(xsdstring)),
  1855         etree.XMLSchema(etree.fromstring(xsdstring)),
  1803         strip_cdata = False, remove_blank_text=True)
  1856         strip_cdata=False, remove_blank_text=True)
  1804     class_lookup = XMLElementClassLookUp(factory.ComputedClassesLookUp)
  1857     class_lookup = XMLElementClassLookUp(factory.ComputedClassesLookUp)
  1805     parser.set_element_class_lookup(class_lookup)
  1858     parser.set_element_class_lookup(class_lookup)
  1806     
  1859 
  1807     return parser
  1860     return parser
  1808