--- a/xmlclass/xmlclass.py Mon Sep 23 00:32:39 2013 +0200
+++ b/xmlclass/xmlclass.py Tue Sep 24 00:44:06 2013 +0200
@@ -925,7 +925,21 @@
if name != base:
equivalences = self.EquivalentClassesParent.setdefault(self.etreeNamespaceFormat % base, {})
equivalences[self.etreeNamespaceFormat % name] = True
-
+
+ def AddDistinctionBetweenParentsInLookupClass(
+ self, lookup_classes, parent, typeinfos):
+ parent = (self.etreeNamespaceFormat % parent
+ if parent is not None else None)
+ parent_class = lookup_classes.get(parent)
+ if parent_class is not None:
+ if isinstance(parent_class, ListType):
+ if typeinfos not in parent_class:
+ lookup_classes[parent].append(typeinfos)
+ elif parent_class != typeinfos:
+ lookup_classes[parent] = [parent_class, typeinfos]
+ else:
+ lookup_classes[parent] = typeinfos
+
def AddToLookupClass(self, name, parent, typeinfos):
lookup_name = self.etreeNamespaceFormat % name
if isinstance(typeinfos, (StringType, UnicodeType)):
@@ -935,13 +949,14 @@
if lookup_classes is None:
self.ComputedClassesLookUp[lookup_name] = (typeinfos, parent)
elif isinstance(lookup_classes, DictType):
- lookup_classes[self.etreeNamespaceFormat % parent
- if parent is not None else None] = typeinfos
- else:
- lookup_classes = {self.etreeNamespaceFormat % lookup_classes[1]
- if lookup_classes[1] is not None else None: lookup_classes[0]}
- lookup_classes[self.etreeNamespaceFormat % parent
- if parent is not None else None] = typeinfos
+ self.AddDistinctionBetweenParentsInLookupClass(
+ lookup_classes, parent, typeinfos)
+ else:
+ lookup_classes = {
+ self.etreeNamespaceFormat % lookup_classes[1]
+ if lookup_classes[1] is not None else None: lookup_classes[0]}
+ self.AddDistinctionBetweenParentsInLookupClass(
+ lookup_classes, parent, typeinfos)
self.ComputedClassesLookUp[lookup_name] = lookup_classes
def ExtractTypeInfos(self, name, parent, typeinfos):
@@ -1130,6 +1145,7 @@
classmembers["get%s" % elmtname] = generateGetMethod(elmtname)
classmembers["_init_"] = generateInitMethod(self, classinfos)
+ classmembers["StructurePattern"] = GetStructurePattern(classinfos)
classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos)
classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos)
classmembers["setElementValue"] = generateSetElementValue(self, classinfos)
@@ -1177,6 +1193,60 @@
print classname
"""
+Method that generate the method for generating the xml tree structure model by
+following the attributes list defined
+"""
+def ComputeMultiplicity(name, infos):
+ if infos["minOccurs"] == 0:
+ if infos["maxOccurs"] == "unbounded":
+ return "(?:%s)*" % name
+ elif infos["maxOccurs"] == 1:
+ return "(?:%s)?" % name
+ else:
+ return "(?:%s){,%d}" % (name, infos["maxOccurs"])
+ elif infos["minOccurs"] == 1:
+ if infos["maxOccurs"] == "unbounded":
+ return "(?:%s)+" % name
+ elif infos["maxOccurs"] == 1:
+ return "(?:%s)" % name
+ else:
+ return "(?:%s){1,%d}" % (name, infos["maxOccurs"])
+ else:
+ if infos["maxOccurs"] == "unbounded":
+ return "(?:%s){%d,}" % (name, infos["minOccurs"], name)
+ else:
+ return "(?:%s){%d,%d}" % (name, infos["minOccurs"],
+ infos["maxOccurs"])
+
+def GetStructurePattern(classinfos):
+ base_structure_pattern = (
+ classinfos["base"].StructurePattern.pattern[:-1]
+ if classinfos.has_key("base") else "")
+ elements = []
+ for element in classinfos["elements"]:
+ if element["type"] == ANY:
+ infos = element.copy()
+ infos["minOccurs"] = 0
+ elements.append(ComputeMultiplicity("#text |#cdata-section |\w* ", infos))
+ elif element["type"] == CHOICE:
+ choices = []
+ for infos in element["choices"]:
+ if infos["type"] == "sequence":
+ structure = "(?:%s)" % GetStructurePattern(infos)
+ else:
+ structure = "%s " % infos["name"]
+ choices.append(ComputeMultiplicity(structure, infos))
+ elements.append(ComputeMultiplicity("|".join(choices), element))
+ elif element["name"] == "content" and element["elmt_type"]["type"] == SIMPLETYPE:
+ elements.append("(?:#text |#cdata-section )?")
+ else:
+ elements.append(ComputeMultiplicity("%s " % element["name"], element))
+ if classinfos.get("order", True) or len(elements) == 0:
+ return re.compile(base_structure_pattern + "".join(elements) + "$")
+ else:
+ raise ValueError("XSD structure not yet supported!")
+
+"""
Method that generate the method for creating a class instance
"""
def generateClassCreateFunction(class_definition):
@@ -1214,12 +1284,22 @@
return None
elif element_infos["type"] == ANY:
return element_infos["elmt_type"]["extract"](self)
+ elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE:
+ return element_infos["elmt_type"]["extract"](self.text, extract=False)
else:
element_name = factory.etreeNamespaceFormat % name
if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
- return self.findall(element_name)
+ values = self.findall(element_name)
+ if element_infos["elmt_type"]["type"] == SIMPLETYPE:
+ return map(lambda value:
+ element_infos["elmt_type"]["extract"](value.text, extract=False),
+ values)
+ return values
else:
- return self.find(element_name)
+ value = self.find(element_name)
+ if element_infos["elmt_type"]["type"] == SIMPLETYPE:
+ return element_infos["elmt_type"]["extract"](value.text, extract=False)
+ return value
elif classinfos.has_key("base"):
return classinfos["base"].__getattr__(self, name)
@@ -1252,6 +1332,9 @@
if element_infos["type"] == ANY:
element_infos["elmt_type"]["generate"](self, value)
+ elif name == "content" and element_infos["elmt_type"]["type"] == SIMPLETYPE:
+ self.text = element_infos["elmt_type"]["generate"](value)
+
else:
prefix = ("%s:" % factory.TargetNamespace
if factory.TargetNamespace is not None else "")
@@ -1277,8 +1360,12 @@
if not isinstance(value, ListType):
value = [value]
-
+
for element in reversed(value):
+ if element_infos["elmt_type"]["type"] == SIMPLETYPE:
+ tmp_element = etree.Element(factory.etreeNamespaceFormat % name)
+ tmp_element.text = element_infos["elmt_type"]["generate"](element)
+ element = tmp_element
self.insert(insertion_point, element)
elif classinfos.has_key("base"):
@@ -1596,6 +1683,8 @@
class DefaultElementClass(etree.ElementBase):
+ StructurePattern = re.compile("$")
+
def _init_(self):
pass
@@ -1625,8 +1714,19 @@
def lookup(self, document, element):
parent = element.getparent()
- return self.GetElementClass(element.tag,
+ element_class = self.GetElementClass(element.tag,
parent.tag if parent is not None else None)
+ if isinstance(element_class, ListType):
+ children = "".join([
+ "%s " % etree.QName(child.tag).localname
+ for child in element])
+ for possible_class in element_class:
+ if isinstance(possible_class, (StringType, UnicodeType)):
+ possible_class = self.GetElementClass(possible_class)
+ if possible_class.StructurePattern.match(children) is not None:
+ return possible_class
+ return element_class[0]
+ return element_class
class XMLClassParser(etree.XMLParser):
@@ -1669,19 +1769,26 @@
if parent_tag is not None else parent_tag,
None)
- def CreateElement(self, element_tag, parent_tag=None):
- new_element = self.GetElementClass(element_tag, parent_tag)()
+ def CreateElement(self, element_tag, parent_tag=None, class_idx=None):
+ element_class = self.GetElementClass(element_tag, parent_tag)
+ if isinstance(element_class, ListType):
+ if class_idx is not None and class_idx < len(element_class):
+ new_element = element_class[class_idx]()
+ else:
+ raise ValueError, "No corresponding class found!"
+ else:
+ new_element = element_class()
DefaultElementClass.__setattr__(new_element, "tag", self.DefaultNamespaceFormat % element_tag)
new_element._init_()
return new_element
def GenerateParser(factory, xsdstring):
ComputedClasses = factory.CreateClasses()
- if factory.FileName is not None and len(ComputedClasses) == 1:
+
+ if factory.FileName is not None:
ComputedClasses = ComputedClasses[factory.FileName]
BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass]
- UpdateXMLClassGlobals(ComputedClasses)
-
+
parser = XMLClassParser(
factory.NSMAP,
factory.etreeNamespaceFormat,
@@ -1693,6 +1800,3 @@
return parser
-def UpdateXMLClassGlobals(classes):
- globals().update(classes)
-