923 |
923 |
924 def AddEquivalentClass(self, name, base): |
924 def AddEquivalentClass(self, name, base): |
925 if name != base: |
925 if name != base: |
926 equivalences = self.EquivalentClassesParent.setdefault(self.etreeNamespaceFormat % base, {}) |
926 equivalences = self.EquivalentClassesParent.setdefault(self.etreeNamespaceFormat % base, {}) |
927 equivalences[self.etreeNamespaceFormat % name] = True |
927 equivalences[self.etreeNamespaceFormat % name] = True |
928 |
928 |
|
929 def AddDistinctionBetweenParentsInLookupClass( |
|
930 self, lookup_classes, parent, typeinfos): |
|
931 parent = (self.etreeNamespaceFormat % parent |
|
932 if parent is not None else None) |
|
933 parent_class = lookup_classes.get(parent) |
|
934 if parent_class is not None: |
|
935 if isinstance(parent_class, ListType): |
|
936 if typeinfos not in parent_class: |
|
937 lookup_classes[parent].append(typeinfos) |
|
938 elif parent_class != typeinfos: |
|
939 lookup_classes[parent] = [parent_class, typeinfos] |
|
940 else: |
|
941 lookup_classes[parent] = typeinfos |
|
942 |
929 def AddToLookupClass(self, name, parent, typeinfos): |
943 def AddToLookupClass(self, name, parent, typeinfos): |
930 lookup_name = self.etreeNamespaceFormat % name |
944 lookup_name = self.etreeNamespaceFormat % name |
931 if isinstance(typeinfos, (StringType, UnicodeType)): |
945 if isinstance(typeinfos, (StringType, UnicodeType)): |
932 self.AddEquivalentClass(name, typeinfos) |
946 self.AddEquivalentClass(name, typeinfos) |
933 typeinfos = self.etreeNamespaceFormat % typeinfos |
947 typeinfos = self.etreeNamespaceFormat % typeinfos |
934 lookup_classes = self.ComputedClassesLookUp.get(lookup_name) |
948 lookup_classes = self.ComputedClassesLookUp.get(lookup_name) |
935 if lookup_classes is None: |
949 if lookup_classes is None: |
936 self.ComputedClassesLookUp[lookup_name] = (typeinfos, parent) |
950 self.ComputedClassesLookUp[lookup_name] = (typeinfos, parent) |
937 elif isinstance(lookup_classes, DictType): |
951 elif isinstance(lookup_classes, DictType): |
938 lookup_classes[self.etreeNamespaceFormat % parent |
952 self.AddDistinctionBetweenParentsInLookupClass( |
939 if parent is not None else None] = typeinfos |
953 lookup_classes, parent, typeinfos) |
940 else: |
954 else: |
941 lookup_classes = {self.etreeNamespaceFormat % lookup_classes[1] |
955 lookup_classes = { |
942 if lookup_classes[1] is not None else None: lookup_classes[0]} |
956 self.etreeNamespaceFormat % lookup_classes[1] |
943 lookup_classes[self.etreeNamespaceFormat % parent |
957 if lookup_classes[1] is not None else None: lookup_classes[0]} |
944 if parent is not None else None] = typeinfos |
958 self.AddDistinctionBetweenParentsInLookupClass( |
|
959 lookup_classes, parent, typeinfos) |
945 self.ComputedClassesLookUp[lookup_name] = lookup_classes |
960 self.ComputedClassesLookUp[lookup_name] = lookup_classes |
946 |
961 |
947 def ExtractTypeInfos(self, name, parent, typeinfos): |
962 def ExtractTypeInfos(self, name, parent, typeinfos): |
948 if isinstance(typeinfos, (StringType, UnicodeType)): |
963 if isinstance(typeinfos, (StringType, UnicodeType)): |
949 namespace, type_name = DecomposeQualifiedName(typeinfos) |
964 namespace, type_name = DecomposeQualifiedName(typeinfos) |
1128 classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname) |
1143 classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname) |
1129 classmembers["set%s" % elmtname] = generateSetMethod(elmtname) |
1144 classmembers["set%s" % elmtname] = generateSetMethod(elmtname) |
1130 classmembers["get%s" % elmtname] = generateGetMethod(elmtname) |
1145 classmembers["get%s" % elmtname] = generateGetMethod(elmtname) |
1131 |
1146 |
1132 classmembers["_init_"] = generateInitMethod(self, classinfos) |
1147 classmembers["_init_"] = generateInitMethod(self, classinfos) |
|
1148 classmembers["StructurePattern"] = GetStructurePattern(classinfos) |
1133 classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos) |
1149 classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos) |
1134 classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos) |
1150 classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos) |
1135 classmembers["setElementValue"] = generateSetElementValue(self, classinfos) |
1151 classmembers["setElementValue"] = generateSetElementValue(self, classinfos) |
1136 |
1152 |
1137 class_definition = classobj(str(classname), bases, classmembers) |
1153 class_definition = classobj(str(classname), bases, classmembers) |
1173 def PrintClassNames(self): |
1189 def PrintClassNames(self): |
1174 classnames = self.XMLClassDefinitions.keys() |
1190 classnames = self.XMLClassDefinitions.keys() |
1175 classnames.sort() |
1191 classnames.sort() |
1176 for classname in classnames: |
1192 for classname in classnames: |
1177 print classname |
1193 print classname |
|
1194 |
|
1195 """ |
|
1196 Method that generate the method for generating the xml tree structure model by |
|
1197 following the attributes list defined |
|
1198 """ |
|
1199 def ComputeMultiplicity(name, infos): |
|
1200 if infos["minOccurs"] == 0: |
|
1201 if infos["maxOccurs"] == "unbounded": |
|
1202 return "(?:%s)*" % name |
|
1203 elif infos["maxOccurs"] == 1: |
|
1204 return "(?:%s)?" % name |
|
1205 else: |
|
1206 return "(?:%s){,%d}" % (name, infos["maxOccurs"]) |
|
1207 elif infos["minOccurs"] == 1: |
|
1208 if infos["maxOccurs"] == "unbounded": |
|
1209 return "(?:%s)+" % name |
|
1210 elif infos["maxOccurs"] == 1: |
|
1211 return "(?:%s)" % name |
|
1212 else: |
|
1213 return "(?:%s){1,%d}" % (name, infos["maxOccurs"]) |
|
1214 else: |
|
1215 if infos["maxOccurs"] == "unbounded": |
|
1216 return "(?:%s){%d,}" % (name, infos["minOccurs"], name) |
|
1217 else: |
|
1218 return "(?:%s){%d,%d}" % (name, infos["minOccurs"], |
|
1219 infos["maxOccurs"]) |
|
1220 |
|
1221 def GetStructurePattern(classinfos): |
|
1222 base_structure_pattern = ( |
|
1223 classinfos["base"].StructurePattern.pattern[:-1] |
|
1224 if classinfos.has_key("base") else "") |
|
1225 elements = [] |
|
1226 for element in classinfos["elements"]: |
|
1227 if element["type"] == ANY: |
|
1228 infos = element.copy() |
|
1229 infos["minOccurs"] = 0 |
|
1230 elements.append(ComputeMultiplicity("#text |#cdata-section |\w* ", infos)) |
|
1231 elif element["type"] == CHOICE: |
|
1232 choices = [] |
|
1233 for infos in element["choices"]: |
|
1234 if infos["type"] == "sequence": |
|
1235 structure = "(?:%s)" % GetStructurePattern(infos) |
|
1236 else: |
|
1237 structure = "%s " % infos["name"] |
|
1238 choices.append(ComputeMultiplicity(structure, infos)) |
|
1239 elements.append(ComputeMultiplicity("|".join(choices), element)) |
|
1240 elif element["name"] == "content" and element["elmt_type"]["type"] == SIMPLETYPE: |
|
1241 elements.append("(?:#text |#cdata-section )?") |
|
1242 else: |
|
1243 elements.append(ComputeMultiplicity("%s " % element["name"], element)) |
|
1244 if classinfos.get("order", True) or len(elements) == 0: |
|
1245 return re.compile(base_structure_pattern + "".join(elements) + "$") |
|
1246 else: |
|
1247 raise ValueError("XSD structure not yet supported!") |
1178 |
1248 |
1179 """ |
1249 """ |
1180 Method that generate the method for creating a class instance |
1250 Method that generate the method for creating a class instance |
1181 """ |
1251 """ |
1182 def generateClassCreateFunction(class_definition): |
1252 def generateClassCreateFunction(class_definition): |
1212 elif len(content) > 0: |
1282 elif len(content) > 0: |
1213 return content[0] |
1283 return content[0] |
1214 return None |
1284 return None |
1215 elif element_infos["type"] == ANY: |
1285 elif element_infos["type"] == ANY: |
1216 return element_infos["elmt_type"]["extract"](self) |
1286 return element_infos["elmt_type"]["extract"](self) |
|
1287 elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE: |
|
1288 return element_infos["elmt_type"]["extract"](self.text, extract=False) |
1217 else: |
1289 else: |
1218 element_name = factory.etreeNamespaceFormat % name |
1290 element_name = factory.etreeNamespaceFormat % name |
1219 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1: |
1291 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1: |
1220 return self.findall(element_name) |
1292 values = self.findall(element_name) |
|
1293 if element_infos["elmt_type"]["type"] == SIMPLETYPE: |
|
1294 return map(lambda value: |
|
1295 element_infos["elmt_type"]["extract"](value.text, extract=False), |
|
1296 values) |
|
1297 return values |
1221 else: |
1298 else: |
1222 return self.find(element_name) |
1299 value = self.find(element_name) |
|
1300 if element_infos["elmt_type"]["type"] == SIMPLETYPE: |
|
1301 return element_infos["elmt_type"]["extract"](value.text, extract=False) |
|
1302 return value |
1223 |
1303 |
1224 elif classinfos.has_key("base"): |
1304 elif classinfos.has_key("base"): |
1225 return classinfos["base"].__getattr__(self, name) |
1305 return classinfos["base"].__getattr__(self, name) |
1226 |
1306 |
1227 return DefaultElementClass.__getattribute__(self, name) |
1307 return DefaultElementClass.__getattribute__(self, name) |
1249 elif elements.has_key(name): |
1329 elif elements.has_key(name): |
1250 element_infos = elements[name] |
1330 element_infos = elements[name] |
1251 element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"]) |
1331 element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"]) |
1252 if element_infos["type"] == ANY: |
1332 if element_infos["type"] == ANY: |
1253 element_infos["elmt_type"]["generate"](self, value) |
1333 element_infos["elmt_type"]["generate"](self, value) |
|
1334 |
|
1335 elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE: |
|
1336 self.text = element_infos["elmt_type"]["generate"](value) |
1254 |
1337 |
1255 else: |
1338 else: |
1256 prefix = ("%s:" % factory.TargetNamespace |
1339 prefix = ("%s:" % factory.TargetNamespace |
1257 if factory.TargetNamespace is not None else "") |
1340 if factory.TargetNamespace is not None else "") |
1258 element_xpath = (prefix + name |
1341 element_xpath = (prefix + name |
1275 else: |
1358 else: |
1276 insertion_point = 0 |
1359 insertion_point = 0 |
1277 |
1360 |
1278 if not isinstance(value, ListType): |
1361 if not isinstance(value, ListType): |
1279 value = [value] |
1362 value = [value] |
1280 |
1363 |
1281 for element in reversed(value): |
1364 for element in reversed(value): |
|
1365 if element_infos["elmt_type"]["type"] == SIMPLETYPE: |
|
1366 tmp_element = etree.Element(factory.etreeNamespaceFormat % name) |
|
1367 tmp_element.text = element_infos["elmt_type"]["generate"](element) |
|
1368 element = tmp_element |
1282 self.insert(insertion_point, element) |
1369 self.insert(insertion_point, element) |
1283 |
1370 |
1284 elif classinfos.has_key("base"): |
1371 elif classinfos.has_key("base"): |
1285 return classinfos["base"].__setattr__(self, name, value) |
1372 return classinfos["base"].__setattr__(self, name, value) |
1286 |
1373 |
1623 return self.GetElementClass(element_with_parent_class, default=default) |
1712 return self.GetElementClass(element_with_parent_class, default=default) |
1624 return element_with_parent_class |
1713 return element_with_parent_class |
1625 |
1714 |
1626 def lookup(self, document, element): |
1715 def lookup(self, document, element): |
1627 parent = element.getparent() |
1716 parent = element.getparent() |
1628 return self.GetElementClass(element.tag, |
1717 element_class = self.GetElementClass(element.tag, |
1629 parent.tag if parent is not None else None) |
1718 parent.tag if parent is not None else None) |
|
1719 if isinstance(element_class, ListType): |
|
1720 children = "".join([ |
|
1721 "%s " % etree.QName(child.tag).localname |
|
1722 for child in element]) |
|
1723 for possible_class in element_class: |
|
1724 if isinstance(possible_class, (StringType, UnicodeType)): |
|
1725 possible_class = self.GetElementClass(possible_class) |
|
1726 if possible_class.StructurePattern.match(children) is not None: |
|
1727 return possible_class |
|
1728 return element_class[0] |
|
1729 return element_class |
1630 |
1730 |
1631 class XMLClassParser(etree.XMLParser): |
1731 class XMLClassParser(etree.XMLParser): |
1632 |
1732 |
1633 def __init__(self, namespaces, default_namespace_format, base_class, *args, **kwargs): |
1733 def __init__(self, namespaces, default_namespace_format, base_class, *args, **kwargs): |
1634 etree.XMLParser.__init__(self, *args, **kwargs) |
1734 etree.XMLParser.__init__(self, *args, **kwargs) |
1667 self.DefaultNamespaceFormat % element_tag, |
1767 self.DefaultNamespaceFormat % element_tag, |
1668 self.DefaultNamespaceFormat % parent_tag |
1768 self.DefaultNamespaceFormat % parent_tag |
1669 if parent_tag is not None else parent_tag, |
1769 if parent_tag is not None else parent_tag, |
1670 None) |
1770 None) |
1671 |
1771 |
1672 def CreateElement(self, element_tag, parent_tag=None): |
1772 def CreateElement(self, element_tag, parent_tag=None, class_idx=None): |
1673 new_element = self.GetElementClass(element_tag, parent_tag)() |
1773 element_class = self.GetElementClass(element_tag, parent_tag) |
|
1774 if isinstance(element_class, ListType): |
|
1775 if class_idx is not None and class_idx < len(element_class): |
|
1776 new_element = element_class[class_idx]() |
|
1777 else: |
|
1778 raise ValueError, "No corresponding class found!" |
|
1779 else: |
|
1780 new_element = element_class() |
1674 DefaultElementClass.__setattr__(new_element, "tag", self.DefaultNamespaceFormat % element_tag) |
1781 DefaultElementClass.__setattr__(new_element, "tag", self.DefaultNamespaceFormat % element_tag) |
1675 new_element._init_() |
1782 new_element._init_() |
1676 return new_element |
1783 return new_element |
1677 |
1784 |
1678 def GenerateParser(factory, xsdstring): |
1785 def GenerateParser(factory, xsdstring): |
1679 ComputedClasses = factory.CreateClasses() |
1786 ComputedClasses = factory.CreateClasses() |
1680 if factory.FileName is not None and len(ComputedClasses) == 1: |
1787 |
|
1788 if factory.FileName is not None: |
1681 ComputedClasses = ComputedClasses[factory.FileName] |
1789 ComputedClasses = ComputedClasses[factory.FileName] |
1682 BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass] |
1790 BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass] |
1683 UpdateXMLClassGlobals(ComputedClasses) |
1791 |
1684 |
|
1685 parser = XMLClassParser( |
1792 parser = XMLClassParser( |
1686 factory.NSMAP, |
1793 factory.NSMAP, |
1687 factory.etreeNamespaceFormat, |
1794 factory.etreeNamespaceFormat, |
1688 BaseClass[0] if len(BaseClass) == 1 else None, |
1795 BaseClass[0] if len(BaseClass) == 1 else None, |
1689 schema = etree.XMLSchema(etree.fromstring(xsdstring)), |
1796 schema = etree.XMLSchema(etree.fromstring(xsdstring)), |