xmlclass/xmlclass.py
changeset 2450 5024c19ca8f0
parent 2439 f0a040f1de1b
child 2456 7373e3048167
equal deleted inserted replaced
2449:b0560adec4b7 2450:5024c19ca8f0
    26 from __future__ import absolute_import
    26 from __future__ import absolute_import
    27 from __future__ import print_function
    27 from __future__ import print_function
    28 import os
    28 import os
    29 import re
    29 import re
    30 import datetime
    30 import datetime
    31 from types import *
       
    32 from xml.dom import minidom
    31 from xml.dom import minidom
    33 from xml.sax.saxutils import unescape
    32 from xml.sax.saxutils import unescape
    34 from collections import OrderedDict
    33 from collections import OrderedDict
    35 from builtins import str as text
    34 from builtins import str as text
    36 
    35 
       
    36 from six import string_types
    37 from six.moves import xrange
    37 from six.moves import xrange
    38 from lxml import etree
    38 from lxml import etree
    39 
    39 
    40 
    40 
    41 def CreateNode(name):
    41 def CreateNode(name):
   573     return {
   573     return {
   574         "type": COMPLEXTYPE,
   574         "type": COMPLEXTYPE,
   575         "extract": ExtractAny,
   575         "extract": ExtractAny,
   576         "generate": GenerateAny,
   576         "generate": GenerateAny,
   577         "initial": InitialAny,
   577         "initial": InitialAny,
   578         "check": lambda x: isinstance(x, (StringType, UnicodeType, etree.ElementBase))
   578         "check": lambda x: isinstance(x, (string_types, etree.ElementBase))
   579     }
   579     }
   580 
   580 
   581 
   581 
   582 def GenerateTagInfos(infos):
   582 def GenerateTagInfos(infos):
   583     def ExtractTag(tree):
   583     def ExtractTag(tree):
   605         "check": lambda x: x is None or infos["minOccurs"] == 0 and x
   605         "check": lambda x: x is None or infos["minOccurs"] == 0 and x
   606     }
   606     }
   607 
   607 
   608 
   608 
   609 def FindTypeInfos(factory, infos):
   609 def FindTypeInfos(factory, infos):
   610     if isinstance(infos, (UnicodeType, StringType)):
   610     if isinstance(infos, string_types):
   611         namespace, name = DecomposeQualifiedName(infos)
   611         namespace, name = DecomposeQualifiedName(infos)
   612         return factory.GetQualifiedNameInfos(name, namespace)
   612         return factory.GetQualifiedNameInfos(name, namespace)
   613     return infos
   613     return infos
   614 
   614 
   615 
   615 
   951             self, lookup_classes, parent, typeinfos):
   951             self, lookup_classes, parent, typeinfos):
   952         parent = (self.etreeNamespaceFormat % parent
   952         parent = (self.etreeNamespaceFormat % parent
   953                   if parent is not None else None)
   953                   if parent is not None else None)
   954         parent_class = lookup_classes.get(parent)
   954         parent_class = lookup_classes.get(parent)
   955         if parent_class is not None:
   955         if parent_class is not None:
   956             if isinstance(parent_class, ListType):
   956             if isinstance(parent_class, list):
   957                 if typeinfos not in parent_class:
   957                 if typeinfos not in parent_class:
   958                     lookup_classes[parent].append(typeinfos)
   958                     lookup_classes[parent].append(typeinfos)
   959             elif parent_class != typeinfos:
   959             elif parent_class != typeinfos:
   960                 lookup_classes[parent] = [typeinfos, parent_class]
   960                 lookup_classes[parent] = [typeinfos, parent_class]
   961         else:
   961         else:
   962             lookup_classes[parent] = typeinfos
   962             lookup_classes[parent] = typeinfos
   963 
   963 
   964     def AddToLookupClass(self, name, parent, typeinfos):
   964     def AddToLookupClass(self, name, parent, typeinfos):
   965         lookup_name = self.etreeNamespaceFormat % name
   965         lookup_name = self.etreeNamespaceFormat % name
   966         if isinstance(typeinfos, (StringType, UnicodeType)):
   966         if isinstance(typeinfos, string_types):
   967             self.AddEquivalentClass(name, typeinfos)
   967             self.AddEquivalentClass(name, typeinfos)
   968             typeinfos = self.etreeNamespaceFormat % typeinfos
   968             typeinfos = self.etreeNamespaceFormat % typeinfos
   969         lookup_classes = self.ComputedClassesLookUp.get(lookup_name)
   969         lookup_classes = self.ComputedClassesLookUp.get(lookup_name)
   970         if lookup_classes is None:
   970         if lookup_classes is None:
   971             self.ComputedClassesLookUp[lookup_name] = (typeinfos, parent)
   971             self.ComputedClassesLookUp[lookup_name] = (typeinfos, parent)
   972         elif isinstance(lookup_classes, DictType):
   972         elif isinstance(lookup_classes, dict):
   973             self.AddDistinctionBetweenParentsInLookupClass(
   973             self.AddDistinctionBetweenParentsInLookupClass(
   974                 lookup_classes, parent, typeinfos)
   974                 lookup_classes, parent, typeinfos)
   975         else:
   975         else:
   976             lookup_classes = {
   976             lookup_classes = {
   977                 self.etreeNamespaceFormat % lookup_classes[1]
   977                 self.etreeNamespaceFormat % lookup_classes[1]
   979             self.AddDistinctionBetweenParentsInLookupClass(
   979             self.AddDistinctionBetweenParentsInLookupClass(
   980                 lookup_classes, parent, typeinfos)
   980                 lookup_classes, parent, typeinfos)
   981             self.ComputedClassesLookUp[lookup_name] = lookup_classes
   981             self.ComputedClassesLookUp[lookup_name] = lookup_classes
   982 
   982 
   983     def ExtractTypeInfos(self, name, parent, typeinfos):
   983     def ExtractTypeInfos(self, name, parent, typeinfos):
   984         if isinstance(typeinfos, (StringType, UnicodeType)):
   984         if isinstance(typeinfos, string_types):
   985             namespace, type_name = DecomposeQualifiedName(typeinfos)
   985             namespace, type_name = DecomposeQualifiedName(typeinfos)
   986             infos = self.GetQualifiedNameInfos(type_name, namespace)
   986             infos = self.GetQualifiedNameInfos(type_name, namespace)
   987             if name != "base":
   987             if name != "base":
   988                 if infos["type"] == SIMPLETYPE:
   988                 if infos["type"] == SIMPLETYPE:
   989                     self.AddToLookupClass(name, parent, DefaultElementClass)
   989                     self.AddToLookupClass(name, parent, DefaultElementClass)
   990                 elif namespace == self.TargetNamespace:
   990                 elif namespace == self.TargetNamespace:
   991                     self.AddToLookupClass(name, parent, type_name)
   991                     self.AddToLookupClass(name, parent, type_name)
   992             if infos["type"] == COMPLEXTYPE:
   992             if infos["type"] == COMPLEXTYPE:
   993                 type_name, parent = self.SplitQualifiedName(type_name, namespace)
   993                 type_name, parent = self.SplitQualifiedName(type_name, namespace)
   994                 result = self.CreateClass(type_name, parent, infos)
   994                 result = self.CreateClass(type_name, parent, infos)
   995                 if result is not None and not isinstance(result, (UnicodeType, StringType)):
   995                 if result is not None and not isinstance(result, string_types):
   996                     self.Namespaces[self.TargetNamespace][result["name"]] = result
   996                     self.Namespaces[self.TargetNamespace][result["name"]] = result
   997                 return result
   997                 return result
   998             elif infos["type"] == ELEMENT and infos["elmt_type"]["type"] == COMPLEXTYPE:
   998             elif infos["type"] == ELEMENT and infos["elmt_type"]["type"] == COMPLEXTYPE:
   999                 type_name, parent = self.SplitQualifiedName(type_name, namespace)
   999                 type_name, parent = self.SplitQualifiedName(type_name, namespace)
  1000                 result = self.CreateClass(type_name, parent, infos["elmt_type"])
  1000                 result = self.CreateClass(type_name, parent, infos["elmt_type"])
  1001                 if result is not None and not isinstance(result, (UnicodeType, StringType)):
  1001                 if result is not None and not isinstance(result, string_types):
  1002                     self.Namespaces[self.TargetNamespace][result["name"]] = result
  1002                     self.Namespaces[self.TargetNamespace][result["name"]] = result
  1003                 return result
  1003                 return result
  1004             else:
  1004             else:
  1005                 return infos
  1005                 return infos
  1006         elif typeinfos["type"] == COMPLEXTYPE:
  1006         elif typeinfos["type"] == COMPLEXTYPE:
  1018         Method that generates the classes
  1018         Method that generates the classes
  1019         """
  1019         """
  1020         self.ParseSchema()
  1020         self.ParseSchema()
  1021         for name, infos in self.Namespaces[self.TargetNamespace].items():
  1021         for name, infos in self.Namespaces[self.TargetNamespace].items():
  1022             if infos["type"] == ELEMENT:
  1022             if infos["type"] == ELEMENT:
  1023                 if not isinstance(infos["elmt_type"], (UnicodeType, StringType)) and \
  1023                 if not isinstance(infos["elmt_type"], string_types) and \
  1024                    infos["elmt_type"]["type"] == COMPLEXTYPE:
  1024                    infos["elmt_type"]["type"] == COMPLEXTYPE:
  1025                     self.ComputeAfter.append((name, None, infos["elmt_type"], True))
  1025                     self.ComputeAfter.append((name, None, infos["elmt_type"], True))
  1026                     while len(self.ComputeAfter) > 0:
  1026                     while len(self.ComputeAfter) > 0:
  1027                         result = self.CreateClass(*self.ComputeAfter.pop(0))
  1027                         result = self.CreateClass(*self.ComputeAfter.pop(0))
  1028                         if result is not None and not isinstance(result, (UnicodeType, StringType)):
  1028                         if result is not None and not isinstance(result, string_types):
  1029                             self.Namespaces[self.TargetNamespace][result["name"]] = result
  1029                             self.Namespaces[self.TargetNamespace][result["name"]] = result
  1030             elif infos["type"] == COMPLEXTYPE:
  1030             elif infos["type"] == COMPLEXTYPE:
  1031                 self.ComputeAfter.append((name, None, infos))
  1031                 self.ComputeAfter.append((name, None, infos))
  1032                 while len(self.ComputeAfter) > 0:
  1032                 while len(self.ComputeAfter) > 0:
  1033                     result = self.CreateClass(*self.ComputeAfter.pop(0))
  1033                     result = self.CreateClass(*self.ComputeAfter.pop(0))
  1034                     if result is not None and \
  1034                     if result is not None and \
  1035                        not isinstance(result, (UnicodeType, StringType)):
  1035                        not isinstance(result, string_types):
  1036                         self.Namespaces[self.TargetNamespace][result["name"]] = result
  1036                         self.Namespaces[self.TargetNamespace][result["name"]] = result
  1037             elif infos["type"] == ELEMENTSGROUP:
  1037             elif infos["type"] == ELEMENTSGROUP:
  1038                 elements = []
  1038                 elements = []
  1039                 if "elements" in infos:
  1039                 if "elements" in infos:
  1040                     elements = infos["elements"]
  1040                     elements = infos["elements"]
  1041                 elif "choices" in infos:
  1041                 elif "choices" in infos:
  1042                     elements = infos["choices"]
  1042                     elements = infos["choices"]
  1043                 for element in elements:
  1043                 for element in elements:
  1044                     if not isinstance(element["elmt_type"], (UnicodeType, StringType)) and \
  1044                     if not isinstance(element["elmt_type"], string_types) and \
  1045                        element["elmt_type"]["type"] == COMPLEXTYPE:
  1045                        element["elmt_type"]["type"] == COMPLEXTYPE:
  1046                         self.ComputeAfter.append((element["name"], infos["name"], element["elmt_type"]))
  1046                         self.ComputeAfter.append((element["name"], infos["name"], element["elmt_type"]))
  1047                         while len(self.ComputeAfter) > 0:
  1047                         while len(self.ComputeAfter) > 0:
  1048                             result = self.CreateClass(*self.ComputeAfter.pop(0))
  1048                             result = self.CreateClass(*self.ComputeAfter.pop(0))
  1049                             if result is not None and \
  1049                             if result is not None and \
  1050                                not isinstance(result, (UnicodeType, StringType)):
  1050                                not isinstance(result, string_types):
  1051                                 self.Namespaces[self.TargetNamespace][result["name"]] = result
  1051                                 self.Namespaces[self.TargetNamespace][result["name"]] = result
  1052 
  1052 
  1053         for name, parents in self.ComputedClassesLookUp.iteritems():
  1053         for name, parents in self.ComputedClassesLookUp.iteritems():
  1054             if isinstance(parents, DictType):
  1054             if isinstance(parents, dict):
  1055                 computed_classes = parents.items()
  1055                 computed_classes = parents.items()
  1056             elif parents[1] is not None:
  1056             elif parents[1] is not None:
  1057                 computed_classes = [(self.etreeNamespaceFormat % parents[1], parents[0])]
  1057                 computed_classes = [(self.etreeNamespaceFormat % parents[1], parents[0])]
  1058             else:
  1058             else:
  1059                 computed_classes = []
  1059                 computed_classes = []
  1060             for parent, computed_class in computed_classes:
  1060             for parent, computed_class in computed_classes:
  1061                 for equivalent_parent in self.GetEquivalentParents(parent):
  1061                 for equivalent_parent in self.GetEquivalentParents(parent):
  1062                     if not isinstance(parents, DictType):
  1062                     if not isinstance(parents, dict):
  1063                         parents = dict(computed_classes)
  1063                         parents = dict(computed_classes)
  1064                         self.ComputedClassesLookUp[name] = parents
  1064                         self.ComputedClassesLookUp[name] = parents
  1065                     parents[equivalent_parent] = computed_class
  1065                     parents[equivalent_parent] = computed_class
  1066 
  1066 
  1067         return self.ComputedClasses
  1067         return self.ComputedClasses
  1380 
  1380 
  1381                         insertion_point = len(self.xpath(previous_elements_xpath, namespaces=factory.NSMAP))
  1381                         insertion_point = len(self.xpath(previous_elements_xpath, namespaces=factory.NSMAP))
  1382                     else:
  1382                     else:
  1383                         insertion_point = 0
  1383                         insertion_point = 0
  1384 
  1384 
  1385                     if not isinstance(value, ListType):
  1385                     if not isinstance(value, list):
  1386                         value = [value]
  1386                         value = [value]
  1387 
  1387 
  1388                     for element in reversed(value):
  1388                     for element in reversed(value):
  1389                         if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1389                         if element_infos["elmt_type"]["type"] == SIMPLETYPE:
  1390                             tmp_element = factory.Parser.makeelement(factory.etreeNamespaceFormat % name)
  1390                             tmp_element = factory.Parser.makeelement(factory.etreeNamespaceFormat % name)
  1746         self.ElementTag = None
  1746         self.ElementTag = None
  1747         self.ElementClass = None
  1747         self.ElementClass = None
  1748 
  1748 
  1749     def GetElementClass(self, element_tag, parent_tag=None, default=DefaultElementClass):
  1749     def GetElementClass(self, element_tag, parent_tag=None, default=DefaultElementClass):
  1750         element_class = self.LookUpClasses.get(element_tag, (default, None))
  1750         element_class = self.LookUpClasses.get(element_tag, (default, None))
  1751         if not isinstance(element_class, DictType):
  1751         if not isinstance(element_class, dict):
  1752             if isinstance(element_class[0], (StringType, UnicodeType)):
  1752             if isinstance(element_class[0], string_types):
  1753                 return self.GetElementClass(element_class[0], default=default)
  1753                 return self.GetElementClass(element_class[0], default=default)
  1754             return element_class[0]
  1754             return element_class[0]
  1755 
  1755 
  1756         element_with_parent_class = element_class.get(parent_tag, default)
  1756         element_with_parent_class = element_class.get(parent_tag, default)
  1757         if isinstance(element_with_parent_class, (StringType, UnicodeType)):
  1757         if isinstance(element_with_parent_class, string_types):
  1758             return self.GetElementClass(element_with_parent_class, default=default)
  1758             return self.GetElementClass(element_with_parent_class, default=default)
  1759         return element_with_parent_class
  1759         return element_with_parent_class
  1760 
  1760 
  1761     def SetLookupResult(self, element, element_class):
  1761     def SetLookupResult(self, element, element_class):
  1762         """
  1762         """
  1809             return element_class
  1809             return element_class
  1810 
  1810 
  1811         parent = element.getparent()
  1811         parent = element.getparent()
  1812         element_class = self.GetElementClass(
  1812         element_class = self.GetElementClass(
  1813             element.tag, parent.tag if parent is not None else None)
  1813             element.tag, parent.tag if parent is not None else None)
  1814         if isinstance(element_class, ListType):
  1814         if isinstance(element_class, list):
  1815             children = "".join([
  1815             children = "".join([
  1816                 "%s " % etree.QName(child.tag).localname
  1816                 "%s " % etree.QName(child.tag).localname
  1817                 for child in element])
  1817                 for child in element])
  1818             for possible_class in element_class:
  1818             for possible_class in element_class:
  1819                 if isinstance(possible_class, (StringType, UnicodeType)):
  1819                 if isinstance(possible_class, string_types):
  1820                     possible_class = self.GetElementClass(possible_class)
  1820                     possible_class = self.GetElementClass(possible_class)
  1821                 if possible_class.StructurePattern.match(children) is not None:
  1821                 if possible_class.StructurePattern.match(children) is not None:
  1822                     return possible_class
  1822                     return possible_class
  1823             return element_class[0]
  1823             return element_class[0]
  1824         return element_class
  1824         return element_class
  1888         :return:
  1888         :return:
  1889             created XML element
  1889             created XML element
  1890             (subclass of lxml.etree._Element created by class factory)
  1890             (subclass of lxml.etree._Element created by class factory)
  1891         """
  1891         """
  1892         element_class = self.GetElementClass(element_tag, parent_tag)
  1892         element_class = self.GetElementClass(element_tag, parent_tag)
  1893         if isinstance(element_class, ListType):
  1893         if isinstance(element_class, list):
  1894             if class_idx is not None and class_idx < len(element_class):
  1894             if class_idx is not None and class_idx < len(element_class):
  1895                 element_class = element_class[class_idx]
  1895                 element_class = element_class[class_idx]
  1896             else:
  1896             else:
  1897                 raise ValueError("No corresponding class found!")
  1897                 raise ValueError("No corresponding class found!")
  1898         return self.CreateElementFromClass(element_class, element_tag)
  1898         return self.CreateElementFromClass(element_class, element_tag)