changeset 592 | 89ff2738ef20 |
parent 565 | 94c11207aa6f |
child 593 | 34c3569042db |
591:4d6719c51f05 | 592:89ff2738ef20 |
---|---|
20 # |
20 # |
21 #You should have received a copy of the GNU General Public |
21 #You should have received a copy of the GNU General Public |
22 #License along with this library; if not, write to the Free Software |
22 #License along with this library; if not, write to the Free Software |
23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
24 |
24 |
25 import sys |
25 import os, sys |
26 import re |
26 import re |
27 import datetime |
27 import datetime |
28 from types import * |
28 from types import * |
29 from xml.dom import minidom |
29 from xml.dom import minidom |
30 from xml.sax.saxutils import escape, unescape, quoteattr |
30 from xml.sax.saxutils import escape, unescape, quoteattr |
90 |
90 |
91 def dst(self, dt): |
91 def dst(self, dt): |
92 return ZERO |
92 return ZERO |
93 |
93 |
94 [SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE, |
94 [SYNTAXELEMENT, SYNTAXATTRIBUTE, SIMPLETYPE, COMPLEXTYPE, COMPILEDCOMPLEXTYPE, |
95 ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG |
95 ATTRIBUTESGROUP, ELEMENTSGROUP, ATTRIBUTE, ELEMENT, CHOICE, ANY, TAG, CONSTRAINT, |
96 ] = range(12) |
96 ] = range(13) |
97 |
97 |
98 def NotSupportedYet(type): |
98 def NotSupportedYet(type): |
99 """ |
99 """ |
100 Function that generates a function that point out to user that datatype |
100 Function that generates a function that point out to user that datatype |
101 used is not supported by xmlclass yet |
101 used is not supported by xmlclass yet |
124 @return: data extracted as string |
124 @return: data extracted as string |
125 """ |
125 """ |
126 if not extract: |
126 if not extract: |
127 return attr |
127 return attr |
128 if len(attr.childNodes) == 1: |
128 if len(attr.childNodes) == 1: |
129 return unescape(attr.childNodes[0].data.encode()) |
129 return unescape(attr.childNodes[0].data.encode("utf-8")) |
130 else: |
130 else: |
131 # content is a CDATA |
131 # content is a CDATA |
132 text = "" |
132 text = "" |
133 for node in attr.childNodes: |
133 for node in attr.childNodes: |
134 if node.nodeName != "#text": |
134 if node.nodeName != "#text": |
135 text += node.data.encode() |
135 text += node.data.encode("utf-8") |
136 return text |
136 return text |
137 |
137 |
138 |
138 |
139 def GetNormalizedString(attr, extract=True): |
139 def GetNormalizedString(attr, extract=True): |
140 """ |
140 """ |
530 raise ValueError("\"%s\" isn't a valid value for %s!" % \ |
530 raise ValueError("\"%s\" isn't a valid value for %s!" % \ |
531 (value, type)) |
531 (value, type)) |
532 return values |
532 return values |
533 return GetModelNameList |
533 return GetModelNameList |
534 |
534 |
535 def GenerateAnyInfos(): |
535 def GenerateAnyInfos(infos): |
536 def ExtractAny(tree): |
536 def ExtractAny(tree): |
537 return tree.data.encode("utf-8") |
537 if tree.nodeName == "#cdata-section": |
538 return tree.data.encode("utf-8") |
|
539 else: |
|
540 return tree |
|
538 |
541 |
539 def GenerateAny(value, name=None, indent=0): |
542 def GenerateAny(value, name=None, indent=0): |
540 try: |
543 if isinstance(value, (StringType, UnicodeType)): |
541 value = value.decode("utf-8") |
544 try: |
542 except: |
545 value = value.decode("utf-8") |
543 pass |
546 except: |
544 return u'<![CDATA[%s]]>\n' % value |
547 pass |
548 return u'<![CDATA[%s]]>\n' % value |
|
549 else: |
|
550 return value.toprettyxml(indent=" "*indent, encoding="utf-8") |
|
545 |
551 |
546 return { |
552 return { |
547 "type": COMPLEXTYPE, |
553 "type": COMPLEXTYPE, |
548 "extract": ExtractAny, |
554 "extract": ExtractAny, |
549 "generate": GenerateAny, |
555 "generate": GenerateAny, |
550 "initial": lambda: "", |
556 "initial": lambda: "", |
551 "check": lambda x: isinstance(x, (StringType, UnicodeType)) |
557 "check": lambda x: isinstance(x, (StringType, UnicodeType, minidom.Node)) |
552 } |
558 } |
553 |
559 |
554 def GenerateTagInfos(name): |
560 def GenerateTagInfos(name): |
555 def ExtractTag(tree): |
561 def ExtractTag(tree): |
556 if len(tree._attrs) > 0: |
562 if len(tree._attrs) > 0: |
571 "extract": ExtractTag, |
577 "extract": ExtractTag, |
572 "generate": GenerateTag, |
578 "generate": GenerateTag, |
573 "initial": lambda: None, |
579 "initial": lambda: None, |
574 "check": lambda x: x == None |
580 "check": lambda x: x == None |
575 } |
581 } |
582 |
|
583 def FindTypeInfos(factory, infos): |
|
584 if isinstance(infos, (UnicodeType, StringType)): |
|
585 namespace, name = DecomposeQualifiedName(infos) |
|
586 return factory.GetQualifiedNameInfos(name, namespace) |
|
587 return infos |
|
576 |
588 |
577 def GenerateContentInfos(factory, choices): |
589 def GetElementInitialValue(factory, infos): |
590 infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
|
591 if infos["minOccurs"] == 0 and infos["maxOccurs"] == 1: |
|
592 if infos.has_key("default"): |
|
593 return infos["elmt_type"]["extract"](infos["default"], False) |
|
594 else: |
|
595 return None |
|
596 elif infos["minOccurs"] == 1 and infos["maxOccurs"] == 1: |
|
597 return infos["elmt_type"]["initial"]() |
|
598 else: |
|
599 return [infos["elmt_type"]["initial"]() for i in xrange(infos["minOccurs"])] |
|
600 |
|
601 def HandleError(message, raise_exception): |
|
602 if raise_exception: |
|
603 raise ValueError(message) |
|
604 return False |
|
605 |
|
606 def CheckElementValue(factory, name, infos, value, raise_exception=True): |
|
607 infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
|
608 if value is None and raise_exception: |
|
609 if not (infos["minOccurs"] == 0 and infos["maxOccurs"] == 1): |
|
610 return HandleError("Attribute '%s' isn't optional." % name, raise_exception) |
|
611 elif infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1: |
|
612 if not isinstance(value, ListType): |
|
613 return HandleError("Attribute '%s' must be a list." % name, raise_exception) |
|
614 if len(value) < infos["minOccurs"] or infos["maxOccurs"] != "unbounded" and len(value) > infos["maxOccurs"]: |
|
615 return HandleError("List out of bounds for attribute '%s'." % name, raise_exception) |
|
616 if not reduce(lambda x, y: x and y, map(infos["elmt_type"]["check"], value), True): |
|
617 return HandleError("Attribute '%s' must be a list of valid elements." % name, raise_exception) |
|
618 elif infos.has_key("fixed") and value != infos["fixed"]: |
|
619 return HandleError("Value of attribute '%s' can only be '%s'." % (name, str(infos["fixed"])), raise_exception) |
|
620 else: |
|
621 return infos["elmt_type"]["check"](value) |
|
622 return True |
|
623 |
|
624 def GetContentInfos(name, choices): |
|
625 for choice_infos in choices: |
|
626 if choices_infos["type"] == "sequence": |
|
627 for element_infos in choices_infos["elements"]: |
|
628 if element_infos["type"] == CHOICE: |
|
629 if GetContentInfos(name, element_infos["choices"]): |
|
630 return choices_infos |
|
631 elif element_infos["name"] == name: |
|
632 return choices_infos |
|
633 elif choice_infos["name"] == name: |
|
634 return choices_infos |
|
635 return None |
|
636 |
|
637 def ComputeContentChoices(factory, name, infos): |
|
638 choices = [] |
|
639 for choice in infos["choices"]: |
|
640 if choice["type"] == "sequence": |
|
641 choice["name"] = "sequence" |
|
642 for sequence_element in choice["elements"]: |
|
643 if sequence_element["type"] != CHOICE: |
|
644 element_infos = factory.ExtractTypeInfos(sequence_element["name"], name, sequence_element["elmt_type"]) |
|
645 if element_infos is not None: |
|
646 sequence_element["elmt_type"] = element_infos |
|
647 elif choice["elmt_type"] == "tag": |
|
648 choice["elmt_type"] = GenerateTagInfos(choice["name"]) |
|
649 else: |
|
650 choice_infos = factory.ExtractTypeInfos(choice["name"], name, choice["elmt_type"]) |
|
651 if choice_infos is not None: |
|
652 choice["elmt_type"] = choice_infos |
|
653 choices.append((choice["name"], choice)) |
|
654 return choices |
|
655 |
|
656 def ExtractContentElement(factory, tree, infos, content): |
|
657 infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
|
658 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1: |
|
659 if isinstance(content, ListType) and len(content) > 0 and \ |
|
660 content[-1]["name"] == tree.nodeName: |
|
661 content_item = content.pop(-1) |
|
662 content_item["value"].append(infos["elmt_type"]["extract"](tree)) |
|
663 return content_item |
|
664 elif not isinstance(content, ListType) and \ |
|
665 content is not None and \ |
|
666 content["name"] == tree.nodeName: |
|
667 return {"name": tree.nodeName, |
|
668 "value": content["value"] + [infos["elmt_type"]["extract"](tree)]} |
|
669 else: |
|
670 return {"name": tree.nodeName, |
|
671 "value": [infos["elmt_type"]["extract"](tree)]} |
|
672 else: |
|
673 return {"name": tree.nodeName, |
|
674 "value": infos["elmt_type"]["extract"](tree)} |
|
675 |
|
676 def GenerateContentInfos(factory, name, choices): |
|
677 choices_dict = {} |
|
678 for choice_name, infos in choices: |
|
679 if choice_name == "sequence": |
|
680 for element in infos["elements"]: |
|
681 if element["type"] == CHOICE: |
|
682 element["elmt_type"] = GenerateContentInfos(factory, name, ComputeContentChoices(factory, name, element)) |
|
683 elif choices_dict.has_key(element["name"]): |
|
684 raise ValueError("'%s' element defined two times in choice" % choice_name) |
|
685 else: |
|
686 choices_dict[element["name"]] = infos |
|
687 else: |
|
688 if choices_dict.has_key(choice_name): |
|
689 raise ValueError("'%s' element defined two times in choice" % choice_name) |
|
690 choices_dict[choice_name] = infos |
|
691 |
|
578 def GetContentInitial(): |
692 def GetContentInitial(): |
579 content_name, infos = choices[0] |
693 content_name, infos = choices[0] |
580 if isinstance(infos["elmt_type"], (UnicodeType, StringType)): |
694 if content_name == "sequence": |
581 namespace, name = DecomposeQualifiedName(infos["elmt_type"]) |
695 content_value = [] |
582 infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
696 for i in xrange(infos["minOccurs"]): |
583 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1: |
697 for element_infos in infos["elements"]: |
584 return {"name": content_name, |
698 value = GetElementInitialValue(factory, element_infos) |
585 "value": map(infos["elmt_type"]["initial"], |
699 if value is not None: |
586 range(infos["minOccurs"]))} |
700 if element_infos["type"] == CHOICE: |
587 else: |
701 content_value.append(value) |
588 return {"name": content_name, |
702 else: |
589 "value": infos["elmt_type"]["initial"]()} |
703 content_value.append({"name": element_infos["name"], "value": value}) |
704 else: |
|
705 content_value = GetElementInitialValue(factory, infos) |
|
706 return {"name": content_name, "value": content_value} |
|
707 |
|
708 def CheckContent(value): |
|
709 if value["name"] != "sequence": |
|
710 infos = choices_dict.get(value["name"], None) |
|
711 if infos is not None: |
|
712 return CheckElementValue(factory, value["name"], infos, value["value"], False) |
|
713 elif len(value["value"]) > 0: |
|
714 infos = choices_dict.get(value["value"][0]["name"], None) |
|
715 if infos is None: |
|
716 for choice_name, infos in choices: |
|
717 if infos["type"] == "sequence": |
|
718 for element_infos in infos["elements"]: |
|
719 if element_infos["type"] == CHOICE: |
|
720 infos = GetContentInfos(value["value"][0]["name"], element_infos["choices"]) |
|
721 if infos is not None: |
|
722 sequence_number = 0 |
|
723 element_idx = 0 |
|
724 while element_idx < len(value["value"]): |
|
725 for element_infos in infos["elements"]: |
|
726 if element_infos["name"] == value["value"][element_idx]["name"]: |
|
727 element_value = value["value"][element_idx]["value"] |
|
728 element_idx += 1 |
|
729 else: |
|
730 element_value = None |
|
731 if not CheckElementValue(factory, element_infos["name"], element_infos, element_value, False): |
|
732 raise ValueError("Invalid sequence value in attribute 'content'") |
|
733 sequence_number += 1 |
|
734 if sequence_number < infos["minOccurs"] or infos["maxOccurs"] != "unbounded" and sequence_number > infos["maxOccurs"]: |
|
735 raise ValueError("Invalid sequence value in attribute 'content'") |
|
736 return True |
|
737 else: |
|
738 for element_name, infos in choices: |
|
739 if element_name == "sequence": |
|
740 required = 0 |
|
741 for element in infos["elements"]: |
|
742 if element["minOccurs"] > 0: |
|
743 required += 1 |
|
744 if required == 0: |
|
745 return True |
|
746 return False |
|
590 |
747 |
591 def CheckContent(value): |
|
592 for content_name, infos in choices: |
|
593 if content_name == value["name"]: |
|
594 if isinstance(infos["elmt_type"], (UnicodeType, StringType)): |
|
595 namespace, name = DecomposeQualifiedName(infos["elmt_type"]) |
|
596 infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
597 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1: |
|
598 if isinstance(value["value"], ListType) and \ |
|
599 infos["minOccurs"] <= len(value["value"]) <= infos["maxOccurs"]: |
|
600 return reduce(lambda x, y: x and y, |
|
601 map(infos["elmt_type"]["check"], |
|
602 value["value"]), |
|
603 True) |
|
604 else: |
|
605 return infos["elmt_type"]["check"](value["value"]) |
|
606 return False |
|
607 |
|
608 def ExtractContent(tree, content): |
748 def ExtractContent(tree, content): |
609 for content_name, infos in choices: |
749 infos = choices_dict.get(tree.nodeName, None) |
610 if content_name == tree.nodeName: |
750 if infos is not None: |
611 if isinstance(infos["elmt_type"], (UnicodeType, StringType)): |
751 if infos["name"] == "sequence": |
612 namespace, name = DecomposeQualifiedName(infos["elmt_type"]) |
752 sequence_dict = dict([(element_infos["name"], element_infos) for element_infos in infos["elements"] if element_infos["type"] != CHOICE]) |
613 infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
753 element_infos = sequence_dict.get(tree.nodeName) |
614 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1: |
754 if content is not None and \ |
615 if isinstance(content, ListType) and len(content) > 0 and \ |
755 content["name"] == "sequence" and \ |
616 content[-1]["name"] == content_name: |
756 len(content["value"]) > 0 and \ |
617 content_item = content.pop(-1) |
757 choices_dict.get(content["value"][-1]["name"]) == infos: |
618 content_item["value"].append(infos["elmt_type"]["extract"](tree)) |
758 return {"name": "sequence", |
619 return content_item |
759 "value": content["value"] + [ExtractContentElement(factory, tree, element_infos, content["value"][-1])]} |
620 elif not isinstance(content, ListType) and \ |
760 else: |
621 content is not None and \ |
761 return {"name": "sequence", |
622 content["name"] == content_name: |
762 "value": [ExtractContentElement(factory, tree, element_infos, None)]} |
623 return {"name": content_name, |
763 else: |
624 "value": content["value"] + \ |
764 return ExtractContentElement(factory, tree, infos, content) |
625 [infos["elmt_type"]["extract"](tree)]} |
765 else: |
626 else: |
766 for choice_name, infos in choices: |
627 return {"name": content_name, |
767 if infos["type"] == "sequence": |
628 "value": [infos["elmt_type"]["extract"](tree)]} |
768 for element_infos in infos["elements"]: |
629 else: |
769 if element_infos["type"] == CHOICE: |
630 return {"name": content_name, |
770 try: |
631 "value": infos["elmt_type"]["extract"](tree)} |
771 if content is not None and \ |
772 content["name"] == "sequence" and \ |
|
773 len(content["value"]) > 0: |
|
774 return {"name": "sequence", |
|
775 "value": content["value"] + [element_infos["elmt_type"]["extract"](tree, content["value"][-1])]} |
|
776 else: |
|
777 return {"name": "sequence", |
|
778 "value": [element_infos["elmt_type"]["extract"](tree, None)]} |
|
779 except: |
|
780 pass |
|
632 raise ValueError("Invalid element \"%s\" for content!" % tree.nodeName) |
781 raise ValueError("Invalid element \"%s\" for content!" % tree.nodeName) |
633 |
782 |
634 def GenerateContent(value, name=None, indent=0): |
783 def GenerateContent(value, name=None, indent=0): |
635 for content_name, infos in choices: |
784 text = "" |
636 if content_name == value["name"]: |
785 if value["name"] != "sequence": |
637 if isinstance(infos["elmt_type"], (UnicodeType, StringType)): |
786 infos = choices_dict.get(value["name"], None) |
638 namespace, name = DecomposeQualifiedName(infos["elmt_type"]) |
787 if infos is not None: |
639 infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
788 infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
640 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1: |
789 if infos["maxOccurs"] == "unbounded" or infos["maxOccurs"] > 1: |
641 text = "" |
|
642 for item in value["value"]: |
790 for item in value["value"]: |
643 text += infos["elmt_type"]["generate"](item, content_name, indent) |
791 text += infos["elmt_type"]["generate"](item, value["name"], indent) |
644 return text |
792 else: |
645 else: |
793 text += infos["elmt_type"]["generate"](value["value"], value["name"], indent) |
646 return infos["elmt_type"]["generate"](value["value"], content_name, indent) |
794 elif len(value["value"]) > 0: |
647 return "" |
795 infos = choices_dict.get(value["value"][0]["name"], None) |
796 if infos is None: |
|
797 for choice_name, infos in choices: |
|
798 if infos["type"] == "sequence": |
|
799 for element_infos in infos["elements"]: |
|
800 if element_infos["type"] == CHOICE: |
|
801 infos = GetContentInfos(value["value"][0]["name"], element_infos["choices"]) |
|
802 if infos is not None: |
|
803 sequence_dict = dict([(element_infos["name"], element_infos) for element_infos in infos["elements"]]) |
|
804 for element_value in value["value"]: |
|
805 element_infos = sequence_dict.get(element_value["name"]) |
|
806 if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1: |
|
807 for item in element_value["value"]: |
|
808 text += element_infos["elmt_type"]["generate"](item, element_value["name"], indent) |
|
809 else: |
|
810 text += element_infos["elmt_type"]["generate"](element_value["value"], element_infos["name"], indent) |
|
811 return text |
|
648 |
812 |
649 return { |
813 return { |
814 "type": COMPLEXTYPE, |
|
650 "initial": GetContentInitial, |
815 "initial": GetContentInitial, |
651 "check": CheckContent, |
816 "check": CheckContent, |
652 "extract": ExtractContent, |
817 "extract": ExtractContent, |
653 "generate": GenerateContent |
818 "generate": GenerateContent |
654 } |
819 } |
705 """ |
870 """ |
706 Class that generate class from an XML Tree |
871 Class that generate class from an XML Tree |
707 """ |
872 """ |
708 class ClassFactory: |
873 class ClassFactory: |
709 |
874 |
710 def __init__(self, document, debug=False): |
875 def __init__(self, document, filepath=None, debug=False): |
711 self.Document = document |
876 self.Document = document |
877 if filepath is not None: |
|
878 self.BaseFolder, self.FileName = os.path.split(filepath) |
|
879 else: |
|
880 self.BaseFolder = self.FileName = None |
|
712 self.Debug = debug |
881 self.Debug = debug |
713 |
882 |
714 # Dictionary for stocking Classes and Types definitions created from |
883 # Dictionary for stocking Classes and Types definitions created from |
715 # the XML tree |
884 # the XML tree |
716 self.XMLClassDefinitions = {} |
885 self.XMLClassDefinitions = {} |
722 |
891 |
723 self.CurrentCompilations = [] |
892 self.CurrentCompilations = [] |
724 |
893 |
725 # Dictionaries for stocking Classes and Types generated |
894 # Dictionaries for stocking Classes and Types generated |
726 self.ComputeAfter = [] |
895 self.ComputeAfter = [] |
727 self.ComputedClasses = {} |
896 if self.FileName is not None: |
897 self.ComputedClasses = {self.FileName: {}} |
|
898 else: |
|
899 self.ComputedClasses = {} |
|
728 self.ComputedClassesInfos = {} |
900 self.ComputedClassesInfos = {} |
729 self.AlreadyComputed = {} |
901 self.AlreadyComputed = {} |
730 |
902 |
731 def GetQualifiedNameInfos(self, name, namespace=None, canbenone=False): |
903 def GetQualifiedNameInfos(self, name, namespace=None, canbenone=False): |
732 if namespace is None: |
904 if namespace is None: |
733 if self.Namespaces[self.SchemaNamespace].has_key(name): |
905 if self.Namespaces[self.SchemaNamespace].has_key(name): |
734 return self.Namespaces[self.SchemaNamespace][name] |
906 return self.Namespaces[self.SchemaNamespace][name] |
735 for space, elements in self.Namespaces.items(): |
907 for space, elements in self.Namespaces.iteritems(): |
736 if space != self.SchemaNamespace and elements.has_key(name): |
908 if space != self.SchemaNamespace and elements.has_key(name): |
737 return elements[name] |
909 return elements[name] |
738 parts = name.split("_", 1) |
910 parts = name.split("_", 1) |
739 if len(parts) > 1: |
911 if len(parts) > 1: |
740 group = self.GetQualifiedNameInfos(parts[0], namespace) |
912 group = self.GetQualifiedNameInfos(parts[0], namespace) |
844 return attrs |
1016 return attrs |
845 |
1017 |
846 def ReduceElements(self, elements, schema=False): |
1018 def ReduceElements(self, elements, schema=False): |
847 result = [] |
1019 result = [] |
848 for child_infos in elements: |
1020 for child_infos in elements: |
849 if child_infos[1].has_key("name") and schema: |
1021 if child_infos is not None: |
850 self.CurrentCompilations.append(child_infos[1]["name"]) |
1022 if child_infos[1].has_key("name") and schema: |
851 namespace, name = DecomposeQualifiedName(child_infos[0]) |
1023 self.CurrentCompilations.append(child_infos[1]["name"]) |
852 infos = self.GetQualifiedNameInfos(name, namespace) |
1024 namespace, name = DecomposeQualifiedName(child_infos[0]) |
853 if infos["type"] != SYNTAXELEMENT: |
1025 infos = self.GetQualifiedNameInfos(name, namespace) |
854 raise ValueError("\"%s\" can't be a member child!" % name) |
1026 if infos["type"] != SYNTAXELEMENT: |
855 result.append(infos["reduce"](self, child_infos[1], child_infos[2])) |
1027 raise ValueError("\"%s\" can't be a member child!" % name) |
856 if child_infos[1].has_key("name") and schema: |
1028 element = infos["reduce"](self, child_infos[1], child_infos[2]) |
857 self.CurrentCompilations.pop(-1) |
1029 if element is not None: |
1030 result.append(element) |
|
1031 if child_infos[1].has_key("name") and schema: |
|
1032 self.CurrentCompilations.pop(-1) |
|
858 annotations = [] |
1033 annotations = [] |
859 children = [] |
1034 children = [] |
860 for element in result: |
1035 for element in result: |
861 if element["type"] == "annotation": |
1036 if element["type"] == "annotation": |
862 annotations.append(element) |
1037 annotations.append(element) |
946 self.AlreadyComputed[classname].IsBaseClass = baseclass |
1121 self.AlreadyComputed[classname].IsBaseClass = baseclass |
947 return self.ComputedClassesInfos.get(classname, None) |
1122 return self.ComputedClassesInfos.get(classname, None) |
948 |
1123 |
949 # If base classes haven't been generated |
1124 # If base classes haven't been generated |
950 bases = [] |
1125 bases = [] |
951 if classinfos.has_key("base"): |
1126 base_infos = classinfos.get("base", None) |
952 result = self.ExtractTypeInfos("base", name, classinfos["base"]) |
1127 if base_infos is not None: |
1128 result = self.ExtractTypeInfos("base", name, base_infos) |
|
953 if result is None: |
1129 if result is None: |
954 namespace, base_name = DecomposeQualifiedName(classinfos["base"]) |
1130 namespace, base_name = DecomposeQualifiedName(base_infos) |
955 if self.AlreadyComputed.get(base_name, False): |
1131 if self.AlreadyComputed.get(base_name, False): |
956 self.ComputeAfter.append((name, parent, classinfos)) |
1132 self.ComputeAfter.append((name, parent, classinfos)) |
957 if self.TargetNamespace is not None: |
1133 if self.TargetNamespace is not None: |
958 return "%s:%s" % (self.TargetNamespace, classname) |
1134 return "%s:%s" % (self.TargetNamespace, classname) |
959 else: |
1135 else: |
960 return classname |
1136 return classname |
961 elif result is not None: |
1137 elif result is not None: |
962 classinfos["base"] = self.ComputedClasses[result["name"]] |
1138 if self.FileName is not None: |
963 bases.append(self.ComputedClasses[result["name"]]) |
1139 classinfos["base"] = self.ComputedClasses[self.FileName].get(result["name"], None) |
1140 if classinfos["base"] is None: |
|
1141 for filename, classes in self.ComputedClasses.iteritems(): |
|
1142 if filename != self.FileName: |
|
1143 classinfos["base"] = classes.get(result["name"], None) |
|
1144 if classinfos["base"] is not None: |
|
1145 break |
|
1146 else: |
|
1147 classinfos["base"] = self.ComputedClasses.get(result["name"], None) |
|
1148 if classinfos["base"] is None: |
|
1149 raise ValueError("No class found for base type") |
|
1150 bases.append(classinfos["base"]) |
|
964 bases.append(object) |
1151 bases.append(object) |
965 bases = tuple(bases) |
1152 bases = tuple(bases) |
966 classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass} |
1153 classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass} |
967 |
1154 |
968 self.AlreadyComputed[classname] = True |
1155 self.AlreadyComputed[classname] = True |
982 classmembers["set%s"%attrname] = generateSetMethod(attrname) |
1169 classmembers["set%s"%attrname] = generateSetMethod(attrname) |
983 classmembers["get%s"%attrname] = generateGetMethod(attrname) |
1170 classmembers["get%s"%attrname] = generateGetMethod(attrname) |
984 else: |
1171 else: |
985 raise ValueError("\"%s\" type unrecognized!" % attribute["attr_type"]) |
1172 raise ValueError("\"%s\" type unrecognized!" % attribute["attr_type"]) |
986 attribute["attr_type"] = infos |
1173 attribute["attr_type"] = infos |
987 |
1174 |
988 for element in classinfos["elements"]: |
1175 for element in classinfos["elements"]: |
989 if element["type"] == CHOICE: |
1176 if element["type"] == CHOICE: |
990 elmtname = element["name"] |
1177 elmtname = element["name"] |
991 choices = [] |
1178 choices = ComputeContentChoices(self, name, element) |
992 for choice in element["choices"]: |
|
993 if choice["elmt_type"] == "tag": |
|
994 choice["elmt_type"] = GenerateTagInfos(choice["name"]) |
|
995 else: |
|
996 infos = self.ExtractTypeInfos(choice["name"], name, choice["elmt_type"]) |
|
997 if infos is not None: |
|
998 choice["elmt_type"] = infos |
|
999 choices.append((choice["name"], choice)) |
|
1000 classmembers["get%schoices"%elmtname] = generateGetChoicesMethod(element["choices"]) |
1179 classmembers["get%schoices"%elmtname] = generateGetChoicesMethod(element["choices"]) |
1001 if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1: |
1180 if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1: |
1002 classmembers["append%sbytype" % elmtname] = generateAppendChoiceByTypeMethod(element["maxOccurs"], self, element["choices"]) |
1181 classmembers["append%sbytype" % elmtname] = generateAppendChoiceByTypeMethod(element["maxOccurs"], self, element["choices"]) |
1003 classmembers["insert%sbytype" % elmtname] = generateInsertChoiceByTypeMethod(element["maxOccurs"], self, element["choices"]) |
1182 classmembers["insert%sbytype" % elmtname] = generateInsertChoiceByTypeMethod(element["maxOccurs"], self, element["choices"]) |
1004 else: |
1183 else: |
1005 classmembers["set%sbytype" % elmtname] = generateSetChoiceByTypeMethod(self, element["choices"]) |
1184 classmembers["set%sbytype" % elmtname] = generateSetChoiceByTypeMethod(self, element["choices"]) |
1006 infos = GenerateContentInfos(self, choices) |
1185 infos = GenerateContentInfos(self, name, choices) |
1007 elif element["type"] == ANY: |
1186 elif element["type"] == ANY: |
1008 elmtname = element["name"] = "text" |
1187 elmtname = element["name"] = "text" |
1009 element["minOccurs"] = element["maxOccurs"] = 1 |
1188 element["minOccurs"] = element["maxOccurs"] = 1 |
1010 infos = GenerateAnyInfos() |
1189 infos = GenerateAnyInfos(element) |
1011 else: |
1190 else: |
1012 elmtname = element["name"] |
1191 elmtname = element["name"] |
1013 infos = self.ExtractTypeInfos(element["name"], name, element["elmt_type"]) |
1192 infos = self.ExtractTypeInfos(element["name"], name, element["elmt_type"]) |
1014 if infos is not None: |
1193 if infos is not None: |
1015 element["elmt_type"] = infos |
1194 element["elmt_type"] = infos |
1048 "check": generateClassCheckFunction(class_definition), |
1227 "check": generateClassCheckFunction(class_definition), |
1049 "initial": generateClassCreateFunction(class_definition), |
1228 "initial": generateClassCreateFunction(class_definition), |
1050 "extract": generateClassExtractFunction(class_definition), |
1229 "extract": generateClassExtractFunction(class_definition), |
1051 "generate": class_definition.generateXMLText} |
1230 "generate": class_definition.generateXMLText} |
1052 |
1231 |
1053 self.ComputedClasses[classname] = class_definition |
1232 if self.FileName is not None: |
1233 self.ComputedClasses[self.FileName][classname] = class_definition |
|
1234 else: |
|
1235 self.ComputedClasses[classname] = class_definition |
|
1054 self.ComputedClassesInfos[classname] = class_infos |
1236 self.ComputedClassesInfos[classname] = class_infos |
1055 |
1237 |
1056 return class_infos |
1238 return class_infos |
1057 |
1239 |
1058 """ |
1240 """ |
1059 Methods that print the classes generated |
1241 Methods that print the classes generated |
1060 """ |
1242 """ |
1061 def PrintClasses(self): |
1243 def PrintClasses(self): |
1062 items = self.ComputedClasses.items() |
1244 items = self.ComputedClasses.items() |
1063 items.sort() |
1245 items.sort() |
1064 for classname, xmlclass in items: |
1246 if self.FileName is not None: |
1065 print "%s : %s" % (classname, str(xmlclass)) |
1247 for filename, classes in items: |
1248 print "File '%s':" % filename |
|
1249 class_items = classes.items() |
|
1250 class_items.sort() |
|
1251 for classname, xmlclass in class_items: |
|
1252 print "%s: %s" % (classname, str(xmlclass)) |
|
1253 else: |
|
1254 for classname, xmlclass in items: |
|
1255 print "%s: %s" % (classname, str(xmlclass)) |
|
1066 |
1256 |
1067 def PrintClassNames(self): |
1257 def PrintClassNames(self): |
1068 classnames = self.XMLClassDefinitions.keys() |
1258 classnames = self.XMLClassDefinitions.keys() |
1069 classnames.sort() |
1259 classnames.sort() |
1070 for classname in classnames: |
1260 for classname in classnames: |
1105 optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"]) |
1295 optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"]) |
1106 elements = dict([(element["name"], element) for element in classinfos["elements"]]) |
1296 elements = dict([(element["name"], element) for element in classinfos["elements"]]) |
1107 |
1297 |
1108 def setattrMethod(self, name, value): |
1298 def setattrMethod(self, name, value): |
1109 if attributes.has_key(name): |
1299 if attributes.has_key(name): |
1110 if isinstance(attributes[name]["attr_type"], (UnicodeType, StringType)): |
1300 attributes[name]["attr_type"] = FindTypeInfos(factory, attributes[name]["attr_type"]) |
1111 namespace, name = DecomposeQualifiedName(infos) |
|
1112 attributes[name]["attr_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1113 if value is None: |
1301 if value is None: |
1114 if optional_attributes.get(name, False): |
1302 if optional_attributes.get(name, False): |
1115 return object.__setattr__(self, name, None) |
1303 return object.__setattr__(self, name, None) |
1116 else: |
1304 else: |
1117 raise ValueError("Attribute '%s' isn't optional." % name) |
1305 raise ValueError("Attribute '%s' isn't optional." % name) |
1120 elif attributes[name]["attr_type"]["check"](value): |
1308 elif attributes[name]["attr_type"]["check"](value): |
1121 return object.__setattr__(self, name, value) |
1309 return object.__setattr__(self, name, value) |
1122 else: |
1310 else: |
1123 raise ValueError("Invalid value for attribute '%s'." % (name)) |
1311 raise ValueError("Invalid value for attribute '%s'." % (name)) |
1124 elif elements.has_key(name): |
1312 elif elements.has_key(name): |
1125 if isinstance(elements[name]["elmt_type"], (UnicodeType, StringType)): |
1313 if CheckElementValue(factory, name, elements[name], value): |
1126 namespace, name = DecomposeQualifiedName(infos) |
|
1127 elements[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1128 if value is None: |
|
1129 if elements[name]["minOccurs"] == 0 and elements[name]["maxOccurs"] == 1: |
|
1130 return object.__setattr__(self, name, None) |
|
1131 else: |
|
1132 raise ValueError("Attribute '%s' isn't optional." % name) |
|
1133 elif elements[name]["maxOccurs"] == "unbounded" or elements[name]["maxOccurs"] > 1: |
|
1134 if isinstance(value, ListType) and elements[name]["minOccurs"] <= len(value) <= elements[name]["maxOccurs"]: |
|
1135 if reduce(lambda x, y: x and y, map(elements[name]["elmt_type"]["check"], value), True): |
|
1136 return object.__setattr__(self, name, value) |
|
1137 raise ValueError, "Attribute '%s' must be a list of valid elements."%name |
|
1138 elif elements[name].has_key("fixed") and value != elements[name]["fixed"]: |
|
1139 raise ValueError("Value of attribute '%s' can only be '%s'." % (name, str(elements[name]["fixed"]))) |
|
1140 elif elements[name]["elmt_type"]["check"](value): |
|
1141 return object.__setattr__(self, name, value) |
1314 return object.__setattr__(self, name, value) |
1142 else: |
1315 else: |
1143 raise ValueError("Invalid value for attribute '%s'." % (name)) |
1316 raise ValueError("Invalid value for attribute '%s'." % (name)) |
1144 elif classinfos.has_key("base"): |
1317 elif classinfos.has_key("base"): |
1145 return classinfos["base"].__setattr__(self, name, value) |
1318 return classinfos["base"].__setattr__(self, name, value) |
1164 return "(?:%s){,%d}" % (name, infos["maxOccurs"]) |
1337 return "(?:%s){,%d}" % (name, infos["maxOccurs"]) |
1165 elif infos["minOccurs"] == 1: |
1338 elif infos["minOccurs"] == 1: |
1166 if infos["maxOccurs"] == "unbounded": |
1339 if infos["maxOccurs"] == "unbounded": |
1167 return "(?:%s)+" % name |
1340 return "(?:%s)+" % name |
1168 elif infos["maxOccurs"] == 1: |
1341 elif infos["maxOccurs"] == 1: |
1169 return name |
1342 return "(?:%s)" % name |
1170 else: |
1343 else: |
1171 return "(?:%s){1,%d}" % (name, infos["maxOccurs"]) |
1344 return "(?:%s){1,%d}" % (name, infos["maxOccurs"]) |
1172 else: |
1345 else: |
1173 if infos["maxOccurs"] == "unbounded": |
1346 if infos["maxOccurs"] == "unbounded": |
1174 return "(?:%s){%d,}" % (name, infos["minOccurs"], name) |
1347 return "(?:%s){%d,}" % (name, infos["minOccurs"], name) |
1175 else: |
1348 else: |
1176 return "(?:%s){%d,%d}" % (name, infos["minOccurs"], |
1349 return "(?:%s){%d,%d}" % (name, infos["minOccurs"], |
1177 infos["maxOccurs"]) |
1350 infos["maxOccurs"]) |
1178 |
1351 |
1179 def generateStructureMethod(classinfos): |
1352 def GetStructure(classinfos): |
1180 elements = [] |
1353 elements = [] |
1181 for element in classinfos["elements"]: |
1354 for element in classinfos["elements"]: |
1182 if element["type"] == ANY: |
1355 if element["type"] == ANY: |
1183 elements.append(ComputeMultiplicity("(?:#cdata-section )?", element)) |
1356 elements.append(ComputeMultiplicity("#cdata-section |\w* ", element)) |
1184 elif element["type"] == CHOICE: |
1357 elif element["type"] == CHOICE: |
1185 elements.append(ComputeMultiplicity( |
1358 choices = [] |
1186 "|".join([ComputeMultiplicity("%s " % infos["name"], infos) for infos in element["choices"]]), |
1359 for infos in element["choices"]: |
1187 element)) |
1360 if infos["type"] == "sequence": |
1361 structure = "(?:%s)" % GetStructure(infos) |
|
1362 else: |
|
1363 structure = "%s " % infos["name"] |
|
1364 choices.append(ComputeMultiplicity(structure, infos)) |
|
1365 elements.append(ComputeMultiplicity("|".join(choices), element)) |
|
1366 elif element["name"] == "content" and element["elmt_type"]["type"] == SIMPLETYPE: |
|
1367 elements.append("(?:#cdata-section )?") |
|
1188 else: |
1368 else: |
1189 elements.append(ComputeMultiplicity("%s " % element["name"], element)) |
1369 elements.append(ComputeMultiplicity("%s " % element["name"], element)) |
1190 if classinfos.get("order", True) or len(elements) == 0: |
1370 if classinfos.get("order", True) or len(elements) == 0: |
1191 structure = "".join(elements) |
1371 return "".join(elements) |
1192 else: |
1372 else: |
1193 raise ValueError("XSD structure not yet supported!") |
1373 raise ValueError("XSD structure not yet supported!") |
1194 |
1374 |
1375 def generateStructureMethod(classinfos): |
|
1195 def getStructureMethod(self): |
1376 def getStructureMethod(self): |
1377 structure = GetStructure(classinfos) |
|
1196 if classinfos.has_key("base"): |
1378 if classinfos.has_key("base"): |
1197 return classinfos["base"].getStructure(self) + structure |
1379 return classinfos["base"].getStructure(self) + structure |
1198 return structure |
1380 return structure |
1199 return getStructureMethod |
1381 return getStructureMethod |
1200 |
1382 |
1211 if not derived: |
1393 if not derived: |
1212 children_structure = "" |
1394 children_structure = "" |
1213 for node in tree.childNodes: |
1395 for node in tree.childNodes: |
1214 if node.nodeName not in ["#comment", "#text"]: |
1396 if node.nodeName not in ["#comment", "#text"]: |
1215 children_structure += "%s " % node.nodeName |
1397 children_structure += "%s " % node.nodeName |
1216 structure_model = re.compile("(%s)$" % self.getStructure()) |
1398 structure_pattern = self.getStructure() |
1217 result = structure_model.match(children_structure) |
1399 if structure_pattern != "": |
1218 if not result: |
1400 structure_model = re.compile("(%s)$" % structure_pattern) |
1219 raise ValueError("Invalid structure for \"%s\" children!." % tree.nodeName) |
1401 result = structure_model.match(children_structure) |
1402 if not result: |
|
1403 raise ValueError("Invalid structure for \"%s\" children!." % tree.nodeName) |
|
1220 required_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "required"]) |
1404 required_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "required"]) |
1221 if classinfos.has_key("base"): |
1405 if classinfos.has_key("base"): |
1222 extras.extend([attr["name"] for attr in classinfos["attributes"] if attr["use"] != "prohibited"]) |
1406 extras.extend([attr["name"] for attr in classinfos["attributes"] if attr["use"] != "prohibited"]) |
1223 classinfos["base"].loadXMLTree(self, tree, extras, True) |
1407 classinfos["base"].loadXMLTree(self, tree, extras, True) |
1224 for attrname, attr in tree._attrs.iteritems(): |
1408 for attrname, attr in tree._attrs.iteritems(): |
1225 if attributes.has_key(attrname): |
1409 if attributes.has_key(attrname): |
1226 if isinstance(attributes[attrname]["attr_type"], (UnicodeType, StringType)): |
1410 attributes[attrname]["attr_type"] = FindTypeInfos(factory, attributes[attrname]["attr_type"]) |
1227 namespace, name = DecomposeQualifiedName(infos) |
1411 object.__setattr__(self, attrname, attributes[attrname]["attr_type"]["extract"](attr)) |
1228 attributes[attrname]["attr_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1229 setattr(self, attrname, attributes[attrname]["attr_type"]["extract"](attr)) |
|
1230 elif not classinfos.has_key("base") and attrname not in extras: |
1412 elif not classinfos.has_key("base") and attrname not in extras: |
1231 raise ValueError("Invalid attribute \"%s\" for \"%s\" element!" % (attrname, tree.nodeName)) |
1413 raise ValueError("Invalid attribute \"%s\" for \"%s\" element!" % (attrname, tree.nodeName)) |
1232 required_attributes.pop(attrname, None) |
1414 required_attributes.pop(attrname, None) |
1233 if len(required_attributes) > 0: |
1415 if len(required_attributes) > 0: |
1234 raise ValueError("Required attributes %s missing for \"%s\" element!" % (", ".join(["\"%s\""%name for name in required_attributes]), tree.nodeName)) |
1416 raise ValueError("Required attributes %s missing for \"%s\" element!" % (", ".join(["\"%s\""%name for name in required_attributes]), tree.nodeName)) |
1235 first = {} |
1417 first = {} |
1236 for node in tree.childNodes: |
1418 for node in tree.childNodes: |
1237 name = node.nodeName |
1419 name = node.nodeName |
1238 if name in ["#text", "#comment"]: |
1420 if name in ["#text", "#comment"]: |
1239 continue |
1421 continue |
1240 if elements.has_key(name): |
1422 elif elements.has_key(name): |
1241 if isinstance(elements[name]["elmt_type"], (UnicodeType, StringType)): |
1423 elements[name]["elmt_type"] = FindTypeInfos(factory, elements[name]["elmt_type"]) |
1242 namespace, name = DecomposeQualifiedName(infos) |
|
1243 elements[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1244 if elements[name]["maxOccurs"] == "unbounded" or elements[name]["maxOccurs"] > 1: |
1424 if elements[name]["maxOccurs"] == "unbounded" or elements[name]["maxOccurs"] > 1: |
1245 if first.get(name, True): |
1425 if first.get(name, True): |
1246 setattr(self, name, [elements[name]["elmt_type"]["extract"](node)]) |
1426 object.__setattr__(self, name, [elements[name]["elmt_type"]["extract"](node)]) |
1247 first[name] = False |
1427 first[name] = False |
1248 else: |
1428 else: |
1249 getattr(self, name).append(elements[name]["elmt_type"]["extract"](node)) |
1429 getattr(self, name).append(elements[name]["elmt_type"]["extract"](node)) |
1250 else: |
1430 else: |
1251 setattr(self, name, elements[name]["elmt_type"]["extract"](node)) |
1431 object.__setattr__(self, name, elements[name]["elmt_type"]["extract"](node)) |
1252 elif name == "#cdata-section" and elements.has_key("text"): |
1432 elif elements.has_key("text"): |
1253 if elements["text"]["maxOccurs"] == "unbounded" or elements["text"]["maxOccurs"] > 1: |
1433 if elements["text"]["maxOccurs"] == "unbounded" or elements["text"]["maxOccurs"] > 1: |
1254 if first.get("text", True): |
1434 if first.get("text", True): |
1255 setattr(self, "text", [elements["text"]["elmt_type"]["extract"](node)]) |
1435 object.__setattr__(self, "text", [elements["text"]["elmt_type"]["extract"](node)]) |
1256 first["text"] = False |
1436 first["text"] = False |
1257 else: |
1437 else: |
1258 getattr(self, "text").append(elements["text"]["elmt_type"]["extract"](node)) |
1438 getattr(self, "text").append(elements["text"]["elmt_type"]["extract"](node)) |
1259 else: |
1439 else: |
1260 setattr(self, "text", elements["text"]["elmt_type"]["extract"](node)) |
1440 object.__setattr__(self, "text", elements["text"]["elmt_type"]["extract"](node)) |
1261 elif elements.has_key("content"): |
1441 elif elements.has_key("content"): |
1262 content = getattr(self, "content") |
1442 if name == "#cdata-section": |
1263 if elements["content"]["maxOccurs"] == "unbounded" or elements["content"]["maxOccurs"] > 1: |
1443 if elements["content"]["elmt_type"]["type"] == SIMPLETYPE: |
1264 if first.get("content", True): |
1444 object.__setattr__(self, "content", elements["content"]["elmt_type"]["extract"](node.data, False)) |
1265 setattr(self, "content", [elements["content"]["elmt_type"]["extract"](node, None)]) |
1445 else: |
1266 first["content"] = False |
1446 content = getattr(self, "content") |
1447 if elements["content"]["maxOccurs"] == "unbounded" or elements["content"]["maxOccurs"] > 1: |
|
1448 if first.get("content", True): |
|
1449 object.__setattr__(self, "content", [elements["content"]["elmt_type"]["extract"](node, None)]) |
|
1450 first["content"] = False |
|
1451 else: |
|
1452 content.append(elements["content"]["elmt_type"]["extract"](node, content)) |
|
1267 else: |
1453 else: |
1268 content.append(elements["content"]["elmt_type"]["extract"](node, content)) |
1454 object.__setattr__(self, "content", elements["content"]["elmt_type"]["extract"](node, content)) |
1269 else: |
|
1270 setattr(self, "content", elements["content"]["elmt_type"]["extract"](node, content)) |
|
1271 return loadXMLTreeMethod |
1455 return loadXMLTreeMethod |
1272 |
1456 |
1273 |
1457 |
1274 """ |
1458 """ |
1275 Method that generates the method for generating an xml text by following the |
1459 Method that generates the method for generating an xml text by following the |
1291 text += u' %s=%s' % (attr, quoteattr(value)) |
1475 text += u' %s=%s' % (attr, quoteattr(value)) |
1292 first = False |
1476 first = False |
1293 extras.clear() |
1477 extras.clear() |
1294 for attr in classinfos["attributes"]: |
1478 for attr in classinfos["attributes"]: |
1295 if attr["use"] != "prohibited": |
1479 if attr["use"] != "prohibited": |
1296 if isinstance(attr["attr_type"], (UnicodeType, StringType)): |
1480 attr["attr_type"] = FindTypeInfos(factory, attr["attr_type"]) |
1297 namespace, name = DecomposeQualifiedName(infos) |
|
1298 attr["attr_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1299 value = getattr(self, attr["name"], None) |
1481 value = getattr(self, attr["name"], None) |
1300 if value != None: |
1482 if value != None: |
1301 computed_value = attr["attr_type"]["generate"](value) |
1483 computed_value = attr["attr_type"]["generate"](value) |
1302 else: |
1484 else: |
1303 computed_value = None |
1485 computed_value = None |
1314 first, new_text = classinfos["base"].generateXMLText(self, name, indent, extras, True) |
1496 first, new_text = classinfos["base"].generateXMLText(self, name, indent, extras, True) |
1315 text += new_text |
1497 text += new_text |
1316 else: |
1498 else: |
1317 first = True |
1499 first = True |
1318 for element in classinfos["elements"]: |
1500 for element in classinfos["elements"]: |
1319 if isinstance(element["elmt_type"], (UnicodeType, StringType)): |
1501 element["elmt_type"] = FindTypeInfos(factory, element["elmt_type"]) |
1320 namespace, name = DecomposeQualifiedName(infos) |
|
1321 element["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1322 value = getattr(self, element["name"], None) |
1502 value = getattr(self, element["name"], None) |
1323 if element["minOccurs"] == 0 and element["maxOccurs"] == 1: |
1503 if element["minOccurs"] == 0 and element["maxOccurs"] == 1: |
1324 if value is not None: |
1504 if value is not None: |
1325 if first: |
1505 if first: |
1326 text += u'>\n' |
1506 text += u'>\n' |
1328 text += element["elmt_type"]["generate"](value, element["name"], indent + 1) |
1508 text += element["elmt_type"]["generate"](value, element["name"], indent + 1) |
1329 elif element["minOccurs"] == 1 and element["maxOccurs"] == 1: |
1509 elif element["minOccurs"] == 1 and element["maxOccurs"] == 1: |
1330 if first: |
1510 if first: |
1331 text += u'>\n' |
1511 text += u'>\n' |
1332 first = False |
1512 first = False |
1333 text += element["elmt_type"]["generate"](value, element["name"], indent + 1) |
1513 if element["name"] == "content" and element["elmt_type"]["type"] == SIMPLETYPE: |
1514 text += element["elmt_type"]["generate"](value) |
|
1515 else: |
|
1516 text += element["elmt_type"]["generate"](value, element["name"], indent + 1) |
|
1334 else: |
1517 else: |
1335 if first and len(value) > 0: |
1518 if first and len(value) > 0: |
1336 text += u'>\n' |
1519 text += u'>\n' |
1337 first = False |
1520 first = False |
1338 for item in value: |
1521 for item in value: |
1420 if classinfos.has_key("base"): |
1603 if classinfos.has_key("base"): |
1421 children.extend(classinfos["base"].getElementInfos(self, name, derived=True)["children"]) |
1604 children.extend(classinfos["base"].getElementInfos(self, name, derived=True)["children"]) |
1422 for element_name, element in elements.items(): |
1605 for element_name, element in elements.items(): |
1423 if element["minOccurs"] == 0: |
1606 if element["minOccurs"] == 0: |
1424 use = "optional" |
1607 use = "optional" |
1425 if element_name == "content": |
1608 if element_name == "content" and element["type"] == CHOICE: |
1426 attr_type = [(choice["name"], None) for choice in element["choices"]] |
1609 attr_type = [(choice["name"], None) for choice in element["choices"]] |
1427 if self.content is None: |
1610 if self.content is None: |
1428 value = "" |
1611 value = "" |
1429 else: |
1612 else: |
1430 value = self.content["name"] |
1613 value = self.content["name"] |
1431 if self.content["value"] is not None: |
1614 if self.content["value"] is not None: |
1432 children.extend(self.content["value"].getElementInfos(self.content["name"])["children"]) |
1615 if self.content["name"] == "sequence": |
1616 choices_dict = dict([(choice["name"], choice) for choice in element["choices"]]) |
|
1617 sequence_infos = choices_dict.get("sequence", None) |
|
1618 if sequence_infos is not None: |
|
1619 children.extend([item.getElementInfos(infos["name"]) for item, infos in zip(self.content["value"], sequence_infos["elements"])]) |
|
1620 else: |
|
1621 children.extend(self.content["value"].getElementInfos(self.content["name"])["children"]) |
|
1433 elif element["elmt_type"]["type"] == SIMPLETYPE: |
1622 elif element["elmt_type"]["type"] == SIMPLETYPE: |
1434 children.append({"name": element_name, "require": element["minOccurs"] != 0, |
1623 children.append({"name": element_name, "require": element["minOccurs"] != 0, |
1435 "type": gettypeinfos(element["elmt_type"]["basename"], |
1624 "type": gettypeinfos(element["elmt_type"]["basename"], |
1436 element["elmt_type"]["facets"]), |
1625 element["elmt_type"]["facets"]), |
1437 "value": getattr(self, element_name, None)}) |
1626 "value": getattr(self, element_name, None)}) |
1493 def generateInitMethod(factory, classinfos): |
1682 def generateInitMethod(factory, classinfos): |
1494 def initMethod(self): |
1683 def initMethod(self): |
1495 if classinfos.has_key("base"): |
1684 if classinfos.has_key("base"): |
1496 classinfos["base"].__init__(self) |
1685 classinfos["base"].__init__(self) |
1497 for attribute in classinfos["attributes"]: |
1686 for attribute in classinfos["attributes"]: |
1498 if isinstance(attribute["attr_type"], (UnicodeType, StringType)): |
1687 attribute["attr_type"] = FindTypeInfos(factory, attribute["attr_type"]) |
1499 namespace, name = DecomposeQualifiedName(attribute["attr_type"]) |
|
1500 attribute["attr_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1501 if attribute["use"] == "required": |
1688 if attribute["use"] == "required": |
1502 setattr(self, attribute["name"], attribute["attr_type"]["initial"]()) |
1689 setattr(self, attribute["name"], attribute["attr_type"]["initial"]()) |
1503 elif attribute["use"] == "optional": |
1690 elif attribute["use"] == "optional": |
1504 if attribute.has_key("default"): |
1691 if attribute.has_key("default"): |
1505 setattr(self, attribute["name"], attribute["attr_type"]["extract"](attribute["default"], False)) |
1692 setattr(self, attribute["name"], attribute["attr_type"]["extract"](attribute["default"], False)) |
1506 else: |
1693 else: |
1507 setattr(self, attribute["name"], None) |
1694 setattr(self, attribute["name"], None) |
1508 for element in classinfos["elements"]: |
1695 for element in classinfos["elements"]: |
1509 if isinstance(element["elmt_type"], (UnicodeType, StringType)): |
1696 setattr(self, element["name"], GetElementInitialValue(factory, element)) |
1510 namespace, name = DecomposeQualifiedName(element["elmt_type"]) |
|
1511 element["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1512 if element["minOccurs"] == 0 and element["maxOccurs"] == 1: |
|
1513 if "default" in element: |
|
1514 setattr(self, element["name"], element["elmt_type"]["extract"](element["default"], False)) |
|
1515 else: |
|
1516 setattr(self, element["name"], None) |
|
1517 elif element["minOccurs"] == 1 and element["maxOccurs"] == 1: |
|
1518 setattr(self, element["name"], element["elmt_type"]["initial"]()) |
|
1519 else: |
|
1520 value = [] |
|
1521 for i in xrange(element["minOccurs"]): |
|
1522 value.append(element["elmt_type"]["initial"]()) |
|
1523 setattr(self, element["name"], value) |
|
1524 return initMethod |
1697 return initMethod |
1525 |
1698 |
1526 def generateSetMethod(attr): |
1699 def generateSetMethod(attr): |
1527 def setMethod(self, value): |
1700 def setMethod(self, value): |
1528 setattr(self, attr, value) |
1701 setattr(self, attr, value) |
1534 return getMethod |
1707 return getMethod |
1535 |
1708 |
1536 def generateAddMethod(attr, factory, infos): |
1709 def generateAddMethod(attr, factory, infos): |
1537 def addMethod(self): |
1710 def addMethod(self): |
1538 if infos["type"] == ATTRIBUTE: |
1711 if infos["type"] == ATTRIBUTE: |
1539 if isinstance(infos["attr_type"], (UnicodeType, StringType)): |
1712 infos["attr_type"] = FindTypeInfos(factory, infos["attr_type"]) |
1540 namespace, name = DecomposeQualifiedName(infos) |
|
1541 infos["attr_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1542 initial = infos["attr_type"]["initial"] |
1713 initial = infos["attr_type"]["initial"] |
1543 extract = infos["attr_type"]["extract"] |
1714 extract = infos["attr_type"]["extract"] |
1544 elif infos["type"] == ELEMENT: |
1715 elif infos["type"] == ELEMENT: |
1545 if isinstance(infos["elmt_type"], (UnicodeType, StringType)): |
1716 infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
1546 namespace, name = DecomposeQualifiedName(infos) |
|
1547 infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1548 initial = infos["elmt_type"]["initial"] |
1717 initial = infos["elmt_type"]["initial"] |
1549 extract = infos["elmt_type"]["extract"] |
1718 extract = infos["elmt_type"]["extract"] |
1550 else: |
1719 else: |
1551 raise ValueError("Invalid class attribute!") |
1720 raise ValueError("Invalid class attribute!") |
1552 if infos.has_key("default"): |
1721 if infos.has_key("default"): |
1560 setattr(self, attr, None) |
1729 setattr(self, attr, None) |
1561 return deleteMethod |
1730 return deleteMethod |
1562 |
1731 |
1563 def generateAppendMethod(attr, maxOccurs, factory, infos): |
1732 def generateAppendMethod(attr, maxOccurs, factory, infos): |
1564 def appendMethod(self, value): |
1733 def appendMethod(self, value): |
1565 if isinstance(infos["elmt_type"], (UnicodeType, StringType)): |
1734 infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
1566 namespace, name = DecomposeQualifiedName(infos) |
|
1567 infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1568 attr_list = getattr(self, attr) |
1735 attr_list = getattr(self, attr) |
1569 if maxOccurs == "unbounded" or len(attr_list) < maxOccurs: |
1736 if maxOccurs == "unbounded" or len(attr_list) < maxOccurs: |
1570 if infos["elmt_type"]["check"](value): |
1737 if infos["elmt_type"]["check"](value): |
1571 attr_list.append(value) |
1738 attr_list.append(value) |
1572 else: |
1739 else: |
1575 raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr)) |
1742 raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr)) |
1576 return appendMethod |
1743 return appendMethod |
1577 |
1744 |
1578 def generateInsertMethod(attr, maxOccurs, factory, infos): |
1745 def generateInsertMethod(attr, maxOccurs, factory, infos): |
1579 def insertMethod(self, index, value): |
1746 def insertMethod(self, index, value): |
1580 if isinstance(infos["elmt_type"], (UnicodeType, StringType)): |
1747 infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"]) |
1581 namespace, name = DecomposeQualifiedName(infos) |
|
1582 infos["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1583 attr_list = getattr(self, attr) |
1748 attr_list = getattr(self, attr) |
1584 if maxOccurs == "unbounded" or len(attr_list) < maxOccurs: |
1749 if maxOccurs == "unbounded" or len(attr_list) < maxOccurs: |
1585 if infos["elmt_type"]["check"](value): |
1750 if infos["elmt_type"]["check"](value): |
1586 attr_list.insert(index, value) |
1751 attr_list.insert(index, value) |
1587 else: |
1752 else: |
1598 def generateSetChoiceByTypeMethod(factory, choice_types): |
1763 def generateSetChoiceByTypeMethod(factory, choice_types): |
1599 choices = dict([(choice["name"], choice) for choice in choice_types]) |
1764 choices = dict([(choice["name"], choice) for choice in choice_types]) |
1600 def setChoiceMethod(self, type): |
1765 def setChoiceMethod(self, type): |
1601 if not choices.has_key(type): |
1766 if not choices.has_key(type): |
1602 raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type) |
1767 raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type) |
1603 if isinstance(choices[type]["elmt_type"], (UnicodeType, StringType)): |
1768 choices[type]["elmt_type"] = FindTypeInfos(factory, choices[type]["elmt_type"]) |
1604 namespace, name = DecomposeQualifiedName(choices[type]["elmt_type"]) |
|
1605 choices[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1606 new_element = choices[type]["elmt_type"]["initial"]() |
1769 new_element = choices[type]["elmt_type"]["initial"]() |
1607 self.content = {"name": type, "value": new_element} |
1770 self.content = {"name": type, "value": new_element} |
1608 return new_element |
1771 return new_element |
1609 return setChoiceMethod |
1772 return setChoiceMethod |
1610 |
1773 |
1611 def generateAppendChoiceByTypeMethod(maxOccurs, factory, choice_types): |
1774 def generateAppendChoiceByTypeMethod(maxOccurs, factory, choice_types): |
1612 choices = dict([(choice["name"], choice) for choice in choice_types]) |
1775 choices = dict([(choice["name"], choice) for choice in choice_types]) |
1613 def appendChoiceMethod(self, type): |
1776 def appendChoiceMethod(self, type): |
1614 if not choices.has_key(type): |
1777 if not choices.has_key(type): |
1615 raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type) |
1778 raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type) |
1616 if isinstance(choices[type]["elmt_type"], (UnicodeType, StringType)): |
1779 choices[type]["elmt_type"] = FindTypeInfos(factory, choices[type]["elmt_type"]) |
1617 namespace, name = DecomposeQualifiedName(choices[type]["elmt_type"]) |
|
1618 choices[type]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1619 if maxOccurs == "unbounded" or len(self.content) < maxOccurs: |
1780 if maxOccurs == "unbounded" or len(self.content) < maxOccurs: |
1620 new_element = choices[type]["elmt_type"]["initial"]() |
1781 new_element = choices[type]["elmt_type"]["initial"]() |
1621 self.content.append({"name": type, "value": new_element}) |
1782 self.content.append({"name": type, "value": new_element}) |
1622 return new_element |
1783 return new_element |
1623 else: |
1784 else: |
1627 def generateInsertChoiceByTypeMethod(maxOccurs, factory, choice_types): |
1788 def generateInsertChoiceByTypeMethod(maxOccurs, factory, choice_types): |
1628 choices = dict([(choice["name"], choice) for choice in choice_types]) |
1789 choices = dict([(choice["name"], choice) for choice in choice_types]) |
1629 def insertChoiceMethod(self, index, type): |
1790 def insertChoiceMethod(self, index, type): |
1630 if not choices.has_key(type): |
1791 if not choices.has_key(type): |
1631 raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type) |
1792 raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type) |
1632 if isinstance(choices[type]["elmt_type"], (UnicodeType, StringType)): |
1793 choices[type]["elmt_type"] = FindTypeInfos(factory, choices[type]["elmt_type"]) |
1633 namespace, name = DecomposeQualifiedName(choices[type]["elmt_type"]) |
|
1634 choices[name]["elmt_type"] = factory.GetQualifiedNameInfos(name, namespace) |
|
1635 if maxOccurs == "unbounded" or len(self.content) < maxOccurs: |
1794 if maxOccurs == "unbounded" or len(self.content) < maxOccurs: |
1636 new_element = choices[type]["elmt_type"]["initial"]() |
1795 new_element = choices[type]["elmt_type"]["initial"]() |
1637 self.content.insert(index, {"name" : type, "value" : new_element}) |
1796 self.content.insert(index, {"name" : type, "value" : new_element}) |
1638 return new_element |
1797 return new_element |
1639 else: |
1798 else: |
1663 if declare: |
1822 if declare: |
1664 for ClassName, Class in pluginClasses.items(): |
1823 for ClassName, Class in pluginClasses.items(): |
1665 sys._getframe(1).f_locals[ClassName] = Class |
1824 sys._getframe(1).f_locals[ClassName] = Class |
1666 for TypeName, Type in pluginTypes.items(): |
1825 for TypeName, Type in pluginTypes.items(): |
1667 sys._getframe(1).f_locals[TypeName] = Type |
1826 sys._getframe(1).f_locals[TypeName] = Type |
1668 globals().update(ComputedClasses) |
1827 if factory.FileName is not None and len(ComputedClasses) == 1: |
1669 return ComputedClasses |
1828 globals().update(ComputedClasses[factory.FileName]) |
1670 |
1829 return ComputedClasses[factory.FileName] |
1830 else: |
|
1831 globals().update(ComputedClasses) |
|
1832 return ComputedClasses |
|
1833 |