FreeCAD
3475 строк · 123.0 Кб
1#!/usr/bin/env python
2
3## LICENSE
4
5## Copyright (c) 2003 Dave Kuhlman
6
7## Permission is hereby granted, free of charge, to any person obtaining
8## a copy of this software and associated documentation files (the
9## "Software"), to deal in the Software without restriction, including
10## without limitation the rights to use, copy, modify, merge, publish,
11## distribute, sublicense, and/or sell copies of the Software, and to
12## permit persons to whom the Software is furnished to do so, subject to
13## the following conditions:
14
15## The above copyright notice and this permission notice shall be
16## included in all copies or substantial portions of the Software.
17
18## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21## IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22## CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23## TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24## SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26import sys
27import os.path
28import time
29import getopt
30from urllib.request import urlopen
31from urllib.error import HTTPError
32from xml.sax import handler, make_parser
33import xml.sax.xmlreader
34
35##from IPython.Shell import IPShellEmbed
36##args = ''
37##ipshell = IPShellEmbed(args,
38## banner = 'Dropping into IPython',
39## exit_msg = 'Leaving Interpreter, back to program.')
40
41# Then use the following line where and when you want to drop into the
42# IPython shell:
43# ipshell('<some message> -- Entering ipshell.\\nHit Ctrl-D to exit')
44
45
46#
47# Global variables etc.
48#
49GenerateProperties = 0
50DelayedElements = []
51DelayedElements_subclass = []
52AlreadyGenerated = []
53AlreadyGenerated_subclass = []
54PostponedExtensions = []
55ElementsForSubclasses = []
56ElementDict = {}
57SaxElementDict = {}
58ElementDebugList = []
59Force = 0
60NameTable = {
61"class": "klass",
62"import": "emport",
63"type": "ttype",
64}
65SubclassSuffix = "Sub"
66RootElement = None
67AttributeGroups = {}
68SubstitutionGroups = {}
69#
70# SubstitutionGroups can also include simple types that are
71# not (defined) elements. Keep a list of these simple types.
72# These are simple types defined at top level.
73SimpleElementDict = {}
74
75
76def set_type_constants(nameSpace):
77global StringType, TokenType, IntegerType, DecimalType, ShortType, LongType, PositiveIntegerType, NegativeIntegerType, NonPositiveIntegerType, NonNegativeIntegerType, BooleanType, FloatType, DoubleType, ElementType, ComplexTypeType, SequenceType, ChoiceType, AttributeGroupType, AttributeType, SchemaType, DateTimeType, DateType, ComplexContentType, ExtensionType, IDType, IDREFType, IDREFSType, AnyAttributeType
78AttributeGroupType = nameSpace + "attributeGroup"
79AttributeType = nameSpace + "attribute"
80BooleanType = nameSpace + "boolean"
81ChoiceType = nameSpace + "choice"
82ComplexContentType = nameSpace + "complexContent"
83ComplexTypeType = nameSpace + "complexType"
84AnyAttributeType = nameSpace + "anyAttribute"
85DateTimeType = nameSpace + "dateTime"
86DateType = nameSpace + "date"
87IntegerType = (
88nameSpace + "integer",
89nameSpace + "xs:unsignedShort",
90nameSpace + "short",
91nameSpace + "long",
92)
93# ShortType = nameSpace + 'short'
94# LongType = nameSpace + 'long'
95DecimalType = nameSpace + "decimal"
96PositiveIntegerType = nameSpace + "positiveInteger"
97NegativeIntegerType = nameSpace + "negativeInteger"
98NonPositiveIntegerType = nameSpace + "nonPositiveInteger"
99NonNegativeIntegerType = nameSpace + "nonNegativeInteger"
100DoubleType = nameSpace + "double"
101ElementType = nameSpace + "element"
102ExtensionType = nameSpace + "extension"
103FloatType = nameSpace + "float"
104IDREFSType = nameSpace + "IDREFS"
105IDREFType = nameSpace + "IDREF"
106IDType = nameSpace + "ID"
107SchemaType = nameSpace + "schema"
108SequenceType = nameSpace + "sequence"
109StringType = (
110nameSpace + "string",
111nameSpace + "duration",
112nameSpace + "anyURI",
113)
114TokenType = nameSpace + "token"
115
116
117#
118# For debugging.
119#
120
121# Print only if DEBUG is true.
122DEBUG = 1
123
124
125def dbgprint(level, msg):
126if DEBUG and level > 0:
127print(msg)
128
129
130def pplist(lst):
131for count, item in enumerate(lst):
132print("%d. %s" % (count, item))
133
134
135#
136# Representation of element definition.
137#
138
139
140def showLevel(outfile, level):
141for idx in range(level):
142outfile.write(" ")
143
144
145class XschemaElement:
146def __init__(self, attrs):
147self.cleanName = ""
148self.attrs = dict(attrs)
149name_val = ""
150type_val = ""
151ref_val = ""
152if "name" in self.attrs:
153name_val = strip_namespace(self.attrs["name"])
154if "type" in self.attrs:
155# fix
156# type_val = strip_namespace(self.attrs['type'])
157type_val = self.attrs["type"]
158if "ref" in self.attrs:
159ref_val = strip_namespace(self.attrs["ref"])
160if type_val and not name_val:
161name_val = type_val
162if ref_val and not name_val:
163name_val = ref_val
164if ref_val and not type_val:
165type_val = ref_val
166if name_val:
167self.attrs["name"] = name_val
168if type_val:
169self.attrs["type"] = type_val
170if ref_val:
171self.attrs["ref"] = ref_val
172self.name = name_val
173self.children = []
174self.maxOccurs = 1
175self.complex = 0
176self.complexType = 0
177self.type = "NoneType"
178self.mixed = 0
179self.base = None
180self.mixedExtensionError = 0
181# Attribute definitions for the correct element.
182self.attributeDefs = {}
183# Attribute definitions for the current attributeGroup, if there is one.
184self.attributeGroup = None
185# List of names of attributes for this element.
186# We will add the attribute definitions in each of these groups
187# to this element in annotate().
188self.attributeGroupNameList = []
189self.topLevel = 0
190# Does this element contain an anyAttribute?
191self.anyAttribute = 0
192
193def addChild(self, element):
194self.children.append(element)
195
196def getChildren(self):
197return self.children
198
199def getName(self):
200return self.name
201
202def getCleanName(self):
203return self.cleanName
204
205def getUnmappedCleanName(self):
206return self.unmappedCleanName
207
208def setName(self, name):
209self.name = name
210
211def getAttrs(self):
212return self.attrs
213
214def setAttrs(self, attrs):
215self.attrs = attrs
216
217def getMaxOccurs(self):
218return self.maxOccurs
219
220def getRawType(self):
221return self.type
222
223def getType(self):
224returnType = self.type
225if self.type in ElementDict:
226typeObj = ElementDict[self.type]
227typeObjType = typeObj.getRawType()
228if (
229typeObjType in StringType
230or typeObjType == TokenType
231or typeObjType == DateTimeType
232or typeObjType == DateType
233or typeObjType in IntegerType
234or typeObjType == DecimalType
235or typeObjType == PositiveIntegerType
236or typeObjType == NegativeIntegerType
237or typeObjType == NonPositiveIntegerType
238or typeObjType == NonNegativeIntegerType
239or typeObjType == BooleanType
240or typeObjType == FloatType
241or typeObjType == DoubleType
242):
243returnType = typeObjType
244return returnType
245
246def isComplex(self):
247return self.complex
248
249def addAttributeDefs(self, attrs):
250self.attributeDefs.append(attrs)
251
252def getAttributeDefs(self):
253return self.attributeDefs
254
255def isMixed(self):
256return self.mixed
257
258def setMixed(self, mixed):
259self.mixed = mixed
260
261def setBase(self, base):
262self.base = base
263
264def getBase(self):
265return self.base
266
267def getMixedExtensionError(self):
268return self.mixedExtensionError
269
270def getAttributeGroups(self):
271return self.attributeGroups
272
273def addAttribute(self, name, attribute):
274self.attributeGroups[name] = attribute
275
276def setAttributeGroup(self, attributeGroup):
277self.attributeGroup = attributeGroup
278
279def getAttributeGroup(self):
280return self.attributeGroup
281
282def setTopLevel(self, topLevel):
283self.topLevel = topLevel
284
285def getTopLevel(self):
286return self.topLevel
287
288def setAnyAttribute(self, anyAttribute):
289self.anyAttribute = anyAttribute
290
291def getAnyAttribute(self):
292return self.anyAttribute
293
294def show(self, outfile, level):
295showLevel(outfile, level)
296outfile.write("Name: %s Type: %s\n" % (self.name, self.getType()))
297showLevel(outfile, level)
298outfile.write(" - Complex: %d MaxOccurs: %d\n" % (self.complex, self.maxOccurs))
299showLevel(outfile, level)
300outfile.write(" - Attrs: %s\n" % self.attrs)
301showLevel(outfile, level)
302outfile.write(" - AttributeDefs: %s\n" % self.attributeDefs)
303# ipshell('(visit_title) Entering ipshell.\nHit Ctrl-D to exit')
304
305for attr in self.getAttributeDefs():
306key = attr["name"]
307try:
308value = attr["value"]
309except:
310value = "<empty>"
311showLevel(outfile, level + 1)
312outfile.write("key: %s value: %s\n" % (key, value))
313for child in self.children:
314child.show(outfile, level + 1)
315
316def annotate(self):
317self.collect_element_dict()
318self.annotate_find_type()
319self.annotate_tree()
320self.fix_dup_names()
321self.coerce_attr_types()
322self.checkMixedBases()
323
324def collect_element_dict(self):
325base = self.getBase()
326if (
327self.getTopLevel()
328or len(self.getChildren()) > 0
329or len(self.getAttributeDefs()) > 0
330or base
331):
332ElementDict[self.name] = self
333for child in self.children:
334child.collect_element_dict()
335
336def element_is_complex(self):
337pass
338
339# If it is a mixed-content element and it is defined as
340# an extension, then all of its bases (base, base of base, ...)
341# must be mixed-content. Mark it as an error, if not.
342def checkMixedBases(self):
343self.checkMixedBasesChain(self, self.mixed)
344for child in self.children:
345child.checkMixedBases()
346
347def checkMixedBasesChain(self, child, childMixed):
348base = self.getBase()
349if base and base in ElementDict:
350parent = ElementDict[base]
351if childMixed != parent.isMixed():
352self.mixedExtensionError = 1
353return
354parent.checkMixedBasesChain(child, childMixed)
355
356def resolve_type(self):
357self.complex = 0
358# If it has any attributes, then it's complex.
359attrDefs = self.getAttributeDefs()
360if len(attrDefs) > 0:
361self.complex = 1
362# type_val = ''
363type_val = self.resolve_type_1()
364if type_val:
365if type_val in ElementDict:
366element = ElementDict[type_val]
367type_val1 = element.resolve_type_1()
368if (
369type_val1 in StringType
370or type_val1 == TokenType
371or type_val1 == DateTimeType
372or type_val1 == DateType
373or type_val1 in IntegerType
374or type_val1 == DecimalType
375or type_val1 == PositiveIntegerType
376or type_val1 == NonPositiveIntegerType
377or type_val1 == NegativeIntegerType
378or type_val1 == NonNegativeIntegerType
379or type_val1 == BooleanType
380or type_val1 == FloatType
381or type_val1 == DoubleType
382):
383type_val = type_val1
384else:
385self.complex = 1
386else:
387if (
388type_val in StringType
389or type_val == TokenType
390or type_val == DateTimeType
391or type_val == DateType
392or type_val in IntegerType
393or type_val == DecimalType
394or type_val == PositiveIntegerType
395or type_val == NonPositiveIntegerType
396or type_val == NegativeIntegerType
397or type_val == NonNegativeIntegerType
398or type_val == BooleanType
399or type_val == FloatType
400or type_val == DoubleType
401):
402pass
403else:
404type_val = StringType[0]
405else:
406type_val = StringType[0]
407return type_val
408
409def resolve_type_1(self):
410type_val = ""
411if "type" in self.attrs:
412# fix
413# type_val = strip_namespace(self.attrs['type'])
414type_val = self.attrs["type"]
415elif "ref" in self.attrs:
416# fix
417type_val = strip_namespace(self.attrs["ref"])
418# type_val = self.attrs['ref']
419elif "name" in self.attrs:
420# fix
421type_val = strip_namespace(self.attrs["name"])
422# type_val = self.attrs['name']
423return type_val
424
425def annotate_find_type(self):
426type_val = self.resolve_type()
427# dbgprint(1, '(aft) n: %s t: %s c: %s id: %s' % \
428# (self.name, type_val, self.complex, id(self), ))
429self.attrs["type"] = type_val
430self.type = type_val
431if not self.complex:
432SimpleElementDict[self.name] = self.name
433for child in self.children:
434child.annotate_find_type()
435
436def annotate_tree(self):
437# If there is a namespace, replace it with an underscore.
438if self.base:
439self.base = strip_namespace(self.base)
440self.unmappedCleanName = cleanupName(self.name)
441self.cleanName = mapName(self.unmappedCleanName)
442SaxElementDict[self.cleanName] = self
443self.replace_attributeGroup_names()
444if "maxOccurs" in self.attrs:
445maxOccurs = self.attrs["maxOccurs"]
446if maxOccurs == "unbounded":
447maxOccurs = 99999
448else:
449try:
450maxOccurs = int(self.attrs["maxOccurs"])
451except ValueError:
452sys.stderr.write(
453'*** %s maxOccurs must be integer or "unbounded".' % (self.getName(),)
454)
455sys.exit(-1)
456else:
457maxOccurs = 1
458self.maxOccurs = maxOccurs
459# if self.cleanName == 'Reason_XXX':
460# ipshell('(annotate_tree) -- Entering ipshell.\\nHit Ctrl-D to exit')
461# If it does not have a type, then make the type the same as the name.
462if self.type == "NoneType" and self.name:
463self.type = self.name
464# Is it a mixed-content element definition?
465if "mixed" in self.attrs:
466mixed = self.attrs["mixed"].strip()
467if mixed == "1" or mixed.lower() == "true":
468self.mixed = 1
469# Do it recursively for all descendents.
470for child in self.children:
471child.annotate_tree()
472
473#
474# For each name in the attributeGroupNameList for this element,
475# add the attributes defined for that name in the global
476# attributeGroup dictionary.
477def replace_attributeGroup_names(self):
478for groupName in self.attributeGroupNameList:
479if groupName in AttributeGroups:
480attrGroup = AttributeGroups[groupName]
481for name in attrGroup.getKeys():
482attr = attrGroup.get(name)
483self.attributeDefs[name] = attr
484else:
485print("*** Error. attributeGroup %s not defined." % groupName)
486
487def __str__(self):
488s1 = '<"%s" XschemaElement instance at 0x%x>' % (self.getName(), id(self))
489return s1
490
491def __repr__(self):
492s1 = '<"%s" XschemaElement instance at 0x%x>' % (self.getName(), id(self))
493return s1
494
495def fix_dup_names(self):
496# Patch-up names that are used for both a child element and an attribute.
497#
498attrDefs = self.getAttributeDefs()
499# Collect a list of child element names.
500# Must do this for base (extension) elements also.
501elementNames = []
502self.collectElementNames(elementNames)
503replaced = []
504# Create the needed new attributes.
505keys = attrDefs.keys()
506for key in keys:
507attr = attrDefs[key]
508name = attr.getName()
509if name in elementNames:
510newName = name + "_attr"
511newAttr = XschemaAttribute(newName)
512attrDefs[newName] = newAttr
513replaced.append(name)
514# Remove the old (replaced) attributes.
515for name in replaced:
516del attrDefs[name]
517for child in self.children:
518child.fix_dup_names()
519
520def collectElementNames(self, elementNames):
521for child in self.children:
522elementNames.append(cleanupName(child.cleanName))
523base = self.getBase()
524if base and base in ElementDict:
525parent = ElementDict[base]
526parent.collectElementNames(elementNames)
527
528def coerce_attr_types(self):
529replacements = []
530attrDefs = self.getAttributeDefs()
531for idx, name in enumerate(attrDefs):
532attr = attrDefs[name]
533attrType = attr.getData_type()
534if attrType == IDType or attrType == IDREFType or attrType == IDREFSType:
535attr.setData_type(StringType[0])
536for child in self.children:
537child.coerce_attr_types()
538
539
540# end class XschemaElement
541
542
543class XschemaAttributeGroup:
544def __init__(self, name="", group=None):
545self.name = name
546if group:
547self.group = group
548else:
549self.group = {}
550
551def setName(self, name):
552self.name = name
553
554def getName(self):
555return self.name
556
557def setGroup(self, group):
558self.group = group
559
560def getGroup(self):
561return self.group
562
563def get(self, name, default=None):
564if name in self.group:
565return self.group[name]
566else:
567return default
568
569def getKeys(self):
570return self.group.keys()
571
572def add(self, name, attr):
573self.group[name] = attr
574
575def delete(self, name):
576# if has_key(self.group, name):
577if name in self.group:
578del self.group[name]
579return 1
580else:
581return 0
582
583
584# end class XschemaAttributeGroup
585
586
587class XschemaAttribute:
588def __init__(self, name, data_type="xs:string", use="optional"):
589self.name = name
590self.data_type = data_type
591self.use = use
592
593def setName(self, name):
594self.name = name
595
596def getName(self):
597return self.name
598
599def setData_type(self, data_type):
600self.data_type = data_type
601
602def getData_type(self):
603return self.data_type
604
605def setUse(self, use):
606self.use = use
607
608def getUse(self):
609return self.use
610
611
612# end class XschemaAttribute
613
614
615#
616# SAX handler
617#
618class XschemaHandler(handler.ContentHandler):
619def __init__(self):
620handler.ContentHandler.__init__(self)
621self.stack = []
622self.root = None
623self.inElement = 0
624self.inComplexType = 0
625self.inNonanonymousComplexType = 0
626self.inSequence = 0
627self.inChoice = 1
628self.inAttribute = 0
629self.inAttributeGroup = 0
630self.inSimpleElement = 0
631
632## self.dbgcount = 1
633## self.dbgnames = []
634
635def getRoot(self):
636# ipshell('Returning root -- Entering ipshell.\\nHit Ctrl-D to exit')
637return self.root
638
639def showError(self, msg):
640print(msg)
641sys.exit(-1)
642
643def startElement(self, name, attrs):
644# dbgprint(1, 'before schema name: %s SchemaType: %s' % (name, SchemaType,))
645if name == SchemaType:
646# dbgprint(1, '(schema in)')
647self.inSchema = 1
648element = XschemaElement(attrs)
649if len(self.stack) == 1:
650element.setTopLevel(1)
651self.stack.append(element)
652# If there is an attribute "xmlns" and its value is
653# "http://www.w3.org/2001/XMLSchema", then remember and
654# use that namespace prefix.
655for name, value in attrs.items():
656if name[:6] == "xmlns:" and value == "http://www.w3.org/2001/XMLSchema":
657nameSpace = name[6:] + ":"
658set_type_constants(nameSpace)
659elif name == ElementType or ((name == ComplexTypeType) and (len(self.stack) == 1)):
660self.inElement = 1
661self.inNonanonymousComplexType = 1
662element = XschemaElement(attrs)
663if len(self.stack) == 1:
664element.setTopLevel(1)
665if "substitutionGroup" in attrs and "name" in attrs:
666substituteName = attrs["name"]
667headName = attrs["substitutionGroup"]
668if headName not in SubstitutionGroups:
669SubstitutionGroups[headName] = []
670SubstitutionGroups[headName].append(substituteName)
671# dbgprint(1, '(startElement) added %s to %s' % (substituteName, headName))
672if name == ComplexTypeType:
673element.complexType = 1
674self.stack.append(element)
675elif name == ComplexTypeType:
676# If it have any attributes and there is something on the stack,
677# then copy the attributes to the item on top of the stack.
678if len(self.stack) > 1 and len(attrs) > 0:
679parentDict = self.stack[-1].getAttrs()
680for key in attrs.keys():
681parentDict[key] = attrs[key]
682self.inComplexType = 1
683elif name == SequenceType:
684self.inSequence = 1
685elif name == ChoiceType:
686self.inChoice = 1
687elif name == AttributeType:
688self.inAttribute = 1
689if "name" in attrs:
690name = attrs["name"]
691# fix-attribute-ref
692elif "ref" in attrs:
693name = strip_namespace(attrs["ref"])
694else:
695name = "no_attribute_name"
696if "type" in attrs:
697data_type = attrs["type"]
698else:
699data_type = StringType[0]
700if "use" in attrs:
701use = attrs["use"]
702else:
703use = "optional"
704if self.stack[-1].attributeGroup:
705# Add this attribute to a current attributeGroup.
706attribute = XschemaAttribute(name, data_type, use)
707self.stack[-1].attributeGroup.add(name, attribute)
708else:
709# Add this attribute to the element/complexType.
710attribute = XschemaAttribute(name, data_type, use)
711self.stack[-1].attributeDefs[name] = attribute
712elif name == AttributeGroupType:
713self.inAttributeGroup = 1
714# If it has attribute 'name', then it's a definition.
715# Prepare to save it as an attributeGroup.
716if "name" in attrs:
717name = strip_namespace(attrs["name"])
718attributeGroup = XschemaAttributeGroup(name)
719element = XschemaElement(attrs)
720if len(self.stack) == 1:
721element.setTopLevel(1)
722element.setAttributeGroup(attributeGroup)
723self.stack.append(element)
724# If it has attribute 'ref', add it to the list of
725# attributeGroups for this element/complexType.
726if "ref" in attrs:
727self.stack[-1].attributeGroupNameList.append(attrs["ref"])
728elif name == ComplexContentType:
729pass
730elif name == ExtensionType:
731if "base" in attrs and len(self.stack) > 0:
732extensionBase = attrs["base"]
733if (
734extensionBase in StringType
735or extensionBase == TokenType
736or extensionBase == DateTimeType
737or extensionBase == DateType
738or extensionBase in IntegerType
739or extensionBase == DecimalType
740or extensionBase == PositiveIntegerType
741or extensionBase == NegativeIntegerType
742or extensionBase == NonPositiveIntegerType
743or extensionBase == NonNegativeIntegerType
744or extensionBase == BooleanType
745or extensionBase == FloatType
746or extensionBase == DoubleType
747):
748pass
749else:
750self.stack[-1].setBase(extensionBase)
751elif name == AnyAttributeType:
752# Mark the current element as containing anyAttribute.
753self.stack[-1].setAnyAttribute(1)
754
755def endElement(self, name):
756if self.inSimpleElement:
757self.inSimpleElement = 0
758elif name == ElementType or (name == ComplexTypeType and self.stack[-1].complexType):
759self.inElement = 0
760self.inNonanonymousComplexType = 0
761element = self.stack.pop()
762self.stack[-1].addChild(element)
763elif name == ComplexTypeType:
764self.inComplexType = 0
765elif name == SequenceType:
766self.inSequence = 0
767elif name == ChoiceType:
768self.inChoice = 0
769elif name == AttributeType:
770self.inAttribute = 0
771elif name == AttributeGroupType:
772self.inAttributeGroup = 0
773if self.stack[-1].attributeGroup:
774# The top of the stack contains an XschemaElement which
775# contains the definition of an attributeGroup.
776# Save this attributeGroup in the
777# global AttributeGroup dictionary.
778attributeGroup = self.stack[-1].attributeGroup
779name = attributeGroup.getName()
780AttributeGroups[name] = attributeGroup
781self.stack[-1].attributeGroup = None
782self.stack.pop()
783else:
784# This is a reference to an attributeGroup.
785# We have already added it to the list of attributeGroup names.
786# Leave it. We'll fill it in during annotate.
787pass
788elif name == SchemaType:
789self.inSchema = 0
790if len(self.stack) != 1:
791print("*** error stack. len(self.stack): %d" % len(self.stack))
792sys.exit(-1)
793self.root = self.stack[0]
794elif name == ComplexContentType:
795pass
796elif name == ExtensionType:
797pass
798
799def characters(self, chrs):
800if self.inElement:
801pass
802elif self.inComplexType:
803pass
804elif self.inSequence:
805pass
806elif self.inChoice:
807pass
808
809
810#
811# Code generation
812#
813
814
815def generateExportFn_1(outfile, child, name, fill):
816cleanName = cleanupName(name)
817if (
818child.getType() in StringType
819or child.getType() == TokenType
820or child.getType() == DateTimeType
821or child.getType() == DateType
822):
823s1 = "%s showIndent(outfile, level)\n" % fill
824outfile.write(s1)
825s1 = "%s outfile.write('<%s>%%s</%s>\\n' %% quote_xml(self.get%s()))\n" % (
826fill,
827name,
828name,
829cleanName.capitalize(),
830)
831outfile.write(s1)
832elif (
833child.getType() in IntegerType
834or child.getType() == BooleanType
835or child.getType() == PositiveIntegerType
836or child.getType() == NonPositiveIntegerType
837or child.getType() == NegativeIntegerType
838or child.getType() == NonNegativeIntegerType
839):
840s1 = "%s showIndent(outfile, level)\n" % fill
841outfile.write(s1)
842s1 = "%s outfile.write('<%s>%%d</%s>\\n' %% self.get%s())\n" % (
843fill,
844name,
845name,
846cleanName.capitalize(),
847)
848outfile.write(s1)
849elif child.getType() == FloatType or child.getType() == DecimalType:
850s1 = "%s showIndent(outfile, level)\n" % fill
851outfile.write(s1)
852s1 = "%s outfile.write('<%s>%%f</%s>\\n' %% self.get%s())\n" % (
853fill,
854name,
855name,
856cleanName.capitalize(),
857)
858outfile.write(s1)
859elif child.getType() == DoubleType:
860s1 = "%s showIndent(outfile, level)\n" % fill
861outfile.write(s1)
862s1 = "%s outfile.write('<%s>%%e</%s>\\n' %% self.get%s())\n" % (
863fill,
864name,
865name,
866cleanName.capitalize(),
867)
868outfile.write(s1)
869else:
870s1 = "%s if self.%s:\n" % (fill, cleanName)
871outfile.write(s1)
872if name == child.getType():
873s1 = "%s self.%s.export(outfile, level)\n" % (fill, cleanName)
874else:
875s1 = "%s self.%s.export(outfile, level, name_='%s')\n" % (
876fill,
877cleanName,
878name,
879)
880outfile.write(s1)
881
882
883def generateExportFn_2(outfile, child, name, fill):
884cleanName = cleanupName(name)
885s1 = "%s for %s_ in self.get%s():\n" % (fill, cleanName, cleanName.capitalize())
886outfile.write(s1)
887if (
888child.getType() in StringType
889or child.getType() == TokenType
890or child.getType() == DateTimeType
891or child.getType() == DateType
892):
893s1 = "%s showIndent(outfile, level)\n" % fill
894outfile.write(s1)
895s1 = "%s outfile.write('<%s>%%s</%s>\\n' %% quote_xml(%s_))\n" % (
896fill,
897name,
898name,
899cleanName,
900)
901outfile.write(s1)
902elif (
903child.getType() in IntegerType
904or child.getType() == BooleanType
905or child.getType() == PositiveIntegerType
906or child.getType() == NonPositiveIntegerType
907or child.getType() == NegativeIntegerType
908or child.getType() == NonNegativeIntegerType
909):
910s1 = "%s showIndent(outfile, level)\n" % fill
911outfile.write(s1)
912s1 = "%s outfile.write('<%s>%%d</%s>\\n' %% %s_)\n" % (
913fill,
914name,
915name,
916cleanName,
917)
918outfile.write(s1)
919elif child.getType() == FloatType or child.getType() == DecimalType:
920s1 = "%s showIndent(outfile, level)\n" % fill
921outfile.write(s1)
922s1 = "%s outfile.write('<%s>%%f</%s>\\n' %% %s_)\n" % (
923fill,
924name,
925name,
926cleanName,
927)
928outfile.write(s1)
929elif child.getType() == DoubleType:
930s1 = "%s showIndent(outfile, level)\n" % fill
931outfile.write(s1)
932s1 = "%s outfile.write('<%s>%%e</%s>\\n' %% %s_)\n" % (
933fill,
934name,
935name,
936cleanName,
937)
938outfile.write(s1)
939else:
940if name == child.getType():
941s1 = "%s %s_.export(outfile, level)\n" % (fill, cleanName)
942else:
943s1 = "%s %s_.export(outfile, level, name_='%s')\n" % (
944fill,
945cleanName,
946cleanName,
947)
948outfile.write(s1)
949
950
951def generateExportAttributes(outfile, element, hasAttributes):
952if len(element.getAttributeDefs()) > 0:
953hasAttributes += 1
954attrDefs = element.getAttributeDefs()
955for key in attrDefs.keys():
956attrDef = attrDefs[key]
957name = attrDef.getName()
958cleanName = cleanupName(name)
959capName = cleanName.capitalize()
960if attrDef.getUse() == "optional":
961s1 = " if self.get%s() is not None:\n" % (capName,)
962outfile.write(s1)
963s1 = " outfile.write(' %s=\"%%s\"' %% (self.get%s(), ))\n" % (
964name,
965capName,
966)
967outfile.write(s1)
968else:
969s1 = " outfile.write(' %s=\"%%s\"' %% (self.get%s(), ))\n" % (
970name,
971capName,
972)
973outfile.write(s1)
974if element.getAnyAttribute():
975s1 = " for name, value in self.anyAttributes_.items():\n"
976outfile.write(s1)
977s1 = " outfile.write(' %s=\"%s\"' % (name, value, ))\n"
978outfile.write(s1)
979return hasAttributes
980
981
982def generateExportChildren(outfile, element, hasChildren):
983if len(element.getChildren()) > 0:
984hasChildren += 1
985if element.isMixed():
986s1 = " for item_ in self.content_:\n"
987outfile.write(s1)
988s1 = " item_.export(outfile, level, name_)\n"
989outfile.write(s1)
990else:
991for child in element.getChildren():
992name = child.getName()
993if child.getMaxOccurs() > 1:
994generateExportFn_2(outfile, child, name, " ")
995else:
996generateExportFn_1(outfile, child, name, "")
997## base = element.getBase()
998## if base and base in ElementDict:
999## parent = ElementDict[base]
1000## hasAttributes = generateExportChildren(outfile, parent, hasChildren)
1001return hasChildren
1002
1003
1004def countChildren(element, count):
1005count += len(element.getChildren())
1006base = element.getBase()
1007if base and base in ElementDict:
1008parent = ElementDict[base]
1009count = countChildren(parent, count)
1010return count
1011
1012
1013def generateExportFn(outfile, prefix, element):
1014base = element.getBase()
1015s1 = " def export(self, outfile, level, name_='%s'):\n" % element.getName()
1016outfile.write(s1)
1017s1 = " showIndent(outfile, level)\n"
1018outfile.write(s1)
1019if len(element.getAttributeDefs()) > 0:
1020s1 = " outfile.write('<%s' % (name_, ))\n"
1021outfile.write(s1)
1022
1023s1 = " self.exportAttributes(outfile, level, name_='%s')\n" % element.getName()
1024outfile.write(s1)
1025if element.isMixed():
1026s1 = " outfile.write('>')\n"
1027else:
1028s1 = " outfile.write('>\\n')\n"
1029outfile.write(s1)
1030else:
1031if element.isMixed():
1032s1 = " outfile.write('<%s>' % name_)\n"
1033else:
1034s1 = " outfile.write('<%s>\\n' % name_)\n"
1035outfile.write(s1)
1036
1037s1 = " self.exportChildren(outfile, level + 1, name_)\n"
1038outfile.write(s1)
1039s1 = " showIndent(outfile, level)\n"
1040outfile.write(s1)
1041s1 = " outfile.write('</%s>\\n' % name_)\n"
1042outfile.write(s1)
1043s1 = " def exportAttributes(self, outfile, level, name_='%s'):\n" % element.getName()
1044outfile.write(s1)
1045hasAttributes = 0
1046hasAttributes = generateExportAttributes(outfile, element, hasAttributes)
1047if base:
1048hasAttributes += 1
1049s1 = " %s.exportAttributes(self, outfile, level, name_='%s')\n" % (
1050base,
1051element.getName(),
1052)
1053outfile.write(s1)
1054if hasAttributes == 0:
1055s1 = " pass\n"
1056outfile.write(s1)
1057## if len(element.getChildren()) > 0 and not element.isMixed():
1058## s1 = ' showIndent(outfile, level)\n'
1059## outfile.write(s1)
1060s1 = " def exportChildren(self, outfile, level, name_='%s'):\n" % element.getName()
1061outfile.write(s1)
1062hasChildren = 0
1063hasChildren = generateExportChildren(outfile, element, hasChildren)
1064if base:
1065hasChildren += 1
1066s1 = " %s.exportChildren(self, outfile, level, name_)\n" % (base,)
1067outfile.write(s1)
1068count = countChildren(element, 0)
1069if count == 0:
1070s1 = " outfile.write(self.valueOf_)\n"
1071outfile.write(s1)
1072
1073
1074#
1075# Generate exportLiteral method.
1076#
1077
1078
1079def generateExportLiteralFn_1(outfile, child, name, fill):
1080mappedName = mapName(name)
1081if (
1082child.getType() in StringType
1083or child.getType() == TokenType
1084or child.getType() == DateTimeType
1085or child.getType() == DateType
1086):
1087s1 = "%s showIndent(outfile, level)\n" % fill
1088outfile.write(s1)
1089s1 = "%s outfile.write('%s=%%s,\\n' %% quote_python(self.get%s()))\n" % (
1090fill,
1091mappedName,
1092name.capitalize(),
1093)
1094outfile.write(s1)
1095elif (
1096child.getType() in IntegerType
1097or child.getType() == BooleanType
1098or child.getType() == PositiveIntegerType
1099or child.getType() == NonPositiveIntegerType
1100or child.getType() == NegativeIntegerType
1101or child.getType() == NonNegativeIntegerType
1102):
1103s1 = "%s showIndent(outfile, level)\n" % fill
1104outfile.write(s1)
1105s1 = "%s outfile.write('%s=%%d,\\n' %% self.get%s())\n" % (
1106fill,
1107mappedName,
1108name.capitalize(),
1109)
1110outfile.write(s1)
1111elif child.getType() == FloatType or child.getType() == DecimalType:
1112s1 = "%s showIndent(outfile, level)\n" % fill
1113outfile.write(s1)
1114s1 = "%s outfile.write('%s=%%f,\\n' %% self.get%s())\n" % (
1115fill,
1116mappedName,
1117name.capitalize(),
1118)
1119outfile.write(s1)
1120elif child.getType() == DoubleType:
1121s1 = "%s showIndent(outfile, level)\n" % fill
1122outfile.write(s1)
1123s1 = "%s outfile.write('%s=%%e,\\n' %% self.get%s())\n" % (
1124fill,
1125name,
1126name.capitalize(),
1127)
1128outfile.write(s1)
1129else:
1130s1 = "%s if self.%s:\n" % (fill, name)
1131outfile.write(s1)
1132s1 = "%s showIndent(outfile, level)\n" % fill
1133outfile.write(s1)
1134s1 = "%s outfile.write('%s=%s(\\n')\n" % (
1135fill,
1136name,
1137child.getType(),
1138)
1139outfile.write(s1)
1140if name == child.getType():
1141s1 = "%s self.%s.exportLiteral(outfile, level)\n" % (fill, name)
1142else:
1143s1 = "%s self.%s.exportLiteral(outfile, level, name_='%s')\n" % (
1144fill,
1145name,
1146name,
1147)
1148outfile.write(s1)
1149s1 = "%s showIndent(outfile, level)\n" % fill
1150outfile.write(s1)
1151s1 = "%s outfile.write('),\\n')\n" % (fill,)
1152outfile.write(s1)
1153
1154
1155def generateExportLiteralFn_2(outfile, child, name, fill):
1156if (
1157child.getType() in StringType
1158or child.getType() == TokenType
1159or child.getType() == DateTimeType
1160or child.getType() == DateType
1161):
1162s1 = "%s showIndent(outfile, level)\n" % fill
1163outfile.write(s1)
1164s1 = "%s outfile.write('%%s,\\n' %% quote_python(%s))\n" % (fill, name)
1165outfile.write(s1)
1166elif (
1167child.getType() in IntegerType
1168or child.getType() == BooleanType
1169or child.getType() == PositiveIntegerType
1170or child.getType() == NonPositiveIntegerType
1171or child.getType() == NegativeIntegerType
1172or child.getType() == NonNegativeIntegerType
1173):
1174s1 = "%s showIndent(outfile, level)\n" % fill
1175outfile.write(s1)
1176s1 = "%s outfile.write('%%d,\\n' %% %s)\n" % (fill, name)
1177outfile.write(s1)
1178elif child.getType() == FloatType or child.getType() == DecimalType:
1179s1 = "%s showIndent(outfile, level)\n" % fill
1180outfile.write(s1)
1181s1 = "%s outfile.write('%%f,\\n' %% %s)\n" % (fill, name)
1182outfile.write(s1)
1183elif child.getType() == DoubleType:
1184s1 = "%s showIndent(outfile, level)\n" % fill
1185outfile.write(s1)
1186s1 = "%s outfile.write('%%e,\\n' %% %s)\n" % (fill, name)
1187outfile.write(s1)
1188else:
1189s1 = "%s showIndent(outfile, level)\n" % fill
1190outfile.write(s1)
1191s1 = "%s outfile.write('%s(\\n')\n" % (
1192fill,
1193cleanupName(child.getType()),
1194)
1195outfile.write(s1)
1196if name == child.getType():
1197s1 = "%s %s.exportLiteral(outfile, level)\n" % (
1198fill,
1199child.getType(),
1200)
1201else:
1202s1 = "%s %s.exportLiteral(outfile, level, name_='%s')\n" % (
1203fill,
1204name,
1205name,
1206)
1207outfile.write(s1)
1208s1 = "%s showIndent(outfile, level)\n" % fill
1209outfile.write(s1)
1210s1 = "%s outfile.write('),\\n')\n" % (fill,)
1211outfile.write(s1)
1212
1213
1214def generateExportLiteralFn(outfile, prefix, element):
1215base = element.getBase()
1216s1 = " def exportLiteral(self, outfile, level, name_='%s'):\n" % element.getName()
1217outfile.write(s1)
1218s1 = " level += 1\n"
1219outfile.write(s1)
1220s1 = " self.exportLiteralAttributes(outfile, level, name_)\n"
1221outfile.write(s1)
1222s1 = " self.exportLiteralChildren(outfile, level, name_)\n"
1223outfile.write(s1)
1224s1 = " def exportLiteralAttributes(self, outfile, level, name_):\n"
1225outfile.write(s1)
1226count = 0
1227attrDefs = element.getAttributeDefs()
1228for key in attrDefs:
1229attrDef = attrDefs[key]
1230count += 1
1231name = attrDef.getName()
1232cleanName = cleanupName(name)
1233capName = cleanName.capitalize()
1234mappedName = mapName(cleanName)
1235s1 = " showIndent(outfile, level)\n"
1236outfile.write(s1)
1237## ipshell('(generateExportLiteral) -- Entering ipshell.\\nHit Ctrl-D to exit')
1238stringType = 0
1239data_type = attrDef.getData_type()
1240if data_type.find("string") >= 0:
1241stringType = 1
1242else:
1243stringType = 1
1244if stringType:
1245s1 = " outfile.write('%s = \"%%s\",\\n' %% (self.get%s(),))\n" % (
1246mappedName,
1247capName,
1248)
1249else:
1250s1 = " outfile.write('%s = %%s,\\n' %% (self.get%s(),))\n" % (
1251mappedName,
1252capName,
1253)
1254outfile.write(s1)
1255
1256if element.getAnyAttribute():
1257count += 1
1258s1 = " for name, value in self.anyAttributes_.items():\n"
1259outfile.write(s1)
1260s1 = " showIndent(outfile, level)\n"
1261outfile.write(s1)
1262s1 = " outfile.write('%s = \"%s\",\\n' % (name, value,))\n"
1263outfile.write(s1)
1264if count == 0:
1265s1 = " pass\n"
1266outfile.write(s1)
1267if base:
1268s1 = " %s.exportLiteralAttributes(self, outfile, level, name_)\n" % (base,)
1269outfile.write(s1)
1270s1 = " def exportLiteralChildren(self, outfile, level, name_):\n"
1271outfile.write(s1)
1272for child in element.getChildren():
1273name = child.getName()
1274name = cleanupName(name)
1275# unmappedName = child.getUnmappedCleanName()
1276# cleanName = cleanupName(name)
1277# mappedName = mapName(cleanName)
1278if element.isMixed():
1279s1 = " showIndent(outfile, level)\n"
1280outfile.write(s1)
1281s1 = " outfile.write('content_ = [\\n')\n"
1282outfile.write(s1)
1283s1 = " for item_ in self.content_:\n"
1284outfile.write(s1)
1285s1 = " item_.exportLiteral(outfile, level, name_)\n"
1286outfile.write(s1)
1287s1 = " showIndent(outfile, level)\n"
1288outfile.write(s1)
1289s1 = " outfile.write('],\\n')\n"
1290outfile.write(s1)
1291else:
1292if child.getMaxOccurs() > 1:
1293s1 = " showIndent(outfile, level)\n"
1294outfile.write(s1)
1295s1 = " outfile.write('%s=[\\n')\n" % name
1296outfile.write(s1)
1297s1 = " level += 1\n"
1298outfile.write(s1)
1299s1 = " for %s in self.%s:\n" % (name, name)
1300outfile.write(s1)
1301generateExportLiteralFn_2(outfile, child, name, " ")
1302s1 = " level -= 1\n"
1303outfile.write(s1)
1304s1 = " showIndent(outfile, level)\n"
1305outfile.write(s1)
1306s1 = " outfile.write('],\\n')\n"
1307outfile.write(s1)
1308else:
1309generateExportLiteralFn_1(outfile, child, name, "")
1310if len(element.getChildren()) == 0:
1311s1 = " showIndent(outfile, level)\n"
1312outfile.write(s1)
1313s1 = " outfile.write('valueOf_ = \"%s\",\\n' % (self.valueOf_,))\n"
1314outfile.write(s1)
1315if base:
1316s1 = " %s.exportLiteralChildren(self, outfile, level, name_)\n" % (base,)
1317outfile.write(s1)
1318# s1 = " level -= 1\n"
1319# outfile.write(s1)
1320
1321
1322#
1323# Generate build method.
1324#
1325
1326
1327def generateBuildAttributes(outfile, element, hasAttributes):
1328attrDefs = element.getAttributeDefs()
1329for key in attrDefs:
1330attrDef = attrDefs[key]
1331hasAttributes += 1
1332name = attrDef.getName()
1333cleanName = cleanupName(name)
1334mappedName = mapName(cleanName)
1335atype = attrDef.getData_type()
1336if (
1337atype in IntegerType
1338or atype == PositiveIntegerType
1339or atype == NonPositiveIntegerType
1340or atype == NegativeIntegerType
1341or atype == NonNegativeIntegerType
1342):
1343s1 = " if attrs.get('%s'):\n" % name
1344outfile.write(s1)
1345s1 = " try:\n"
1346outfile.write(s1)
1347s1 = " self.%s = int(attrs.get('%s').value)\n" % (
1348mappedName,
1349name,
1350)
1351outfile.write(s1)
1352s1 = " except ValueError:\n"
1353outfile.write(s1)
1354s1 = " raise ValueError('Bad integer attribute (%s)')\n" % (name,)
1355outfile.write(s1)
1356if atype == PositiveIntegerType:
1357s1 = " if self.%s <= 0:\n" % mappedName
1358outfile.write(s1)
1359s1 = " raise ValueError('Invalid PositiveInteger (%s)')\n" % name
1360outfile.write(s1)
1361elif atype == NonPositiveIntegerType:
1362s1 = " if self.%s > 0:\n" % mappedName
1363outfile.write(s1)
1364s1 = " raise ValueError('Invalid NonPositiveInteger (%s)')\n" % name
1365outfile.write(s1)
1366elif atype == NegativeIntegerType:
1367s1 = " if self.%s >= 0:\n" % mappedName
1368outfile.write(s1)
1369s1 = " raise ValueError('Invalid NegativeInteger (%s)')\n" % name
1370outfile.write(s1)
1371elif atype == NonNegativeIntegerType:
1372s1 = " if self.%s < 0:\n" % mappedName
1373outfile.write(s1)
1374s1 = " raise ValueError('Invalid NonNegativeInteger (%s)')\n" % name
1375outfile.write(s1)
1376elif atype == BooleanType:
1377s1 = " if attrs.get('%s'):\n" % (name,)
1378outfile.write(s1)
1379s1 = " if attrs.get('%s').value in ('true', '1'):\n" % (name,)
1380outfile.write(s1)
1381s1 = " self.%s = 1\n" % (mappedName,)
1382outfile.write(s1)
1383s1 = " elif attrs.get('%s').value in ('false', '0'):\n" % (name,)
1384outfile.write(s1)
1385s1 = " self.%s = 0\n" % (mappedName,)
1386outfile.write(s1)
1387s1 = " else:\n"
1388outfile.write(s1)
1389s1 = " raise ValueError('Bad boolean attribute (%s)')\n" % (name,)
1390outfile.write(s1)
1391elif atype == FloatType or atype == DoubleType or atype == DecimalType:
1392s1 = " if attrs.get('%s'):\n" % (name,)
1393outfile.write(s1)
1394s1 = " try:\n"
1395outfile.write(s1)
1396s1 = " self.%s = float(attrs.get('%s').value)\n" % (
1397mappedName,
1398name,
1399)
1400outfile.write(s1)
1401s1 = " except:\n"
1402outfile.write(s1)
1403s1 = " raise ValueError('Bad float/double attribute (%s)')\n" % (name,)
1404outfile.write(s1)
1405elif atype == TokenType:
1406s1 = " if attrs.get('%s'):\n" % (name,)
1407outfile.write(s1)
1408s1 = " self.%s = attrs.get('%s').value\n" % (
1409mappedName,
1410name,
1411)
1412outfile.write(s1)
1413s1 = " self.%s = ' '.join(self.%s.split())\n" % (
1414mappedName,
1415mappedName,
1416)
1417outfile.write(s1)
1418else:
1419# Assume attr['type'] in StringType or attr['type'] == DateTimeType:
1420s1 = " if attrs.get('%s'):\n" % (name,)
1421outfile.write(s1)
1422s1 = " self.%s = attrs.get('%s').value\n" % (
1423mappedName,
1424name,
1425)
1426outfile.write(s1)
1427if element.getAnyAttribute():
1428s1 = " self.anyAttributes_ = {}\n"
1429outfile.write(s1)
1430s1 = " for name, value in attrs.items():\n"
1431outfile.write(s1)
1432s1List = [" if"]
1433firstTime = 1
1434for key in attrDefs:
1435if firstTime:
1436s1List.append(' name != "%s"' % key)
1437firstTime = 0
1438else:
1439s1List.append(' and name != "%s"' % key)
1440s1List.append(":\n")
1441s1 = "".join(s1List)
1442outfile.write(s1)
1443s1 = " self.anyAttributes_[name] = value\n"
1444outfile.write(s1)
1445return hasAttributes
1446
1447
1448def generateBuildMixed_1(outfile, prefix, child, headChild, keyword, delayed):
1449global DelayedElements, DelayedElements_subclass
1450nestedElements = 1
1451origName = child.getName()
1452name = child.getCleanName()
1453headName = cleanupName(headChild.getName())
1454childType = child.getType()
1455if (
1456childType in StringType
1457or childType == TokenType
1458or childType == DateTimeType
1459or childType == DateType
1460):
1461s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1462outfile.write(s1)
1463s1 = " nodeName_ == '%s':\n" % origName
1464outfile.write(s1)
1465s1 = " value_ = []\n"
1466outfile.write(s1)
1467s1 = " for text_ in child_.childNodes:\n"
1468outfile.write(s1)
1469s1 = " value_.append(text_.nodeValue)\n"
1470outfile.write(s1)
1471s1 = " valuestr_ = ''.join(value_)\n"
1472outfile.write(s1)
1473if childType == TokenType:
1474s1 = " valuestr_ = ' '.join(valuestr_.split())\n"
1475outfile.write(s1)
1476s1 = " obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
1477outfile.write(s1)
1478s1 = " MixedContainer.TypeString, '%s', valuestr_)\n" % origName
1479outfile.write(s1)
1480s1 = " self.content_.append(obj_)\n"
1481outfile.write(s1)
1482elif (
1483childType in IntegerType
1484or childType == PositiveIntegerType
1485or childType == NonPositiveIntegerType
1486or childType == NegativeIntegerType
1487or childType == NonNegativeIntegerType
1488):
1489s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1490outfile.write(s1)
1491s1 = " nodeName_ == '%s':\n" % origName
1492outfile.write(s1)
1493s1 = " if child_.firstChild:\n"
1494outfile.write(s1)
1495s1 = " sval_ = child_.firstChild.nodeValue\n"
1496outfile.write(s1)
1497s1 = " try:\n"
1498outfile.write(s1)
1499s1 = " ival_ = int(sval_)\n"
1500outfile.write(s1)
1501s1 = " except ValueError:\n"
1502outfile.write(s1)
1503s1 = " raise ValueError('requires integer -- %s' % child_.toxml())\n"
1504outfile.write(s1)
1505if childType == PositiveIntegerType:
1506s1 = " if ival_ <= 0:\n"
1507outfile.write(s1)
1508s1 = " raise ValueError('Invalid positiveInteger (%s)' % child_.toxml()))\n"
1509outfile.write(s1)
1510if childType == NonPositiveIntegerType:
1511s1 = " if ival_ > 0:\n"
1512outfile.write(s1)
1513s1 = " raise ValueError('Invalid nonPositiveInteger (%s)' % child_.toxml()))\n"
1514outfile.write(s1)
1515if childType == NegativeIntegerType:
1516s1 = " if ival_ >= 0:\n"
1517outfile.write(s1)
1518s1 = " raise ValueError('Invalid negativeInteger (%s)' % child_.toxml()))\n"
1519outfile.write(s1)
1520if childType == NonNegativeIntegerType:
1521s1 = " if ival_ < 0:\n"
1522outfile.write(s1)
1523s1 = " raise ValueError('Invalid nonNegativeInteger (%s)' % child_.toxml()))\n"
1524outfile.write(s1)
1525s1 = " else:\n"
1526outfile.write(s1)
1527s1 = " ival_ = -1\n"
1528outfile.write(s1)
1529s1 = " obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
1530outfile.write(s1)
1531s1 = " MixedContainer.TypeInteger, '%s', ival_)\n" % origName
1532outfile.write(s1)
1533s1 = " self.content_.append(obj_)\n"
1534outfile.write(s1)
1535elif childType == BooleanType:
1536s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1537outfile.write(s1)
1538s1 = " nodeName_ == '%s':\n" % origName
1539outfile.write(s1)
1540s1 = " if child_.firstChild:\n"
1541outfile.write(s1)
1542s1 = " sval_ = child_.firstChild.nodeValue\n"
1543outfile.write(s1)
1544s1 = " if sval_ in ('true', '1'):\n"
1545outfile.write(s1)
1546s1 = " ival_ = 1\n"
1547outfile.write(s1)
1548s1 = " elif sval_ in ('false', '0'):\n"
1549outfile.write(s1)
1550s1 = " ival_ = 0\n"
1551outfile.write(s1)
1552s1 = " else:\n"
1553outfile.write(s1)
1554s1 = " raise ValueError('requires boolean -- %s' % child_.toxml())\n"
1555outfile.write(s1)
1556s1 = " obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
1557outfile.write(s1)
1558s1 = " MixedContainer.TypeInteger, '%s', ival_)\n" % origName
1559outfile.write(s1)
1560s1 = " self.content_.append(obj_)\n"
1561outfile.write(s1)
1562elif childType == FloatType or childType == DoubleType or childType == DecimalType:
1563s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1564outfile.write(s1)
1565s1 = " nodeName_ == '%s':\n" % origName
1566outfile.write(s1)
1567s1 = " if child_.firstChild:\n"
1568outfile.write(s1)
1569s1 = " sval_ = child_.firstChild.nodeValue\n"
1570outfile.write(s1)
1571s1 = " try:\n"
1572outfile.write(s1)
1573s1 = " fval_ = float(sval_)\n"
1574outfile.write(s1)
1575s1 = " except ValueError:\n"
1576outfile.write(s1)
1577s1 = " raise ValueError('requires float (or double) -- %s' % child_.toxml())\n"
1578outfile.write(s1)
1579s1 = " obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
1580outfile.write(s1)
1581s1 = " MixedContainer.TypeFloat, '%s', fval_)\n" % origName
1582outfile.write(s1)
1583s1 = " self.content_.append(obj_)\n"
1584outfile.write(s1)
1585else:
1586# Perhaps it's a complexType that is defined right here.
1587# Generate (later) a class for the nested types.
1588if not delayed and not child in DelayedElements:
1589DelayedElements.append(child)
1590DelayedElements_subclass.append(child)
1591s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1592outfile.write(s1)
1593s1 = " nodeName_ == '%s':\n" % origName
1594outfile.write(s1)
1595s1 = " childobj_ = %s%s.factory()\n" % (
1596prefix,
1597cleanupName(mapName(childType)),
1598)
1599outfile.write(s1)
1600s1 = " childobj_.build(child_)\n"
1601outfile.write(s1)
1602s1 = " obj_ = self.mixedclass_(MixedContainer.CategoryComplex,\n"
1603outfile.write(s1)
1604s1 = " MixedContainer.TypeNone, '%s', childobj_)\n" % origName
1605outfile.write(s1)
1606s1 = " self.content_.append(obj_)\n"
1607outfile.write(s1)
1608
1609
1610def generateBuildMixed(outfile, prefix, element, keyword, delayed, hasChildren):
1611for child in element.getChildren():
1612generateBuildMixed_1(outfile, prefix, child, child, keyword, delayed)
1613hasChildren += 1
1614keyword = "elif"
1615# Does this element have a substitutionGroup?
1616# If so generate a clause for each element in the substitutionGroup.
1617if child.getName() in SubstitutionGroups:
1618for memberName in SubstitutionGroups[child.getName()]:
1619if memberName in ElementDict:
1620member = ElementDict[memberName]
1621generateBuildMixed_1(outfile, prefix, member, child, keyword, delayed)
1622s1 = " %s child_.nodeType == Node.TEXT_NODE:\n" % keyword
1623outfile.write(s1)
1624s1 = " obj_ = self.mixedclass_(MixedContainer.CategoryText,\n"
1625outfile.write(s1)
1626s1 = " MixedContainer.TypeNone, '', child_.nodeValue)\n"
1627outfile.write(s1)
1628s1 = " self.content_.append(obj_)\n"
1629outfile.write(s1)
1630## base = element.getBase()
1631## if base and base in ElementDict:
1632## parent = ElementDict[base]
1633## hasChildren = generateBuildMixed(outfile, prefix, parent, keyword, delayed, hasChildren)
1634return hasChildren
1635
1636
1637def generateBuildStandard_1(outfile, prefix, child, headChild, keyword, delayed):
1638global DelayedElements, DelayedElements_subclass
1639origName = child.getName()
1640name = cleanupName(child.getName())
1641mappedName = mapName(name)
1642headName = cleanupName(headChild.getName())
1643attrCount = len(child.getAttributeDefs())
1644# dbgprint(1, '(gbs) name: %s type: %s complex: %s id: %s' % \
1645# (child.getName(), child.getType(), child.isComplex(), id(child), ))
1646childType = child.getType()
1647if attrCount == 0 and (
1648childType in StringType
1649or childType == TokenType
1650or childType == DateTimeType
1651or childType == DateType
1652):
1653s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1654outfile.write(s1)
1655s1 = " nodeName_ == '%s':\n" % origName
1656outfile.write(s1)
1657s1 = " %s_ = ''\n" % name
1658outfile.write(s1)
1659s1 = " for text__content_ in child_.childNodes:\n"
1660outfile.write(s1)
1661s1 = " %s_ += text__content_.nodeValue\n" % name
1662outfile.write(s1)
1663if childType == TokenType:
1664s1 = " %s_ = ' '.join(%s_.split())\n" % (
1665name,
1666name,
1667)
1668outfile.write(s1)
1669if child.getMaxOccurs() > 1:
1670s1 = " self.%s.append(%s_)\n" % (
1671mappedName,
1672name,
1673)
1674outfile.write(s1)
1675else:
1676s1 = " self.%s = %s_\n" % (
1677mappedName,
1678name,
1679)
1680outfile.write(s1)
1681elif (
1682childType in IntegerType
1683or childType == PositiveIntegerType
1684or childType == NonPositiveIntegerType
1685or childType == NegativeIntegerType
1686or childType == NonNegativeIntegerType
1687):
1688s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1689outfile.write(s1)
1690s1 = " nodeName_ == '%s':\n" % origName
1691outfile.write(s1)
1692s1 = " if child_.firstChild:\n"
1693outfile.write(s1)
1694s1 = " sval_ = child_.firstChild.nodeValue\n"
1695outfile.write(s1)
1696s1 = " try:\n"
1697outfile.write(s1)
1698s1 = " ival_ = int(sval_)\n"
1699outfile.write(s1)
1700s1 = " except ValueError:\n"
1701outfile.write(s1)
1702s1 = " raise ValueError('requires integer -- %s' % child_.toxml())\n"
1703outfile.write(s1)
1704if childType == PositiveIntegerType:
1705s1 = " if ival_ <= 0:\n"
1706outfile.write(s1)
1707s1 = " raise ValueError('requires positiveInteger -- %s' % child_.toxml())\n"
1708outfile.write(s1)
1709elif childType == NonPositiveIntegerType:
1710s1 = " if ival_ > 0:\n"
1711outfile.write(s1)
1712s1 = " raise ValueError('requires nonPositiveInteger -- %s' % child_.toxml())\n"
1713outfile.write(s1)
1714elif childType == NegativeIntegerType:
1715s1 = " if ival_ >= 0:\n"
1716outfile.write(s1)
1717s1 = " raise ValueError('requires negativeInteger -- %s' % child_.toxml())\n"
1718outfile.write(s1)
1719elif childType == NonNegativeIntegerType:
1720s1 = " if ival_ < 0:\n"
1721outfile.write(s1)
1722s1 = " raise ValueError('requires nonNegativeInteger -- %s' % child_.toxml())\n"
1723outfile.write(s1)
1724if child.getMaxOccurs() > 1:
1725s1 = " self.%s.append(ival_)\n" % (mappedName,)
1726outfile.write(s1)
1727else:
1728s1 = " self.%s = ival_\n" % (mappedName,)
1729outfile.write(s1)
1730elif childType == BooleanType:
1731s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1732outfile.write(s1)
1733s1 = " nodeName_ == '%s':\n" % origName
1734outfile.write(s1)
1735s1 = " if child_.firstChild:\n"
1736outfile.write(s1)
1737s1 = " sval_ = child_.firstChild.nodeValue\n"
1738outfile.write(s1)
1739s1 = " if sval_ in ('true', '1'):\n"
1740outfile.write(s1)
1741s1 = " ival_ = 1\n"
1742outfile.write(s1)
1743s1 = " elif sval_ in ('false', '0'):\n"
1744outfile.write(s1)
1745s1 = " ival_ = 0\n"
1746outfile.write(s1)
1747s1 = " else:\n"
1748outfile.write(s1)
1749s1 = " raise ValueError('requires boolean -- %s' % child_.toxml())\n"
1750outfile.write(s1)
1751if child.getMaxOccurs() > 1:
1752s1 = " self.%s.append(ival_)\n" % (mappedName,)
1753outfile.write(s1)
1754else:
1755s1 = " self.%s = ival_\n" % (mappedName,)
1756outfile.write(s1)
1757elif childType == FloatType or childType == DoubleType or childType == DecimalType:
1758s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1759outfile.write(s1)
1760s1 = " nodeName_ == '%s':\n" % origName
1761outfile.write(s1)
1762s1 = " if child_.firstChild:\n"
1763outfile.write(s1)
1764s1 = " sval_ = child_.firstChild.nodeValue\n"
1765outfile.write(s1)
1766s1 = " try:\n"
1767outfile.write(s1)
1768s1 = " fval_ = float(sval_)\n"
1769outfile.write(s1)
1770s1 = " except ValueError:\n"
1771outfile.write(s1)
1772s1 = " raise ValueError('requires float (or double) -- %s' % child_.toxml())\n"
1773outfile.write(s1)
1774if child.getMaxOccurs() > 1:
1775s1 = " self.%s.append(fval_)\n" % (mappedName,)
1776outfile.write(s1)
1777else:
1778s1 = " self.%s = fval_\n" % (mappedName,)
1779outfile.write(s1)
1780else:
1781# Perhaps it's a complexType that is defined right here.
1782# Generate (later) a class for the nested types.
1783if not delayed and not child in DelayedElements:
1784DelayedElements.append(child)
1785DelayedElements_subclass.append(child)
1786s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1787outfile.write(s1)
1788s1 = " nodeName_ == '%s':\n" % origName
1789outfile.write(s1)
1790s1 = " obj_ = %s%s.factory()\n" % (
1791prefix,
1792cleanupName(mapName(childType)),
1793)
1794outfile.write(s1)
1795s1 = " obj_.build(child_)\n"
1796outfile.write(s1)
1797if headChild.getMaxOccurs() > 1:
1798s1 = " self.%s.append(obj_)\n" % headName
1799outfile.write(s1)
1800else:
1801s1 = " self.set%s(obj_)\n" % headName.capitalize()
1802outfile.write(s1)
1803
1804
1805def generateBuildStandard(outfile, prefix, element, keyword, delayed, hasChildren):
1806for child in element.getChildren():
1807# dbgprint(1, '(generateBuildStandard) %s type: %s' % (child.getName(), child.getType(),))
1808generateBuildStandard_1(outfile, prefix, child, child, keyword, delayed)
1809hasChildren += 1
1810keyword = "elif"
1811# Does this element have a substitutionGroup?
1812# If so generate a clause for each element in the substitutionGroup.
1813childName = child.getName()
1814if childName in SubstitutionGroups:
1815# dbgprint(1, '(BldStd) found: %s in %s' % (childName, SubstitutionGroups))
1816for memberName in SubstitutionGroups[childName]:
1817memberName = cleanupName(memberName)
1818if memberName in ElementDict:
1819member = ElementDict[memberName]
1820# dbgprint(1, '(BldStd) found subst: %s/%s' % (memberName, member))
1821generateBuildStandard_1(outfile, prefix, member, child, keyword, delayed)
1822return hasChildren
1823
1824
1825def generateBuildFn(outfile, prefix, element, delayed):
1826base = element.getBase()
1827outfile.write(" def build(self, node_):\n")
1828outfile.write(" attrs = node_.attributes\n")
1829outfile.write(" self.buildAttributes(attrs)\n")
1830## if len(element.getChildren()) > 0:
1831outfile.write(" for child_ in node_.childNodes:\n")
1832outfile.write(" nodeName_ = child_.nodeName.split(':')[-1]\n")
1833outfile.write(" self.buildChildren(child_, nodeName_)\n")
1834outfile.write(" def buildAttributes(self, attrs):\n")
1835hasAttributes = generateBuildAttributes(outfile, element, 0)
1836if base:
1837hasAttributes += 1
1838s1 = " %s.buildAttributes(self, attrs)\n" % (base,)
1839outfile.write(s1)
1840if hasAttributes == 0:
1841outfile.write(" pass\n")
1842outfile.write(" def buildChildren(self, child_, nodeName_):\n")
1843keyword = "if"
1844hasChildren = 0
1845if element.isMixed():
1846hasChildren = generateBuildMixed(outfile, prefix, element, keyword, delayed, hasChildren)
1847else: # not element.isMixed()
1848hasChildren = generateBuildStandard(outfile, prefix, element, keyword, delayed, hasChildren)
1849if hasChildren == 0:
1850s1 = " self.valueOf_ = ''\n"
1851outfile.write(s1)
1852s1 = " for child in child_.childNodes:\n"
1853outfile.write(s1)
1854s1 = " if child.nodeType == Node.TEXT_NODE:\n"
1855outfile.write(s1)
1856s1 = " self.valueOf_ += child.nodeValue\n"
1857outfile.write(s1)
1858if base and base in ElementDict:
1859parent = ElementDict[base]
1860if len(parent.getChildren()) > 0:
1861s1 = " %s.buildChildren(self, child_, nodeName_)\n" % (base,)
1862outfile.write(s1)
1863
1864
1865def countElementChildren(element, count):
1866count += len(element.getChildren())
1867base = element.getBase()
1868if base and base in ElementDict:
1869parent = ElementDict[base]
1870countElementChildren(parent, count)
1871return count
1872
1873
1874def buildCtorArgs_multilevel(element):
1875content = []
1876add = content.append
1877buildCtorArgs_multilevel_aux(add, element)
1878count = countElementChildren(element, 0)
1879if count == 0:
1880add(", valueOf_=''")
1881if element.isMixed():
1882add(", mixedclass_=None")
1883add(", content_=None")
1884s1 = "".join(content)
1885return s1
1886
1887
1888def buildCtorArgs_multilevel_aux(add, element):
1889buildCtorArgs_aux(add, element)
1890base = element.getBase()
1891if base and base in ElementDict:
1892parent = ElementDict[base]
1893buildCtorArgs_multilevel_aux(add, parent)
1894
1895
1896def buildCtorArgs_1_level(element):
1897content = []
1898add = content.append
1899buildCtorArgs_aux(add, element)
1900count = countElementChildren(element, 0)
1901if count == 0:
1902add(", valueOf_=''")
1903s1 = "".join(content)
1904return s1
1905
1906
1907def buildCtorArgs_aux(add, element):
1908attrDefs = element.getAttributeDefs()
1909for key in attrDefs:
1910attrDef = attrDefs[key]
1911name = attrDef.getName()
1912mappedName = name.replace(":", "_")
1913mappedName = cleanupName(mapName(mappedName))
1914try:
1915atype = attrDef.getData_type()
1916except KeyError:
1917atype = StringType
1918if atype in StringType or atype == TokenType or atype == DateTimeType or atype == DateType:
1919add(", %s=''" % mappedName)
1920elif atype in IntegerType:
1921add(", %s=-1" % mappedName)
1922elif atype == PositiveIntegerType:
1923add(", %s=1" % mappedName)
1924elif atype == NonPositiveIntegerType:
1925add(", %s=0" % mappedName)
1926elif atype == NegativeIntegerType:
1927add(", %s=-1" % mappedName)
1928elif atype == NonNegativeIntegerType:
1929add(", %s=0" % mappedName)
1930elif atype == BooleanType:
1931add(", %s=0" % mappedName)
1932elif atype == FloatType or atype == DoubleType or atype == DecimalType:
1933add(", %s=0.0" % mappedName)
1934else:
1935add(", %s=None" % mappedName)
1936nestedElements = 0
1937for child in element.getChildren():
1938nestedElements = 1
1939if child.getMaxOccurs() > 1:
1940add(", %s=None" % child.getCleanName())
1941else:
1942childType = child.getType()
1943if (
1944childType in StringType
1945or childType == TokenType
1946or childType == DateTimeType
1947or childType == DateType
1948):
1949add(", %s=''" % child.getCleanName())
1950elif childType in IntegerType:
1951add(", %s=-1" % child.getCleanName())
1952elif childType == PositiveIntegerType:
1953add(", %s=1" % child.getCleanName())
1954elif childType == NonPositiveIntegerType:
1955add(", %s=0" % child.getCleanName())
1956elif childType == NegativeIntegerType:
1957add(", %s=-1" % child.getCleanName())
1958elif childType == NonNegativeIntegerType:
1959add(", %s=0" % child.getCleanName())
1960elif childType == BooleanType:
1961add(", %s=0" % child.getCleanName())
1962elif childType == FloatType or childType == DoubleType or childType == DecimalType:
1963add(", %s=0.0" % child.getCleanName())
1964else:
1965add(", %s=None" % child.getCleanName())
1966
1967
1968MixedCtorInitializers = """\
1969if mixedclass_ is None:
1970self.mixedclass_ = MixedContainer
1971else:
1972self.mixedclass_ = mixedclass_
1973if content_ is None:
1974self.content_ = []
1975else:
1976self.content_ = content_
1977"""
1978
1979
1980def generateCtor(outfile, element):
1981s2 = buildCtorArgs_multilevel(element)
1982s1 = " def __init__(self%s):\n" % s2
1983outfile.write(s1)
1984base = element.getBase()
1985if base and base in ElementDict:
1986parent = ElementDict[base]
1987s2 = buildCtorParams(parent)
1988s1 = " %s.__init__(self%s)\n" % (
1989base,
1990s2,
1991)
1992outfile.write(s1)
1993attrDefs = element.getAttributeDefs()
1994for key in attrDefs:
1995attrDef = attrDefs[key]
1996mappedName = cleanupName(attrDef.getName())
1997mappedName = mapName(mappedName)
1998s1 = " self.%s = %s\n" % (mappedName, mappedName)
1999outfile.write(s1)
2000member = 1
2001# Generate member initializers in ctor.
2002if element.isMixed():
2003outfile.write(MixedCtorInitializers)
2004else:
2005member = 0
2006nestedElements = 0
2007for child in element.getChildren():
2008name = cleanupName(child.getCleanName())
2009if child.getMaxOccurs() > 1:
2010s1 = " if %s is None:\n" % (name,)
2011outfile.write(s1)
2012s1 = " self.%s = []\n" % (name,)
2013outfile.write(s1)
2014s1 = " else:\n"
2015outfile.write(s1)
2016s1 = " self.%s = %s\n" % (name, name)
2017outfile.write(s1)
2018else:
2019s1 = " self.%s = %s\n" % (name, name)
2020outfile.write(s1)
2021member = 1
2022nestedElements = 1
2023if not nestedElements:
2024s1 = " self.valueOf_ = valueOf_\n"
2025outfile.write(s1)
2026member = 1
2027if element.getAnyAttribute():
2028s1 = " self.anyAttributes_ = {}\n"
2029outfile.write(s1)
2030member = 1
2031if not member:
2032outfile.write(" pass\n")
2033
2034
2035# Generate get/set/add member functions.
2036def generateGettersAndSetters(outfile, element):
2037nestedElements = 0
2038for child in element.getChildren():
2039nestedElements = 1
2040name = cleanupName(child.getCleanName())
2041unmappedName = cleanupName(child.getName())
2042capName = unmappedName.capitalize()
2043s1 = " def get%s(self): return self.%s\n" % (capName, name)
2044outfile.write(s1)
2045s1 = " def set%s(self, %s): self.%s = %s\n" % (capName, name, name, name)
2046outfile.write(s1)
2047if child.getMaxOccurs() > 1:
2048s1 = " def add%s(self, value): self.%s.append(value)\n" % (capName, name)
2049outfile.write(s1)
2050s1 = " def insert%s(self, index, value): self.%s[index] = value\n" % (
2051capName,
2052name,
2053)
2054outfile.write(s1)
2055if GenerateProperties:
2056s1 = " %sProp = property(get%s, set%s)\n" % (
2057unmappedName,
2058capName,
2059capName,
2060)
2061outfile.write(s1)
2062attrDefs = element.getAttributeDefs()
2063for key in attrDefs:
2064attrDef = attrDefs[key]
2065name = cleanupName(attrDef.getName().replace(":", "_"))
2066mappedName = mapName(name)
2067capName = mappedName.capitalize()
2068s1 = " def get%s(self): return self.%s\n" % (name.capitalize(), mappedName)
2069outfile.write(s1)
2070#
2071# What? An attribute cannot occur multiple times on the same
2072# element. No attribute is a list of values. Right?
2073## if element.getMaxOccurs() > 1:
2074## s1 = ' def add%s(self, %s): self.%s.append(%s)\n' % \
2075## (capName, mappedName, mappedName, mappedName)
2076## outfile.write(s1)
2077## s1 = ' def set%s(self, %s, index): self.%s[index] = %s\n' % \
2078## (name.capitalize(), mappedName, mappedName, mappedName)
2079## outfile.write(s1)
2080## else:
2081s1 = " def set%s(self, %s): self.%s = %s\n" % (
2082name.capitalize(),
2083mappedName,
2084mappedName,
2085mappedName,
2086)
2087outfile.write(s1)
2088if GenerateProperties:
2089s1 = " %sProp = property(get%s, set%s)\n" % (
2090mappedName,
2091capName,
2092capName,
2093)
2094outfile.write(s1)
2095if not nestedElements:
2096s1 = " def getValueOf_(self): return self.valueOf_\n"
2097outfile.write(s1)
2098s1 = " def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_\n"
2099outfile.write(s1)
2100if element.getAnyAttribute():
2101s1 = " def getAnyAttributes_(self): return self.anyAttributes_\n"
2102outfile.write(s1)
2103s1 = " def setAnyAttributes_(self, anyAttributes_): self.anyAttributes_ = anyAttributes_\n"
2104outfile.write(s1)
2105
2106
2107def generateClasses(outfile, prefix, element, delayed):
2108base = element.getBase()
2109wrt = outfile.write
2110if (not element.getChildren()) and (not element.getAttributeDefs()):
2111return
2112# If this element is an extension (has a base) and the base has
2113# not been generated, then postpone it.
2114if base and base in ElementDict:
2115parent = ElementDict[base]
2116parentName = parent.getName()
2117if parentName not in AlreadyGenerated:
2118PostponedExtensions.append(element)
2119return
2120if element.getName() in AlreadyGenerated:
2121return
2122AlreadyGenerated.append(element.getName())
2123if element.getMixedExtensionError():
2124print(
2125"*** Element %s extension chain contains mixed and non-mixed content. Not generated."
2126% (element.getName(),)
2127)
2128return
2129ElementsForSubclasses.append(element)
2130name = element.getCleanName()
2131if GenerateProperties:
2132if base:
2133s1 = "class %s%s(object, %s):\n" % (prefix, name, base)
2134else:
2135s1 = "class %s%s(object):\n" % (prefix, name)
2136else:
2137if base:
2138s1 = "class %s%s(%s):\n" % (prefix, name, base)
2139else:
2140s1 = "class %s%s:\n" % (prefix, name)
2141wrt(s1)
2142wrt(" subclass = None\n")
2143generateCtor(outfile, element)
2144wrt(" def factory(*args_, **kwargs_):\n")
2145wrt(" if %s%s.subclass:\n" % (prefix, name))
2146wrt(" return %s%s.subclass(*args_, **kwargs_)\n" % (prefix, name))
2147wrt(" else:\n")
2148wrt(" return %s%s(*args_, **kwargs_)\n" % (prefix, name))
2149wrt(" factory = staticmethod(factory)\n")
2150generateGettersAndSetters(outfile, element)
2151generateExportFn(outfile, prefix, element)
2152generateExportLiteralFn(outfile, prefix, element)
2153generateBuildFn(outfile, prefix, element, delayed)
2154wrt("# end class %s\n" % name)
2155wrt("\n\n")
2156
2157
2158#
2159# Generate the SAX handler class for SAX parsing.
2160#
2161
2162SAX_STARTELEMENT_1 = """\
2163def startElement(self, name, attrs):
2164done = 0
2165if name == '%s':
2166obj = %s.factory()
2167stackObj = SaxStackElement('%s', obj)
2168self.stack.append(stackObj)
2169done = 1
2170"""
2171
2172SAX_STARTELEMENT_2 = """\
2173stackObj = SaxStackElement('%s', obj)
2174self.stack.append(stackObj)
2175done = 1
2176"""
2177
2178SAX_STARTELEMENT_3 = """\
2179stackObj = SaxStackElement('%s', None)
2180self.stack.append(stackObj)
2181done = 1
2182"""
2183
2184SAX_STARTELEMENT_4 = """\
2185if not done:
2186self.reportError('"%s" element not allowed here.' % name)
2187"""
2188
2189SAX_ATTR_INTEGER = """\
2190val = attrs.get('%s', None)
2191if val is not None:
2192try:
2193obj.set%s(int(val))
2194except:
2195self.reportError('"%s" attribute must be integer')
2196"""
2197
2198SAX_ATTR_BOOLEAN = """\
2199val = attrs.get('%s', None)
2200if val is not None:
2201if val in ('true', '1'):
2202obj.set%s(1)
2203elif val in ('false', '0'):
2204obj.set%s(0)
2205else:
2206self.reportError('"%s" attribute must be boolean ("true", "1", "false", "0")')
2207"""
2208
2209SAX_ATTR_FLOAT = """\
2210val = attrs.get('%s', None)
2211if val is not None:
2212try:
2213obj.set%s(float(val))
2214except:
2215self.reportError('"%s" attribute must be float')
2216"""
2217
2218SAX_ATTR_STRING = """\
2219val = attrs.get('%s', None)
2220if val is not None:
2221obj.set%s(val)
2222"""
2223
2224
2225def getClassName(element):
2226name = element.getCleanName()
2227return name
2228
2229
2230def generateSaxAttributes(wrt, element):
2231attrDefs = element.getAttributeDefs()
2232for key in attrDefs:
2233attrDef = attrDefs[key]
2234name = attrDef.getName()
2235atype = attrDef.getData_type()
2236if atype in IntegerType:
2237s1 = SAX_ATTR_INTEGER % (name, name.capitalize(), name)
2238wrt(s1)
2239## s1 = " if attrs.get('%s'):\n" % name
2240## wrt(s1)
2241## s1 = ' try:\n'
2242## wrt(s1)
2243## s1 = " self.%s = int(attrs.get('%s').value)\n" % \
2244## (name, name)
2245## wrt(s1)
2246## s1 = ' except ValueError:\n'
2247## wrt(s1)
2248## s1 = " raise ValueError('Bad integer')\n"
2249## wrt(s1)
2250elif atype == BooleanType:
2251s1 = SAX_ATTR_BOOLEAN % (name, name.capitalize(), name.capitalize(), name)
2252wrt(s1)
2253## wrt(s1)
2254## s1 = " if attrs.get('%s'):\n" % name
2255## wrt(s1)
2256## s1 = " if attrs.get('%s').value in ('true', '1'):\n" % \
2257## name
2258## wrt(s1)
2259## s1 = " self.%s = 1\n" % \
2260## name
2261## wrt(s1)
2262## s1 = " elif attrs.get('%s').value in ('false', '0'):\n" % \
2263## name
2264## wrt(s1)
2265## s1 = " self.%s = 0\n" % \
2266## name
2267## wrt(s1)
2268## s1 = ' else:\n'
2269## wrt(s1)
2270## s1 = " raise ValueError('Bad boolean')\n"
2271## wrt(s1)
2272elif atype == FloatType or atype == DoubleType or atype == DecimalType:
2273s1 = SAX_ATTR_FLOAT % (name, name.capitalize(), name)
2274wrt(s1)
2275## s1 = " if attrs.get('%s'):\n" % name
2276## wrt(s1)
2277## s1 = ' try:\n'
2278## wrt(s1)
2279## s1 = " self.%s = float(attrs.get('%s').value)\n" % \
2280## (name, name)
2281## wrt(s1)
2282## s1 = ' except:\n'
2283## wrt(s1)
2284## s1 = " raise ValueError('Bad float/double')\n"
2285## wrt(s1)
2286else:
2287# Assume attr['type'] in StringType or attr['type'] == DateTimeType:
2288s1 = SAX_ATTR_STRING % (name, name.capitalize())
2289wrt(s1)
2290
2291
2292## s1 = " if attrs.get('%s'):\n" % name
2293## wrt(s1)
2294## s1 = " self.%s = attrs.get('%s').value\n" % (name, name)
2295## wrt(s1)
2296
2297
2298def generateSAXStartElement_1(wrt, element):
2299origName = element.getName()
2300typeName = cleanupName(mapName(element.getRawType()))
2301className = element.getCleanName()
2302s1 = " elif name == '%s':\n" % origName
2303wrt(s1)
2304if element.isComplex():
2305s1 = " obj = %s.factory()\n" % cleanupName(typeName)
2306wrt(s1)
2307element1 = SaxElementDict[element.getCleanName()]
2308generateSaxAttributes(wrt, element1)
2309if element.isComplex():
2310s1 = SAX_STARTELEMENT_2 % className
2311else:
2312s1 = SAX_STARTELEMENT_3 % className
2313wrt(s1)
2314
2315
2316def generateSAXStartElement(outfile, root, elementList):
2317wrt = outfile.write
2318name = root.getChildren()[0].getName()
2319s1 = SAX_STARTELEMENT_1 % (name, name, name)
2320wrt(s1)
2321for element, parent in elementList:
2322generateSAXStartElement_1(wrt, element)
2323s1 = SAX_STARTELEMENT_4
2324wrt(s1)
2325wrt("\n")
2326
2327
2328SAX_ENDELEMENT_1 = """\
2329if name == '%s':
2330if len(self.stack) == 1:
2331self.root = self.stack[-1].obj
2332self.stack.pop()
2333done = 1
2334"""
2335
2336SAX_ENDELEMENT_2 = """\
2337elif name == '%s':
2338if len(self.stack) >= 2:
2339self.stack[-2].obj.%s%s(self.stack[-1].obj)
2340self.stack.pop()
2341done = 1
2342"""
2343
2344SAX_ENDELEMENT_3 = """\
2345elif name == '%s':
2346if len(self.stack) >= 2:
2347content = self.stack[-1].content
2348%s self.stack[-2].obj.%s%s(content)
2349self.stack.pop()
2350done = 1
2351"""
2352
2353SAX_ENDELEMENT_INT = """\
2354if content:
2355try:
2356content = int(content)
2357except:
2358self.reportError('"%s" must be integer -- content: %%s' %% content)
2359else:
2360content = -1
2361"""
2362
2363SAX_ENDELEMENT_FLOAT = """\
2364if content:
2365try:
2366content = float(content)
2367except:
2368self.reportError('"%s" must be float -- content: %%s' %% content)
2369else:
2370content = -1
2371"""
2372
2373SAX_ENDELEMENT_BOOLEAN = """\
2374if content and content in ('true', '1'):
2375content = 1
2376else:
2377content = 0
2378"""
2379
2380SAX_ENDELEMENT_4 = """\
2381if not done:
2382self.reportError('"%s" element not allowed here.' % name)
2383"""
2384
2385
2386def generateParentCheck(parent):
2387s1 = "self.stack[-2].name == '%s'" % getClassName(parent)
2388return s1
2389
2390
2391## strList = []
2392## for parent in parentList:
2393## strList.append("self.stack[-2].name == '%s'" % \
2394## parent.getName())
2395## s1 = ' or '.join(strList)
2396## if len(parentList) > 1:
2397## s1 = '(%s)' % s1
2398## return s1
2399
2400
2401def generateSAXEndElement(outfile, root, elementList):
2402wrt = outfile.write
2403s1 = " def endElement(self, name):\n"
2404wrt(s1)
2405s1 = " done = 0\n"
2406wrt(s1)
2407name = root.getChildren()[0].getName()
2408s1 = SAX_ENDELEMENT_1 % (name,)
2409wrt(s1)
2410for element, parent in elementList:
2411# s2 = generateParentCheck(parent)
2412name = element.getName()
2413capName = element.getUnmappedCleanName().capitalize()
2414if element.isComplex():
2415if element.getMaxOccurs() > 1:
2416s1 = SAX_ENDELEMENT_2 % (name, "add", capName)
2417else:
2418s1 = SAX_ENDELEMENT_2 % (name, "set", capName)
2419else:
2420etype = element.getType()
2421if etype in IntegerType:
2422s3 = SAX_ENDELEMENT_INT % name
2423elif etype == FloatType or etype == DoubleType or etype == DecimalType:
2424s3 = SAX_ENDELEMENT_FLOAT % name
2425elif etype == BooleanType:
2426s3 = SAX_ENDELEMENT_BOOLEAN
2427else:
2428s3 = ""
2429if element.getMaxOccurs() > 1:
2430s1 = SAX_ENDELEMENT_3 % (name, s3, "add", capName)
2431else:
2432s1 = SAX_ENDELEMENT_3 % (name, s3, "set", capName)
2433wrt(s1)
2434s1 = SAX_ENDELEMENT_4
2435wrt(s1)
2436wrt("\n")
2437
2438
2439SAX_HEADER = """\
2440from xml.sax import handler, make_parser
2441
2442class SaxStackElement:
2443def __init__(self, name='', obj=None):
2444self.name = name
2445self.obj = obj
2446self.content = ''
2447
2448#
2449# SAX handler
2450#
2451class Sax%sHandler(handler.ContentHandler):
2452def __init__(self):
2453self.stack = []
2454self.root = None
2455
2456def getRoot(self):
2457return self.root
2458
2459def setDocumentLocator(self, locator):
2460self.locator = locator
2461
2462def showError(self, msg):
2463print('*** (showError):', msg)
2464sys.exit(-1)
2465
2466"""
2467
2468SAX_FOOTER = """\
2469def characters(self, chrs, start, end):
2470if len(self.stack) > 0:
2471self.stack[-1].content += chrs[start:end]
2472
2473def reportError(self, mesg):
2474locator = self.locator
2475sys.stderr.write('Doc: %s Line: %d Column: %d\\n' % \\
2476(locator.getSystemId(), locator.getLineNumber(),
2477locator.getColumnNumber() + 1))
2478sys.stderr.write(mesg)
2479sys.stderr.write('\\n')
2480sys.exit(-1)
2481#raise RuntimeError
2482
2483"""
2484
2485
2486##def produceAllElements(element, parent):
2487## if element.getType() in StringType or \
2488## element.getType() in IntegerType or \
2489## element.getType() == DecimalType or \
2490## element.getType() == FloatType or \
2491## element.getType() == DoubleType or \
2492## element.getType() == BooleanType or \
2493## len(element.getChildren()) != 0:
2494## yield (element, parent)
2495## for child in element.getChildren():
2496## for element1, parent1 in produceAllElements(child, element):
2497## yield (element1, parent1)
2498
2499
2500#
2501# This version of produceAllElements does not use 'yield' and is,
2502# therefore, usable with older versions of Python.
2503def produceAllElements_nogen(element, parent, collection):
2504collection.append((element, parent))
2505for child in element.getChildren():
2506produceAllElements_nogen(child, element, collection)
2507
2508
2509def generateSAXHndlr(outfile, root):
2510firstElement = root.getChildren()[0]
2511name = firstElement.getName()
2512s1 = SAX_HEADER % cleanupName(name.capitalize())
2513outfile.write(s1)
2514elementList = []
2515collection = []
2516produceAllElements_nogen(root, None, collection)
2517for element, parent in collection:
2518if element == root:
2519continue
2520elementList.append((element, parent))
2521## print '(gsh) element: %s/%s/%d parent: %s/%s/%d' % \
2522## (element.getUnmappedCleanName(), element.getType(), id(element),
2523## #(element.getName(), element.getType(), id(element),
2524## parent.getName(), parent.getType(), id(parent))
2525## if parent.getName() == 'booster':
2526## ipshell('at booster -- Entering ipshell.\\nHit Ctrl-D to exit')
2527## if element in elementDict:
2528## elementDict[element].append(parent)
2529## else:
2530## elementDict[element] = [parent]
2531elementList1 = []
2532alreadySeen = []
2533for element, parent in elementList:
2534if parent == root:
2535continue
2536if element.getName() in alreadySeen:
2537continue
2538alreadySeen.append(element.getName())
2539elementList1.append((element, parent))
2540## print '+' * 20
2541## for element, parent in elementList1:
2542## print '(gsh) element: %s/%s/%d parent: %s/%s/%d' % \
2543## (element.getUnmappedCleanName(), element.getType(), id(element),
2544## #(element.getName(), element.getType(), id(element),
2545## parent.getName(), parent.getType(), id(parent))
2546generateSAXStartElement(outfile, root, elementList1)
2547generateSAXEndElement(outfile, root, elementList1)
2548s1 = SAX_FOOTER
2549outfile.write(s1)
2550
2551
2552def collect(element, elements):
2553if element.getName() != "root":
2554elements.append(element)
2555for child in element.getChildren():
2556collect(child, elements)
2557
2558
2559TEMPLATE_HEADER = """\
2560#!/usr/bin/env python3
2561
2562#
2563# Generated %s by generateDS.py.
2564# Update it with: python generateDS.py -o generateModel_Module.py generateMetaModel_Module.xsd
2565#
2566# WARNING! All changes made in this file will be lost!
2567#
2568
2569
2570import sys
2571import getopt
2572from xml.dom import minidom
2573from xml.dom import Node
2574
2575#
2576# If you have installed IPython you can uncomment and use the following.
2577# IPython is available from http://ipython.scipy.org/.
2578#
2579
2580## from IPython.Shell import IPShellEmbed
2581## args = ''
2582## ipshell = IPShellEmbed(args,
2583## banner = 'Dropping into IPython',
2584## exit_msg = 'Leaving Interpreter, back to program.')
2585
2586# Then use the following line where and when you want to drop into the
2587# IPython shell:
2588# ipshell('<some message> -- Entering ipshell.\\nHit Ctrl-D to exit')
2589
2590#
2591# Support/utility functions.
2592#
2593
2594def showIndent(outfile, level):
2595for idx in range(level):
2596outfile.write(' ')
2597
2598def quote_xml(inStr):
2599s1 = inStr
2600s1 = s1.replace('&', '&')
2601s1 = s1.replace('<', '<')
2602s1 = s1.replace('"', '"')
2603return s1
2604
2605def quote_python(inStr):
2606s1 = inStr
2607if s1.find("'") == -1:
2608if s1.find('\\n') == -1:
2609return "'%%s'" %% s1
2610else:
2611return "'''%%s'''" %% s1
2612else:
2613if s1.find('"') != -1:
2614s1 = s1.replace('"', '\\\\"')
2615if s1.find('\\n') == -1:
2616return '"%%s"' %% s1
2617else:
2618return '\"\"\"%%s\"\"\"' %% s1
2619
2620
2621class MixedContainer:
2622# Constants for category:
2623CategoryNone = 0
2624CategoryText = 1
2625CategorySimple = 2
2626CategoryComplex = 3
2627# Constants for content_type:
2628TypeNone = 0
2629TypeText = 1
2630TypeString = 2
2631TypeInteger = 3
2632TypeFloat = 4
2633TypeDecimal = 5
2634TypeDouble = 6
2635TypeBoolean = 7
2636def __init__(self, category, content_type, name, value):
2637self.category = category
2638self.content_type = content_type
2639self.name = name
2640self.value = value
2641def getCategory(self):
2642return self.category
2643def getContenttype(self, content_type):
2644return self.content_type
2645def getValue(self):
2646return self.value
2647def getName(self):
2648return self.name
2649def export(self, outfile, level, name):
2650if self.category == MixedContainer.CategoryText:
2651outfile.write(self.value)
2652elif self.category == MixedContainer.CategorySimple:
2653self.exportSimple(outfile, level, name)
2654else: # category == MixedContainer.CategoryComplex
2655self.value.export(outfile, level, name)
2656def exportSimple(self, outfile, level, name):
2657if self.content_type == MixedContainer.TypeString:
2658outfile.write('<%%s>%%s</%%s>' %% (self.name, self.value, self.name))
2659elif self.content_type == MixedContainer.TypeInteger or \\
2660self.content_type == MixedContainer.TypeBoolean:
2661outfile.write('<%%s>%%d</%%s>' %% (self.name, self.value, self.name))
2662elif self.content_type == MixedContainer.TypeFloat or \\
2663self.content_type == MixedContainer.TypeDecimal:
2664outfile.write('<%%s>%%f</%%s>' %% (self.name, self.value, self.name))
2665elif self.content_type == MixedContainer.TypeDouble:
2666outfile.write('<%%s>%%g</%%s>' %% (self.name, self.value, self.name))
2667def exportLiteral(self, outfile, level, name):
2668if self.category == MixedContainer.CategoryText:
2669showIndent(outfile, level)
2670outfile.write('MixedContainer(%%d, %%d, "%%s", "%%s"),\\n' %% \\
2671(self.category, self.content_type, self.name, self.value))
2672elif self.category == MixedContainer.CategorySimple:
2673showIndent(outfile, level)
2674outfile.write('MixedContainer(%%d, %%d, "%%s", "%%s"),\\n' %% \\
2675(self.category, self.content_type, self.name, self.value))
2676else: # category == MixedContainer.CategoryComplex
2677showIndent(outfile, level)
2678outfile.write('MixedContainer(%%d, %%d, "%%s",\\n' %% \\
2679(self.category, self.content_type, self.name,))
2680self.value.exportLiteral(outfile, level + 1)
2681showIndent(outfile, level)
2682outfile.write(')\\n')
2683
2684
2685#
2686# Data representation classes.
2687#
2688
2689"""
2690
2691# Fool (and straighten out) the syntax highlighting.
2692# DUMMY = '''
2693
2694
2695def generateHeader(outfile, prefix):
2696s1 = TEMPLATE_HEADER % time.ctime()
2697outfile.write(s1)
2698
2699
2700TEMPLATE_MAIN = """\
2701USAGE_TEXT = \"\"\"
2702Usage: python <%(prefix)sParser>.py [ -s ] <in_xml_file>
2703Options:
2704-s Use the SAX parser, not the minidom parser.
2705\"\"\"
2706
2707def usage():
2708print(USAGE_TEXT)
2709sys.exit(-1)
2710
2711
2712#
2713# SAX handler used to determine the top level element.
2714#
2715class SaxSelectorHandler(handler.ContentHandler):
2716def __init__(self):
2717self.topElementName = None
2718def getTopElementName(self):
2719return self.topElementName
2720def startElement(self, name, attrs):
2721self.topElementName = name
2722raise StopIteration
2723
2724
2725def parseSelect(inFileName):
2726infile = open(inFileName, 'r')
2727topElementName = None
2728parser = make_parser()
2729documentHandler = SaxSelectorHandler()
2730parser.setContentHandler(documentHandler)
2731try:
2732try:
2733parser.parse(infile)
2734except StopIteration:
2735topElementName = documentHandler.getTopElementName()
2736if topElementName is None:
2737raise RuntimeError('no top level element')
2738topElementName = topElementName.replace('-', '_').replace(':', '_')
2739if topElementName not in globals():
2740raise RuntimeError('no class for top element: %%s' %% topElementName)
2741topElement = globals()[topElementName]
2742infile.seek(0)
2743doc = minidom.parse(infile)
2744finally:
2745infile.close()
2746rootNode = doc.childNodes[0]
2747rootObj = topElement.factory()
2748rootObj.build(rootNode)
2749# Enable Python to collect the space used by the DOM.
2750doc = None
2751sys.stdout.write('<?xml version="1.0" ?>\\n')
2752rootObj.export(sys.stdout, 0)
2753return rootObj
2754
2755
2756def saxParse(inFileName):
2757parser = make_parser()
2758documentHandler = Sax%(cap_name)sHandler()
2759parser.setDocumentHandler(documentHandler)
2760parser.parse('file:%%s' %% inFileName)
2761root = documentHandler.getRoot()
2762sys.stdout.write('<?xml version="1.0" ?>\\n')
2763root.export(sys.stdout, 0)
2764return root
2765
2766
2767def saxParseString(inString):
2768parser = make_parser()
2769documentHandler = Sax%(cap_name)sHandler()
2770parser.setDocumentHandler(documentHandler)
2771parser.feed(inString)
2772parser.close()
2773rootObj = documentHandler.getRoot()
2774#sys.stdout.write('<?xml version="1.0" ?>\\n')
2775#rootObj.export(sys.stdout, 0)
2776return rootObj
2777
2778
2779def parse(inFileName):
2780doc = minidom.parse(inFileName)
2781rootNode = doc.documentElement
2782rootObj = %(prefix)s%(root)s.factory()
2783rootObj.build(rootNode)
2784# Enable Python to collect the space used by the DOM.
2785doc = None
2786sys.stdout.write('<?xml version="1.0" ?>\\n')
2787rootObj.export(sys.stdout, 0, name_="%(name)s")
2788return rootObj
2789
2790
2791def parseString(inString):
2792doc = minidom.parseString(inString)
2793rootNode = doc.documentElement
2794rootObj = %(prefix)s%(root)s.factory()
2795rootObj.build(rootNode)
2796# Enable Python to collect the space used by the DOM.
2797doc = None
2798sys.stdout.write('<?xml version="1.0" ?>\\n')
2799rootObj.export(sys.stdout, 0, name_="%(name)s")
2800return rootObj
2801
2802
2803def parseLiteral(inFileName):
2804doc = minidom.parse(inFileName)
2805rootNode = doc.documentElement
2806rootObj = %(prefix)s%(root)s.factory()
2807rootObj.build(rootNode)
2808# Enable Python to collect the space used by the DOM.
2809doc = None
2810sys.stdout.write('from %(module_name)s import *\\n\\n')
2811sys.stdout.write('rootObj = %(name)s(\\n')
2812rootObj.exportLiteral(sys.stdout, 0, name_="%(name)s")
2813sys.stdout.write(')\\n')
2814return rootObj
2815
2816
2817def main():
2818args = sys.argv[1:]
2819if len(args) == 2 and args[0] == '-s':
2820saxParse(args[1])
2821elif len(args) == 1:
2822parse(args[0])
2823else:
2824usage()
2825
2826
2827if __name__ == '__main__':
2828main()
2829#import pdb
2830#pdb.run('main()')
2831
2832"""
2833
2834
2835# Fool (and straighten out) the syntax highlighting.
2836# DUMMY = '''
2837
2838
2839def generateMain(outfile, prefix, root):
2840name = root.getChildren()[0].getName()
2841elType = cleanupName(root.getChildren()[0].getType())
2842if RootElement:
2843rootElement = RootElement
2844else:
2845rootElement = elType
2846params = {
2847"prefix": prefix,
2848"cap_name": cleanupName(name.capitalize()),
2849"name": cleanupName(name),
2850"module_name": os.path.splitext(os.path.basename(outfile.name))[0],
2851"root": rootElement,
2852}
2853s1 = TEMPLATE_MAIN % params
2854outfile.write(s1)
2855
2856
2857def buildCtorParams(element):
2858content = []
2859add = content.append
2860if element.isMixed():
2861add(", mixedclass_")
2862add(", content_")
2863else:
2864buildCtorParams_aux(add, element)
2865s1 = "".join(content)
2866return s1
2867
2868
2869def buildCtorParams_aux(add, element):
2870attrDefs = element.getAttributeDefs()
2871for key in attrDefs:
2872attrDef = attrDefs[key]
2873name = attrDef.getName()
2874cleanName = cleanupName(mapName(name))
2875add(", %s" % cleanName)
2876for child in element.getChildren():
2877add(", %s" % child.getCleanName())
2878base = element.getBase()
2879if base and base in ElementDict:
2880parent = ElementDict[base]
2881buildCtorParams_aux(add, parent)
2882
2883
2884def get_class_behavior_args(classBehavior):
2885argList = []
2886args = classBehavior.getArgs()
2887args = args.getArg()
2888# print '(get_class_behavior_args) args:', args
2889for arg in args:
2890argList.append(arg.getName())
2891argString = ", ".join(argList)
2892return argString
2893
2894
2895#
2896# Retrieve the implementation body via an HTTP request to a
2897# URL formed from the concatenation of the baseImplUrl and the
2898# implUrl.
2899# An alternative implementation of get_impl_body() that also
2900# looks in the local file system is commented out below.
2901#
2902def get_impl_body(classBehavior, baseImplUrl, implUrl):
2903impl = " pass\n"
2904if implUrl:
2905if baseImplUrl:
2906implUrl = "%s%s" % (baseImplUrl, implUrl)
2907try:
2908implFile = urlopen(implUrl)
2909impl = implFile.read()
2910implFile.close()
2911except HTTPError:
2912print("*** Implementation at %s not found." % implUrl)
2913return impl
2914
2915
2916###
2917### This alternative implementation of get_impl_body() tries the URL
2918### via http first, then, if that fails, looks in a directory on
2919### the local file system (baseImplUrl) for a file (implUrl)
2920### containing the implementation body.
2921###
2922##def get_impl_body(classBehavior, baseImplUrl, implUrl):
2923## impl = ' pass\n'
2924## if implUrl:
2925## trylocal = 0
2926## if baseImplUrl:
2927## implUrl = '%s%s' % (baseImplUrl, implUrl)
2928## try:
2929## implFile = urlopen(implUrl)
2930## impl = implFile.read()
2931## implFile.close()
2932## except:
2933## trylocal = 1
2934## if trylocal:
2935## try:
2936## implFile = open(implUrl)
2937## impl = implFile.read()
2938## implFile.close()
2939## except:
2940## print ('*** Implementation at %s not found.' % implUrl)
2941## return impl
2942
2943
2944def generateClassBehaviors(wrt, classBehaviors, baseImplUrl):
2945for classBehavior in classBehaviors:
2946behaviorName = classBehavior.getName()
2947#
2948# Generate the core behavior.
2949argString = get_class_behavior_args(classBehavior)
2950if argString:
2951wrt(" def %s(self, %s, *args):\n" % (behaviorName, argString))
2952else:
2953wrt(" def %s(self, *args):\n" % (behaviorName,))
2954implUrl = classBehavior.getImpl_url()
2955impl = get_impl_body(classBehavior, baseImplUrl, implUrl)
2956wrt(impl)
2957wrt("\n")
2958#
2959# Generate the ancillaries for this behavior.
2960ancillaries = classBehavior.getAncillaries()
2961if ancillaries:
2962ancillaries = ancillaries.getAncillary()
2963if ancillaries:
2964for ancillary in ancillaries:
2965argString = get_class_behavior_args(ancillary)
2966if argString:
2967wrt(" def %s(self, %s, *args):\n" % (ancillary.getName(), argString))
2968else:
2969wrt(" def %s(self, *args):\n" % (ancillary.getName(),))
2970implUrl = ancillary.getImpl_url()
2971impl = get_impl_body(classBehavior, baseImplUrl, implUrl)
2972wrt(impl)
2973wrt("\n")
2974#
2975# Generate the wrapper method that calls the ancillaries and
2976# the core behavior.
2977argString = get_class_behavior_args(classBehavior)
2978if argString:
2979wrt(" def %s_wrapper(self, %s, *args):\n" % (behaviorName, argString))
2980else:
2981wrt(" def %s_wrapper(self, *args):\n" % (behaviorName,))
2982if ancillaries:
2983for ancillary in ancillaries:
2984role = ancillary.getRole()
2985if role == "DBC-precondition":
2986wrt(" if not self.%s(*args)\n" % (ancillary.getName(),))
2987wrt(" return False\n")
2988if argString:
2989wrt(" result = self.%s(%s, *args)\n" % (behaviorName, argString))
2990else:
2991wrt(" result = self.%s(*args)\n" % (behaviorName,))
2992if ancillaries:
2993for ancillary in ancillaries:
2994role = ancillary.getRole()
2995if role == "DBC-postcondition":
2996wrt(" if not self.%s(*args)\n" % (ancillary.getName(),))
2997wrt(" return False\n")
2998wrt(" return result\n")
2999wrt("\n")
3000
3001
3002def generateSubclass(outfile, element, prefix, xmlbehavior, behaviors, baseUrl):
3003wrt = outfile.write
3004if not element.isComplex():
3005return
3006if (not element.getChildren()) and (not element.getAttributeDefs()):
3007return
3008if element.getName() in AlreadyGenerated_subclass:
3009return
3010AlreadyGenerated_subclass.append(element.getName())
3011name = element.getCleanName()
3012wrt("class %s%s%s(supermod.%s):\n" % (prefix, name, SubclassSuffix, name))
3013s1 = buildCtorArgs_multilevel(element)
3014wrt(" def __init__(self%s):\n" % s1)
3015s1 = buildCtorParams(element)
3016wrt(" supermod.%s%s.__init__(self%s)\n" % (prefix, name, s1))
3017if xmlbehavior and behaviors:
3018wrt("\n")
3019wrt(" #\n")
3020wrt(" # XMLBehaviors\n")
3021wrt(" #\n")
3022# Get a list of behaviors for this class/subclass.
3023classDictionary = behaviors.get_class_dictionary()
3024if name in classDictionary:
3025classBehaviors = classDictionary[name]
3026else:
3027classBehaviors = None
3028if classBehaviors:
3029generateClassBehaviors(wrt, classBehaviors, baseUrl)
3030wrt("supermod.%s.subclass = %s%s\n" % (name, name, SubclassSuffix))
3031wrt("# end class %s%s%s\n" % (prefix, name, SubclassSuffix))
3032wrt("\n\n")
3033
3034
3035TEMPLATE_SUBCLASS_HEADER = """\
3036#!/usr/bin/env python
3037
3038#
3039# Generated %s by generateDS.py.
3040#
3041
3042import sys
3043from xml.dom import minidom
3044from xml.sax import handler, make_parser
3045
3046import %s as supermod
3047
3048"""
3049
3050TEMPLATE_SUBCLASS_FOOTER = """\
3051
3052#
3053# SAX handler used to determine the top level element.
3054#
3055class SaxSelectorHandler(handler.ContentHandler):
3056def __init__(self):
3057self.topElementName = None
3058def getTopElementName(self):
3059return self.topElementName
3060def startElement(self, name, attrs):
3061self.topElementName = name
3062raise StopIteration
3063
3064
3065def parseSelect(inFileName):
3066infile = open(inFileName, 'r')
3067topElementName = None
3068parser = make_parser()
3069documentHandler = SaxSelectorHandler()
3070parser.setContentHandler(documentHandler)
3071try:
3072try:
3073parser.parse(infile)
3074except StopIteration:
3075topElementName = documentHandler.getTopElementName()
3076if topElementName is None:
3077raise RuntimeError, 'no top level element'
3078topElementName = topElementName.replace('-', '_').replace(':', '_')
3079if topElementName not in supermod.__dict__:
3080raise RuntimeError, 'no class for top element: %%s' %% topElementName
3081topElement = supermod.__dict__[topElementName]
3082infile.seek(0)
3083doc = minidom.parse(infile)
3084finally:
3085infile.close()
3086rootNode = doc.childNodes[0]
3087rootObj = topElement.factory()
3088rootObj.build(rootNode)
3089# Enable Python to collect the space used by the DOM.
3090doc = None
3091sys.stdout.write('<?xml version="1.0" ?>\\n')
3092rootObj.export(sys.stdout, 0)
3093return rootObj
3094
3095
3096def saxParse(inFileName):
3097parser = make_parser()
3098documentHandler = supermod.Sax%(cap_name)sHandler()
3099parser.setDocumentHandler(documentHandler)
3100parser.parse('file:%%s' %% inFileName)
3101rootObj = documentHandler.getRoot()
3102#sys.stdout.write('<?xml version="1.0" ?>\\n')
3103#rootObj.export(sys.stdout, 0)
3104return rootObj
3105
3106
3107def saxParseString(inString):
3108parser = make_parser()
3109documentHandler = supermod.SaxContentHandler()
3110parser.setDocumentHandler(documentHandler)
3111parser.feed(inString)
3112parser.close()
3113rootObj = documentHandler.getRoot()
3114#sys.stdout.write('<?xml version="1.0" ?>\\n')
3115#rootObj.export(sys.stdout, 0)
3116return rootObj
3117
3118
3119def parse(inFilename):
3120doc = minidom.parse(inFilename)
3121rootNode = doc.documentElement
3122rootObj = supermod.%(root)s.factory()
3123rootObj.build(rootNode)
3124# Enable Python to collect the space used by the DOM.
3125doc = None
3126sys.stdout.write('<?xml version="1.0" ?>\\n')
3127rootObj.export(sys.stdout, 0, name_="%(name)s")
3128doc = None
3129return rootObj
3130
3131
3132def parseString(inString):
3133doc = minidom.parseString(inString)
3134rootNode = doc.documentElement
3135rootObj = supermod.%(root)s.factory()
3136rootObj.build(rootNode)
3137# Enable Python to collect the space used by the DOM.
3138doc = None
3139sys.stdout.write('<?xml version="1.0" ?>\\n')
3140rootObj.export(sys.stdout, 0, name_="%(name)s")
3141return rootObj
3142
3143
3144def parseLiteral(inFilename):
3145doc = minidom.parse(inFilename)
3146rootNode = doc.documentElement
3147rootObj = supermod.%(root)s.factory()
3148rootObj.build(rootNode)
3149# Enable Python to collect the space used by the DOM.
3150doc = None
3151sys.stdout.write('from %(super)s import *\\n\\n')
3152sys.stdout.write('rootObj = %(name)s(\\n')
3153rootObj.exportLiteral(sys.stdout, 0, name_="%(name)s")
3154sys.stdout.write(')\\n')
3155return rootObj
3156
3157
3158USAGE_TEXT = \"\"\"
3159Usage: python ???.py <infilename>
3160\"\"\"
3161
3162def usage():
3163print(USAGE_TEXT)
3164sys.exit(-1)
3165
3166
3167def main():
3168args = sys.argv[1:]
3169if len(args) != 1:
3170usage()
3171infilename = args[0]
3172root = parse(infilename)
3173
3174
3175if __name__ == '__main__':
3176main()
3177#import pdb
3178#pdb.run('main()')
3179
3180
3181"""
3182
3183##def isMember(item, lst):
3184## for item1 in lst:
3185## if item == item1:
3186## print '(isMember) found name: %s' % item
3187## return True
3188## print '(isMember) did not find name: %s' % item
3189## return False
3190
3191
3192def generateSubclasses(root, subclassFilename, behaviorFilename, prefix, superModule="xxx"):
3193name = root.getChildren()[0].getName()
3194subclassFile = makeFile(subclassFilename)
3195if subclassFile:
3196# Read in the XMLBehavior file.
3197xmlbehavior = None
3198behaviors = None
3199baseUrl = None
3200if behaviorFilename:
3201try:
3202# Add the correct working directory to the path so that
3203# we use the user/developers local copy.
3204sys.path.insert(0, ".")
3205import xmlbehavior_sub as xmlbehavior
3206except ImportError:
3207print("*** You have requested generation of extended methods.")
3208print("*** But, no xmlbehavior module is available.")
3209print("*** Generation of extended behavior methods is omitted.")
3210if xmlbehavior:
3211behaviors = xmlbehavior.parse(behaviorFilename)
3212behaviors.make_class_dictionary(cleanupName)
3213baseUrl = behaviors.getBase_impl_url()
3214wrt = subclassFile.write
3215wrt(TEMPLATE_SUBCLASS_HEADER % (time.ctime(), superModule))
3216for element in ElementsForSubclasses:
3217generateSubclass(subclassFile, element, prefix, xmlbehavior, behaviors, baseUrl)
3218## processed = []
3219## for element in root.getChildren():
3220## name = element.getCleanName()
3221## if name not in processed:
3222## processed.append(name)
3223## generateSubclass(subclassFile, element, prefix, xmlbehavior, behaviors, baseUrl)
3224## while 1:
3225## if len(DelayedElements_subclass) <= 0:
3226## break
3227## element = DelayedElements_subclass.pop()
3228## name = element.getCleanName()
3229## if name not in processed:
3230## processed.append(name)
3231## generateSubclass(subclassFile, element, prefix, xmlbehavior, behaviors, baseUrl)
3232name = root.getChildren()[0].getName()
3233elType = cleanupName(root.getChildren()[0].getType())
3234if RootElement:
3235rootElement = RootElement
3236else:
3237rootElement = elType
3238params = {
3239"cap_name": cleanupName(name).capitalize(),
3240"name": cleanupName(name),
3241"module_name": os.path.splitext(os.path.basename(subclassFilename))[0],
3242"root": rootElement,
3243"super": superModule,
3244}
3245wrt(TEMPLATE_SUBCLASS_FOOTER % params)
3246subclassFile.close()
3247
3248
3249def generateFromTree(outfile, prefix, elements, processed):
3250for element in elements:
3251name = element.getCleanName()
3252if 1: # if name not in processed:
3253processed.append(name)
3254generateClasses(outfile, prefix, element, 0)
3255children = element.getChildren()
3256if children:
3257generateFromTree(outfile, prefix, element.getChildren(), processed)
3258
3259
3260def generate(outfileName, subclassFilename, behaviorFilename, prefix, root, superModule):
3261global DelayedElements, DelayedElements_subclass
3262# Create an output file.
3263# Note that even if the user does not request an output file,
3264# we still need to go through the process of generating classes
3265# because it produces data structures needed during generation of
3266# subclasses.
3267outfile = None
3268if outfileName:
3269outfile = makeFile(outfileName)
3270if not outfile:
3271outfile = os.tmpfile()
3272processed = []
3273generateHeader(outfile, prefix)
3274DelayedElements = []
3275DelayedElements_subclass = []
3276elements = root.getChildren()
3277generateFromTree(outfile, prefix, elements, processed)
3278while 1:
3279if len(DelayedElements) <= 0:
3280break
3281element = DelayedElements.pop()
3282name = element.getCleanName()
3283if name not in processed:
3284processed.append(name)
3285generateClasses(outfile, prefix, element, 1)
3286#
3287# Generate the elements that were postponed because we had not
3288# yet generated their base class.
3289idx = 0
3290while 1:
3291if len(PostponedExtensions) <= 0:
3292break
3293element = PostponedExtensions.pop()
3294base = element.getBase()
3295if base and base in ElementDict:
3296parent = ElementDict[base]
3297parentName = parent.getName()
3298if parentName not in AlreadyGenerated:
3299PostponedExtensions.insert(0, element)
3300else:
3301idx += 1
3302generateClasses(outfile, prefix, element, 1)
3303#
3304# Disable the generation of SAX handler/parser.
3305# It failed when we stopped putting simple types into ElementDict.
3306# When there are duplicate names, the SAX parser probably does
3307# not work anyway.
3308generateSAXHndlr(outfile, root)
3309generateMain(outfile, prefix, root)
3310outfile.close()
3311if subclassFilename:
3312generateSubclasses(root, subclassFilename, behaviorFilename, prefix, superModule)
3313
3314
3315def makeFile(outFileName):
3316global Force
3317outFile = None
3318if (not Force) and os.path.exists(outFileName):
3319reply = input("File %s exists. Overwrite? (y/n): " % outFileName)
3320if reply == "y":
3321outFile = open(outFileName, "w")
3322else:
3323outFile = open(outFileName, "w")
3324return outFile
3325
3326
3327def mapName(oldName):
3328global NameTable
3329newName = oldName
3330if NameTable:
3331if oldName in NameTable:
3332newName = NameTable[oldName]
3333return newName
3334
3335
3336def cleanupName(oldName):
3337newName = oldName.replace(":", "_")
3338newName = newName.replace("-", "_")
3339return newName
3340
3341
3342## def mapName(oldName):
3343## return '_X_%s' % oldName
3344
3345
3346def strip_namespace(val):
3347return val.split(":")[-1]
3348
3349
3350def parseAndGenerate(
3351outfileName,
3352subclassFilename,
3353prefix,
3354xschemaFileName,
3355behaviorFilename,
3356superModule="???",
3357):
3358global DelayedElements, DelayedElements_subclass, AlreadyGenerated, SaxDelayedElements, AlreadyGenerated_subclass
3359DelayedElements = []
3360DelayedElements_subclass = []
3361AlreadyGenerated = []
3362AlreadyGenerated_subclass = []
3363## parser = saxexts.make_parser("xml.sax.drivers2.drv_pyexpat")
3364parser = make_parser()
3365## print 'dir(parser):', dir(parser)
3366## print "Parser: %s" % parser
3367dh = XschemaHandler()
3368## parser.setDocumentHandler(dh)
3369parser.setContentHandler(dh)
3370parser.parse(xschemaFileName)
3371root = dh.getRoot()
3372root.annotate()
3373## print 'ElementDict:', ElementDict
3374## for name, obj in ElementDict.items():
3375## print ' ', name, obj.getName(), obj.type
3376## print '=' * 50
3377## root.show(sys.stdout, 0)
3378## print '=' * 50
3379## response = input('Press Enter')
3380## root.show(sys.stdout, 0)
3381## print '=' * 50
3382## print ']]] root: ', root, '[[['
3383generate(outfileName, subclassFilename, behaviorFilename, prefix, root, superModule)
3384
3385
3386USAGE_TEXT = """
3387Usage: python generateDS.py [ options ] <in_xsd_file>
3388Options:
3389-o <outfilename> Output file name for data representation classes
3390-s <subclassfilename> Output file name for subclasses
3391-p <prefix> Prefix string to be prepended to the class names
3392-n <mappingfilename> Transform names with table in mappingfilename.
3393-f Force creation of output files. Do not ask.
3394-a <namespaceabbrev> Namespace abbreviation, e.g. "xsd:". Default = 'xs:'.
3395-b <behaviorfilename> Input file name for behaviors added to subclasses
3396-m Generate properties for member variables
3397--subclass-suffix="XXX" Append XXX to the generated subclass names. Default="Sub".
3398--root-element="XXX" Assume XXX is root element of instance docs.
3399Default is first element defined in schema.
3400--super="XXX" Super module name in subclass module. Default="???"
3401
3402Example:
3403python generateDS.py -o generateModel_Module.py generateMetaModel_Module.xsd
3404"""
3405
3406
3407def usage():
3408print(USAGE_TEXT)
3409sys.exit(-1)
3410
3411
3412def main():
3413global Force, GenerateProperties, SubclassSuffix, RootElement
3414args = sys.argv[1:]
3415options, args = getopt.getopt(
3416args,
3417"fyo:s:p:a:b:m",
3418[
3419"subclass-suffix=",
3420"root-element=",
3421"super=",
3422],
3423)
3424prefix = ""
3425outFilename = None
3426subclassFilename = None
3427behaviorFilename = None
3428nameSpace = "xs:"
3429debug = 0
3430superModule = "???"
3431for option in options:
3432if option[0] == "-p":
3433prefix = option[1]
3434elif option[0] == "-o":
3435outFilename = option[1]
3436elif option[0] == "-s":
3437subclassFilename = option[1]
3438elif option[0] == "-f":
3439Force = 1
3440elif option[0] == "-a":
3441nameSpace = option[1]
3442elif option[0] == "-b":
3443behaviorFilename = option[1]
3444elif option[0] == "-m":
3445GenerateProperties = 1
3446elif option[0] == "--subclass-suffix":
3447SubclassSuffix = option[1]
3448elif option[0] == "--root-element":
3449RootElement = option[1]
3450elif option[0] == "--super":
3451superModule = option[1]
3452set_type_constants(nameSpace)
3453if behaviorFilename and not subclassFilename:
3454print("\n*** Error. -b requires -s")
3455usage()
3456if len(args) != 1:
3457usage()
3458xschemaFileName = args[0]
3459if debug:
3460pass
3461else:
3462parseAndGenerate(
3463outFilename,
3464subclassFilename,
3465prefix,
3466xschemaFileName,
3467behaviorFilename,
3468superModule=superModule,
3469)
3470
3471
3472if __name__ == "__main__":
3473main()
3474## import pdb
3475## pdb.run('main()')
3476