FreeCAD

Форк
0
/
generateDS.py 
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

26
import sys
27
import os.path
28
import time
29
import getopt
30
from urllib.request import urlopen
31
from urllib.error import HTTPError
32
from xml.sax import handler, make_parser
33
import 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
#
49
GenerateProperties = 0
50
DelayedElements = []
51
DelayedElements_subclass = []
52
AlreadyGenerated = []
53
AlreadyGenerated_subclass = []
54
PostponedExtensions = []
55
ElementsForSubclasses = []
56
ElementDict = {}
57
SaxElementDict = {}
58
ElementDebugList = []
59
Force = 0
60
NameTable = {
61
    "class": "klass",
62
    "import": "emport",
63
    "type": "ttype",
64
}
65
SubclassSuffix = "Sub"
66
RootElement = None
67
AttributeGroups = {}
68
SubstitutionGroups = {}
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.
73
SimpleElementDict = {}
74

75

76
def set_type_constants(nameSpace):
77
    global 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
78
    AttributeGroupType = nameSpace + "attributeGroup"
79
    AttributeType = nameSpace + "attribute"
80
    BooleanType = nameSpace + "boolean"
81
    ChoiceType = nameSpace + "choice"
82
    ComplexContentType = nameSpace + "complexContent"
83
    ComplexTypeType = nameSpace + "complexType"
84
    AnyAttributeType = nameSpace + "anyAttribute"
85
    DateTimeType = nameSpace + "dateTime"
86
    DateType = nameSpace + "date"
87
    IntegerType = (
88
        nameSpace + "integer",
89
        nameSpace + "xs:unsignedShort",
90
        nameSpace + "short",
91
        nameSpace + "long",
92
    )
93
    # ShortType = nameSpace + 'short'
94
    # LongType = nameSpace + 'long'
95
    DecimalType = nameSpace + "decimal"
96
    PositiveIntegerType = nameSpace + "positiveInteger"
97
    NegativeIntegerType = nameSpace + "negativeInteger"
98
    NonPositiveIntegerType = nameSpace + "nonPositiveInteger"
99
    NonNegativeIntegerType = nameSpace + "nonNegativeInteger"
100
    DoubleType = nameSpace + "double"
101
    ElementType = nameSpace + "element"
102
    ExtensionType = nameSpace + "extension"
103
    FloatType = nameSpace + "float"
104
    IDREFSType = nameSpace + "IDREFS"
105
    IDREFType = nameSpace + "IDREF"
106
    IDType = nameSpace + "ID"
107
    SchemaType = nameSpace + "schema"
108
    SequenceType = nameSpace + "sequence"
109
    StringType = (
110
        nameSpace + "string",
111
        nameSpace + "duration",
112
        nameSpace + "anyURI",
113
    )
114
    TokenType = nameSpace + "token"
115

116

117
#
118
# For debugging.
119
#
120

121
# Print only if DEBUG is true.
122
DEBUG = 1
123

124

125
def dbgprint(level, msg):
126
    if DEBUG and level > 0:
127
        print(msg)
128

129

130
def pplist(lst):
131
    for count, item in enumerate(lst):
132
        print("%d. %s" % (count, item))
133

134

135
#
136
# Representation of element definition.
137
#
138

139

140
def showLevel(outfile, level):
141
    for idx in range(level):
142
        outfile.write("    ")
143

144

145
class XschemaElement:
146
    def __init__(self, attrs):
147
        self.cleanName = ""
148
        self.attrs = dict(attrs)
149
        name_val = ""
150
        type_val = ""
151
        ref_val = ""
152
        if "name" in self.attrs:
153
            name_val = strip_namespace(self.attrs["name"])
154
        if "type" in self.attrs:
155
            # fix
156
            # type_val = strip_namespace(self.attrs['type'])
157
            type_val = self.attrs["type"]
158
        if "ref" in self.attrs:
159
            ref_val = strip_namespace(self.attrs["ref"])
160
        if type_val and not name_val:
161
            name_val = type_val
162
        if ref_val and not name_val:
163
            name_val = ref_val
164
        if ref_val and not type_val:
165
            type_val = ref_val
166
        if name_val:
167
            self.attrs["name"] = name_val
168
        if type_val:
169
            self.attrs["type"] = type_val
170
        if ref_val:
171
            self.attrs["ref"] = ref_val
172
        self.name = name_val
173
        self.children = []
174
        self.maxOccurs = 1
175
        self.complex = 0
176
        self.complexType = 0
177
        self.type = "NoneType"
178
        self.mixed = 0
179
        self.base = None
180
        self.mixedExtensionError = 0
181
        # Attribute definitions for the correct element.
182
        self.attributeDefs = {}
183
        # Attribute definitions for the current attributeGroup, if there is one.
184
        self.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().
188
        self.attributeGroupNameList = []
189
        self.topLevel = 0
190
        # Does this element contain an anyAttribute?
191
        self.anyAttribute = 0
192

193
    def addChild(self, element):
194
        self.children.append(element)
195

196
    def getChildren(self):
197
        return self.children
198

199
    def getName(self):
200
        return self.name
201

202
    def getCleanName(self):
203
        return self.cleanName
204

205
    def getUnmappedCleanName(self):
206
        return self.unmappedCleanName
207

208
    def setName(self, name):
209
        self.name = name
210

211
    def getAttrs(self):
212
        return self.attrs
213

214
    def setAttrs(self, attrs):
215
        self.attrs = attrs
216

217
    def getMaxOccurs(self):
218
        return self.maxOccurs
219

220
    def getRawType(self):
221
        return self.type
222

223
    def getType(self):
224
        returnType = self.type
225
        if self.type in ElementDict:
226
            typeObj = ElementDict[self.type]
227
            typeObjType = typeObj.getRawType()
228
            if (
229
                typeObjType in StringType
230
                or typeObjType == TokenType
231
                or typeObjType == DateTimeType
232
                or typeObjType == DateType
233
                or typeObjType in IntegerType
234
                or typeObjType == DecimalType
235
                or typeObjType == PositiveIntegerType
236
                or typeObjType == NegativeIntegerType
237
                or typeObjType == NonPositiveIntegerType
238
                or typeObjType == NonNegativeIntegerType
239
                or typeObjType == BooleanType
240
                or typeObjType == FloatType
241
                or typeObjType == DoubleType
242
            ):
243
                returnType = typeObjType
244
        return returnType
245

246
    def isComplex(self):
247
        return self.complex
248

249
    def addAttributeDefs(self, attrs):
250
        self.attributeDefs.append(attrs)
251

252
    def getAttributeDefs(self):
253
        return self.attributeDefs
254

255
    def isMixed(self):
256
        return self.mixed
257

258
    def setMixed(self, mixed):
259
        self.mixed = mixed
260

261
    def setBase(self, base):
262
        self.base = base
263

264
    def getBase(self):
265
        return self.base
266

267
    def getMixedExtensionError(self):
268
        return self.mixedExtensionError
269

270
    def getAttributeGroups(self):
271
        return self.attributeGroups
272

273
    def addAttribute(self, name, attribute):
274
        self.attributeGroups[name] = attribute
275

276
    def setAttributeGroup(self, attributeGroup):
277
        self.attributeGroup = attributeGroup
278

279
    def getAttributeGroup(self):
280
        return self.attributeGroup
281

282
    def setTopLevel(self, topLevel):
283
        self.topLevel = topLevel
284

285
    def getTopLevel(self):
286
        return self.topLevel
287

288
    def setAnyAttribute(self, anyAttribute):
289
        self.anyAttribute = anyAttribute
290

291
    def getAnyAttribute(self):
292
        return self.anyAttribute
293

294
    def show(self, outfile, level):
295
        showLevel(outfile, level)
296
        outfile.write("Name: %s  Type: %s\n" % (self.name, self.getType()))
297
        showLevel(outfile, level)
298
        outfile.write("  - Complex: %d  MaxOccurs: %d\n" % (self.complex, self.maxOccurs))
299
        showLevel(outfile, level)
300
        outfile.write("  - Attrs: %s\n" % self.attrs)
301
        showLevel(outfile, level)
302
        outfile.write("  - AttributeDefs: %s\n" % self.attributeDefs)
303
        # ipshell('(visit_title) Entering ipshell.\nHit Ctrl-D to exit')
304

305
        for attr in self.getAttributeDefs():
306
            key = attr["name"]
307
            try:
308
                value = attr["value"]
309
            except:
310
                value = "<empty>"
311
            showLevel(outfile, level + 1)
312
            outfile.write("key: %s  value: %s\n" % (key, value))
313
        for child in self.children:
314
            child.show(outfile, level + 1)
315

316
    def annotate(self):
317
        self.collect_element_dict()
318
        self.annotate_find_type()
319
        self.annotate_tree()
320
        self.fix_dup_names()
321
        self.coerce_attr_types()
322
        self.checkMixedBases()
323

324
    def collect_element_dict(self):
325
        base = self.getBase()
326
        if (
327
            self.getTopLevel()
328
            or len(self.getChildren()) > 0
329
            or len(self.getAttributeDefs()) > 0
330
            or base
331
        ):
332
            ElementDict[self.name] = self
333
        for child in self.children:
334
            child.collect_element_dict()
335

336
    def element_is_complex(self):
337
        pass
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.
342
    def checkMixedBases(self):
343
        self.checkMixedBasesChain(self, self.mixed)
344
        for child in self.children:
345
            child.checkMixedBases()
346

347
    def checkMixedBasesChain(self, child, childMixed):
348
        base = self.getBase()
349
        if base and base in ElementDict:
350
            parent = ElementDict[base]
351
            if childMixed != parent.isMixed():
352
                self.mixedExtensionError = 1
353
                return
354
            parent.checkMixedBasesChain(child, childMixed)
355

356
    def resolve_type(self):
357
        self.complex = 0
358
        # If it has any attributes, then it's complex.
359
        attrDefs = self.getAttributeDefs()
360
        if len(attrDefs) > 0:
361
            self.complex = 1
362
            # type_val = ''
363
        type_val = self.resolve_type_1()
364
        if type_val:
365
            if type_val in ElementDict:
366
                element = ElementDict[type_val]
367
                type_val1 = element.resolve_type_1()
368
                if (
369
                    type_val1 in StringType
370
                    or type_val1 == TokenType
371
                    or type_val1 == DateTimeType
372
                    or type_val1 == DateType
373
                    or type_val1 in IntegerType
374
                    or type_val1 == DecimalType
375
                    or type_val1 == PositiveIntegerType
376
                    or type_val1 == NonPositiveIntegerType
377
                    or type_val1 == NegativeIntegerType
378
                    or type_val1 == NonNegativeIntegerType
379
                    or type_val1 == BooleanType
380
                    or type_val1 == FloatType
381
                    or type_val1 == DoubleType
382
                ):
383
                    type_val = type_val1
384
                else:
385
                    self.complex = 1
386
            else:
387
                if (
388
                    type_val in StringType
389
                    or type_val == TokenType
390
                    or type_val == DateTimeType
391
                    or type_val == DateType
392
                    or type_val in IntegerType
393
                    or type_val == DecimalType
394
                    or type_val == PositiveIntegerType
395
                    or type_val == NonPositiveIntegerType
396
                    or type_val == NegativeIntegerType
397
                    or type_val == NonNegativeIntegerType
398
                    or type_val == BooleanType
399
                    or type_val == FloatType
400
                    or type_val == DoubleType
401
                ):
402
                    pass
403
                else:
404
                    type_val = StringType[0]
405
        else:
406
            type_val = StringType[0]
407
        return type_val
408

409
    def resolve_type_1(self):
410
        type_val = ""
411
        if "type" in self.attrs:
412
            # fix
413
            # type_val = strip_namespace(self.attrs['type'])
414
            type_val = self.attrs["type"]
415
        elif "ref" in self.attrs:
416
            # fix
417
            type_val = strip_namespace(self.attrs["ref"])
418
            # type_val = self.attrs['ref']
419
        elif "name" in self.attrs:
420
            # fix
421
            type_val = strip_namespace(self.attrs["name"])
422
            # type_val = self.attrs['name']
423
        return type_val
424

425
    def annotate_find_type(self):
426
        type_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), ))
429
        self.attrs["type"] = type_val
430
        self.type = type_val
431
        if not self.complex:
432
            SimpleElementDict[self.name] = self.name
433
        for child in self.children:
434
            child.annotate_find_type()
435

436
    def annotate_tree(self):
437
        # If there is a namespace, replace it with an underscore.
438
        if self.base:
439
            self.base = strip_namespace(self.base)
440
        self.unmappedCleanName = cleanupName(self.name)
441
        self.cleanName = mapName(self.unmappedCleanName)
442
        SaxElementDict[self.cleanName] = self
443
        self.replace_attributeGroup_names()
444
        if "maxOccurs" in self.attrs:
445
            maxOccurs = self.attrs["maxOccurs"]
446
            if maxOccurs == "unbounded":
447
                maxOccurs = 99999
448
            else:
449
                try:
450
                    maxOccurs = int(self.attrs["maxOccurs"])
451
                except ValueError:
452
                    sys.stderr.write(
453
                        '*** %s  maxOccurs must be integer or "unbounded".' % (self.getName(),)
454
                    )
455
                    sys.exit(-1)
456
        else:
457
            maxOccurs = 1
458
        self.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.
462
        if self.type == "NoneType" and self.name:
463
            self.type = self.name
464
        # Is it a mixed-content element definition?
465
        if "mixed" in self.attrs:
466
            mixed = self.attrs["mixed"].strip()
467
            if mixed == "1" or mixed.lower() == "true":
468
                self.mixed = 1
469
        # Do it recursively for all descendents.
470
        for child in self.children:
471
            child.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.
477
    def replace_attributeGroup_names(self):
478
        for groupName in self.attributeGroupNameList:
479
            if groupName in AttributeGroups:
480
                attrGroup = AttributeGroups[groupName]
481
                for name in attrGroup.getKeys():
482
                    attr = attrGroup.get(name)
483
                    self.attributeDefs[name] = attr
484
            else:
485
                print("*** Error. attributeGroup %s not defined." % groupName)
486

487
    def __str__(self):
488
        s1 = '<"%s" XschemaElement instance at 0x%x>' % (self.getName(), id(self))
489
        return s1
490

491
    def __repr__(self):
492
        s1 = '<"%s" XschemaElement instance at 0x%x>' % (self.getName(), id(self))
493
        return s1
494

495
    def fix_dup_names(self):
496
        # Patch-up names that are used for both a child element and an attribute.
497
        #
498
        attrDefs = self.getAttributeDefs()
499
        # Collect a list of child element names.
500
        #   Must do this for base (extension) elements also.
501
        elementNames = []
502
        self.collectElementNames(elementNames)
503
        replaced = []
504
        # Create the needed new attributes.
505
        keys = attrDefs.keys()
506
        for key in keys:
507
            attr = attrDefs[key]
508
            name = attr.getName()
509
            if name in elementNames:
510
                newName = name + "_attr"
511
                newAttr = XschemaAttribute(newName)
512
                attrDefs[newName] = newAttr
513
                replaced.append(name)
514
        # Remove the old (replaced) attributes.
515
        for name in replaced:
516
            del attrDefs[name]
517
        for child in self.children:
518
            child.fix_dup_names()
519

520
    def collectElementNames(self, elementNames):
521
        for child in self.children:
522
            elementNames.append(cleanupName(child.cleanName))
523
        base = self.getBase()
524
        if base and base in ElementDict:
525
            parent = ElementDict[base]
526
            parent.collectElementNames(elementNames)
527

528
    def coerce_attr_types(self):
529
        replacements = []
530
        attrDefs = self.getAttributeDefs()
531
        for idx, name in enumerate(attrDefs):
532
            attr = attrDefs[name]
533
            attrType = attr.getData_type()
534
            if attrType == IDType or attrType == IDREFType or attrType == IDREFSType:
535
                attr.setData_type(StringType[0])
536
        for child in self.children:
537
            child.coerce_attr_types()
538

539

540
# end class XschemaElement
541

542

543
class XschemaAttributeGroup:
544
    def __init__(self, name="", group=None):
545
        self.name = name
546
        if group:
547
            self.group = group
548
        else:
549
            self.group = {}
550

551
    def setName(self, name):
552
        self.name = name
553

554
    def getName(self):
555
        return self.name
556

557
    def setGroup(self, group):
558
        self.group = group
559

560
    def getGroup(self):
561
        return self.group
562

563
    def get(self, name, default=None):
564
        if name in self.group:
565
            return self.group[name]
566
        else:
567
            return default
568

569
    def getKeys(self):
570
        return self.group.keys()
571

572
    def add(self, name, attr):
573
        self.group[name] = attr
574

575
    def delete(self, name):
576
        # if has_key(self.group, name):
577
        if name in self.group:
578
            del self.group[name]
579
            return 1
580
        else:
581
            return 0
582

583

584
# end class XschemaAttributeGroup
585

586

587
class XschemaAttribute:
588
    def __init__(self, name, data_type="xs:string", use="optional"):
589
        self.name = name
590
        self.data_type = data_type
591
        self.use = use
592

593
    def setName(self, name):
594
        self.name = name
595

596
    def getName(self):
597
        return self.name
598

599
    def setData_type(self, data_type):
600
        self.data_type = data_type
601

602
    def getData_type(self):
603
        return self.data_type
604

605
    def setUse(self, use):
606
        self.use = use
607

608
    def getUse(self):
609
        return self.use
610

611

612
# end class XschemaAttribute
613

614

615
#
616
# SAX handler
617
#
618
class XschemaHandler(handler.ContentHandler):
619
    def __init__(self):
620
        handler.ContentHandler.__init__(self)
621
        self.stack = []
622
        self.root = None
623
        self.inElement = 0
624
        self.inComplexType = 0
625
        self.inNonanonymousComplexType = 0
626
        self.inSequence = 0
627
        self.inChoice = 1
628
        self.inAttribute = 0
629
        self.inAttributeGroup = 0
630
        self.inSimpleElement = 0
631

632
    ##        self.dbgcount = 1
633
    ##        self.dbgnames = []
634

635
    def getRoot(self):
636
        # ipshell('Returning root -- Entering ipshell.\\nHit Ctrl-D to exit')
637
        return self.root
638

639
    def showError(self, msg):
640
        print(msg)
641
        sys.exit(-1)
642

643
    def startElement(self, name, attrs):
644
        # dbgprint(1, 'before schema name: %s  SchemaType: %s' % (name, SchemaType,))
645
        if name == SchemaType:
646
            # dbgprint(1, '(schema in)')
647
            self.inSchema = 1
648
            element = XschemaElement(attrs)
649
            if len(self.stack) == 1:
650
                element.setTopLevel(1)
651
            self.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.
655
            for name, value in attrs.items():
656
                if name[:6] == "xmlns:" and value == "http://www.w3.org/2001/XMLSchema":
657
                    nameSpace = name[6:] + ":"
658
                    set_type_constants(nameSpace)
659
        elif name == ElementType or ((name == ComplexTypeType) and (len(self.stack) == 1)):
660
            self.inElement = 1
661
            self.inNonanonymousComplexType = 1
662
            element = XschemaElement(attrs)
663
            if len(self.stack) == 1:
664
                element.setTopLevel(1)
665
            if "substitutionGroup" in attrs and "name" in attrs:
666
                substituteName = attrs["name"]
667
                headName = attrs["substitutionGroup"]
668
                if headName not in SubstitutionGroups:
669
                    SubstitutionGroups[headName] = []
670
                SubstitutionGroups[headName].append(substituteName)
671
                # dbgprint(1, '(startElement) added %s to %s' % (substituteName, headName))
672
            if name == ComplexTypeType:
673
                element.complexType = 1
674
            self.stack.append(element)
675
        elif 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.
678
            if len(self.stack) > 1 and len(attrs) > 0:
679
                parentDict = self.stack[-1].getAttrs()
680
                for key in attrs.keys():
681
                    parentDict[key] = attrs[key]
682
            self.inComplexType = 1
683
        elif name == SequenceType:
684
            self.inSequence = 1
685
        elif name == ChoiceType:
686
            self.inChoice = 1
687
        elif name == AttributeType:
688
            self.inAttribute = 1
689
            if "name" in attrs:
690
                name = attrs["name"]
691
            # fix-attribute-ref
692
            elif "ref" in attrs:
693
                name = strip_namespace(attrs["ref"])
694
            else:
695
                name = "no_attribute_name"
696
            if "type" in attrs:
697
                data_type = attrs["type"]
698
            else:
699
                data_type = StringType[0]
700
            if "use" in attrs:
701
                use = attrs["use"]
702
            else:
703
                use = "optional"
704
            if self.stack[-1].attributeGroup:
705
                # Add this attribute to a current attributeGroup.
706
                attribute = XschemaAttribute(name, data_type, use)
707
                self.stack[-1].attributeGroup.add(name, attribute)
708
            else:
709
                # Add this attribute to the element/complexType.
710
                attribute = XschemaAttribute(name, data_type, use)
711
                self.stack[-1].attributeDefs[name] = attribute
712
        elif name == AttributeGroupType:
713
            self.inAttributeGroup = 1
714
            # If it has attribute 'name', then it's a definition.
715
            #   Prepare to save it as an attributeGroup.
716
            if "name" in attrs:
717
                name = strip_namespace(attrs["name"])
718
                attributeGroup = XschemaAttributeGroup(name)
719
                element = XschemaElement(attrs)
720
                if len(self.stack) == 1:
721
                    element.setTopLevel(1)
722
                element.setAttributeGroup(attributeGroup)
723
                self.stack.append(element)
724
            # If it has attribute 'ref', add it to the list of
725
            #   attributeGroups for this element/complexType.
726
            if "ref" in attrs:
727
                self.stack[-1].attributeGroupNameList.append(attrs["ref"])
728
        elif name == ComplexContentType:
729
            pass
730
        elif name == ExtensionType:
731
            if "base" in attrs and len(self.stack) > 0:
732
                extensionBase = attrs["base"]
733
                if (
734
                    extensionBase in StringType
735
                    or extensionBase == TokenType
736
                    or extensionBase == DateTimeType
737
                    or extensionBase == DateType
738
                    or extensionBase in IntegerType
739
                    or extensionBase == DecimalType
740
                    or extensionBase == PositiveIntegerType
741
                    or extensionBase == NegativeIntegerType
742
                    or extensionBase == NonPositiveIntegerType
743
                    or extensionBase == NonNegativeIntegerType
744
                    or extensionBase == BooleanType
745
                    or extensionBase == FloatType
746
                    or extensionBase == DoubleType
747
                ):
748
                    pass
749
                else:
750
                    self.stack[-1].setBase(extensionBase)
751
        elif name == AnyAttributeType:
752
            # Mark the current element as containing anyAttribute.
753
            self.stack[-1].setAnyAttribute(1)
754

755
    def endElement(self, name):
756
        if self.inSimpleElement:
757
            self.inSimpleElement = 0
758
        elif name == ElementType or (name == ComplexTypeType and self.stack[-1].complexType):
759
            self.inElement = 0
760
            self.inNonanonymousComplexType = 0
761
            element = self.stack.pop()
762
            self.stack[-1].addChild(element)
763
        elif name == ComplexTypeType:
764
            self.inComplexType = 0
765
        elif name == SequenceType:
766
            self.inSequence = 0
767
        elif name == ChoiceType:
768
            self.inChoice = 0
769
        elif name == AttributeType:
770
            self.inAttribute = 0
771
        elif name == AttributeGroupType:
772
            self.inAttributeGroup = 0
773
            if 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.
778
                attributeGroup = self.stack[-1].attributeGroup
779
                name = attributeGroup.getName()
780
                AttributeGroups[name] = attributeGroup
781
                self.stack[-1].attributeGroup = None
782
                self.stack.pop()
783
            else:
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.
787
                pass
788
        elif name == SchemaType:
789
            self.inSchema = 0
790
            if len(self.stack) != 1:
791
                print("*** error stack.  len(self.stack): %d" % len(self.stack))
792
                sys.exit(-1)
793
            self.root = self.stack[0]
794
        elif name == ComplexContentType:
795
            pass
796
        elif name == ExtensionType:
797
            pass
798

799
    def characters(self, chrs):
800
        if self.inElement:
801
            pass
802
        elif self.inComplexType:
803
            pass
804
        elif self.inSequence:
805
            pass
806
        elif self.inChoice:
807
            pass
808

809

810
#
811
# Code generation
812
#
813

814

815
def generateExportFn_1(outfile, child, name, fill):
816
    cleanName = cleanupName(name)
817
    if (
818
        child.getType() in StringType
819
        or child.getType() == TokenType
820
        or child.getType() == DateTimeType
821
        or child.getType() == DateType
822
    ):
823
        s1 = "%s        showIndent(outfile, level)\n" % fill
824
        outfile.write(s1)
825
        s1 = "%s        outfile.write('<%s>%%s</%s>\\n' %% quote_xml(self.get%s()))\n" % (
826
            fill,
827
            name,
828
            name,
829
            cleanName.capitalize(),
830
        )
831
        outfile.write(s1)
832
    elif (
833
        child.getType() in IntegerType
834
        or child.getType() == BooleanType
835
        or child.getType() == PositiveIntegerType
836
        or child.getType() == NonPositiveIntegerType
837
        or child.getType() == NegativeIntegerType
838
        or child.getType() == NonNegativeIntegerType
839
    ):
840
        s1 = "%s        showIndent(outfile, level)\n" % fill
841
        outfile.write(s1)
842
        s1 = "%s        outfile.write('<%s>%%d</%s>\\n' %% self.get%s())\n" % (
843
            fill,
844
            name,
845
            name,
846
            cleanName.capitalize(),
847
        )
848
        outfile.write(s1)
849
    elif child.getType() == FloatType or child.getType() == DecimalType:
850
        s1 = "%s        showIndent(outfile, level)\n" % fill
851
        outfile.write(s1)
852
        s1 = "%s        outfile.write('<%s>%%f</%s>\\n' %% self.get%s())\n" % (
853
            fill,
854
            name,
855
            name,
856
            cleanName.capitalize(),
857
        )
858
        outfile.write(s1)
859
    elif child.getType() == DoubleType:
860
        s1 = "%s        showIndent(outfile, level)\n" % fill
861
        outfile.write(s1)
862
        s1 = "%s        outfile.write('<%s>%%e</%s>\\n' %% self.get%s())\n" % (
863
            fill,
864
            name,
865
            name,
866
            cleanName.capitalize(),
867
        )
868
        outfile.write(s1)
869
    else:
870
        s1 = "%s        if self.%s:\n" % (fill, cleanName)
871
        outfile.write(s1)
872
        if name == child.getType():
873
            s1 = "%s            self.%s.export(outfile, level)\n" % (fill, cleanName)
874
        else:
875
            s1 = "%s            self.%s.export(outfile, level, name_='%s')\n" % (
876
                fill,
877
                cleanName,
878
                name,
879
            )
880
        outfile.write(s1)
881

882

883
def generateExportFn_2(outfile, child, name, fill):
884
    cleanName = cleanupName(name)
885
    s1 = "%s    for %s_ in self.get%s():\n" % (fill, cleanName, cleanName.capitalize())
886
    outfile.write(s1)
887
    if (
888
        child.getType() in StringType
889
        or child.getType() == TokenType
890
        or child.getType() == DateTimeType
891
        or child.getType() == DateType
892
    ):
893
        s1 = "%s        showIndent(outfile, level)\n" % fill
894
        outfile.write(s1)
895
        s1 = "%s        outfile.write('<%s>%%s</%s>\\n' %% quote_xml(%s_))\n" % (
896
            fill,
897
            name,
898
            name,
899
            cleanName,
900
        )
901
        outfile.write(s1)
902
    elif (
903
        child.getType() in IntegerType
904
        or child.getType() == BooleanType
905
        or child.getType() == PositiveIntegerType
906
        or child.getType() == NonPositiveIntegerType
907
        or child.getType() == NegativeIntegerType
908
        or child.getType() == NonNegativeIntegerType
909
    ):
910
        s1 = "%s        showIndent(outfile, level)\n" % fill
911
        outfile.write(s1)
912
        s1 = "%s        outfile.write('<%s>%%d</%s>\\n' %% %s_)\n" % (
913
            fill,
914
            name,
915
            name,
916
            cleanName,
917
        )
918
        outfile.write(s1)
919
    elif child.getType() == FloatType or child.getType() == DecimalType:
920
        s1 = "%s        showIndent(outfile, level)\n" % fill
921
        outfile.write(s1)
922
        s1 = "%s        outfile.write('<%s>%%f</%s>\\n' %% %s_)\n" % (
923
            fill,
924
            name,
925
            name,
926
            cleanName,
927
        )
928
        outfile.write(s1)
929
    elif child.getType() == DoubleType:
930
        s1 = "%s        showIndent(outfile, level)\n" % fill
931
        outfile.write(s1)
932
        s1 = "%s        outfile.write('<%s>%%e</%s>\\n' %% %s_)\n" % (
933
            fill,
934
            name,
935
            name,
936
            cleanName,
937
        )
938
        outfile.write(s1)
939
    else:
940
        if name == child.getType():
941
            s1 = "%s        %s_.export(outfile, level)\n" % (fill, cleanName)
942
        else:
943
            s1 = "%s        %s_.export(outfile, level, name_='%s')\n" % (
944
                fill,
945
                cleanName,
946
                cleanName,
947
            )
948
        outfile.write(s1)
949

950

951
def generateExportAttributes(outfile, element, hasAttributes):
952
    if len(element.getAttributeDefs()) > 0:
953
        hasAttributes += 1
954
        attrDefs = element.getAttributeDefs()
955
        for key in attrDefs.keys():
956
            attrDef = attrDefs[key]
957
            name = attrDef.getName()
958
            cleanName = cleanupName(name)
959
            capName = cleanName.capitalize()
960
            if attrDef.getUse() == "optional":
961
                s1 = "        if self.get%s() is not None:\n" % (capName,)
962
                outfile.write(s1)
963
                s1 = "            outfile.write(' %s=\"%%s\"' %% (self.get%s(), ))\n" % (
964
                    name,
965
                    capName,
966
                )
967
                outfile.write(s1)
968
            else:
969
                s1 = "        outfile.write(' %s=\"%%s\"' %% (self.get%s(), ))\n" % (
970
                    name,
971
                    capName,
972
                )
973
                outfile.write(s1)
974
    if element.getAnyAttribute():
975
        s1 = "        for name, value in self.anyAttributes_.items():\n"
976
        outfile.write(s1)
977
        s1 = "            outfile.write(' %s=\"%s\"' % (name, value, ))\n"
978
        outfile.write(s1)
979
    return hasAttributes
980

981

982
def generateExportChildren(outfile, element, hasChildren):
983
    if len(element.getChildren()) > 0:
984
        hasChildren += 1
985
        if element.isMixed():
986
            s1 = "        for item_ in self.content_:\n"
987
            outfile.write(s1)
988
            s1 = "            item_.export(outfile, level, name_)\n"
989
            outfile.write(s1)
990
        else:
991
            for child in element.getChildren():
992
                name = child.getName()
993
                if child.getMaxOccurs() > 1:
994
                    generateExportFn_2(outfile, child, name, "    ")
995
                else:
996
                    generateExportFn_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)
1001
    return hasChildren
1002

1003

1004
def countChildren(element, count):
1005
    count += len(element.getChildren())
1006
    base = element.getBase()
1007
    if base and base in ElementDict:
1008
        parent = ElementDict[base]
1009
        count = countChildren(parent, count)
1010
    return count
1011

1012

1013
def generateExportFn(outfile, prefix, element):
1014
    base = element.getBase()
1015
    s1 = "    def export(self, outfile, level, name_='%s'):\n" % element.getName()
1016
    outfile.write(s1)
1017
    s1 = "        showIndent(outfile, level)\n"
1018
    outfile.write(s1)
1019
    if len(element.getAttributeDefs()) > 0:
1020
        s1 = "        outfile.write('<%s' % (name_, ))\n"
1021
        outfile.write(s1)
1022

1023
        s1 = "        self.exportAttributes(outfile, level, name_='%s')\n" % element.getName()
1024
        outfile.write(s1)
1025
        if element.isMixed():
1026
            s1 = "        outfile.write('>')\n"
1027
        else:
1028
            s1 = "        outfile.write('>\\n')\n"
1029
        outfile.write(s1)
1030
    else:
1031
        if element.isMixed():
1032
            s1 = "        outfile.write('<%s>' % name_)\n"
1033
        else:
1034
            s1 = "        outfile.write('<%s>\\n' % name_)\n"
1035
        outfile.write(s1)
1036

1037
    s1 = "        self.exportChildren(outfile, level + 1, name_)\n"
1038
    outfile.write(s1)
1039
    s1 = "        showIndent(outfile, level)\n"
1040
    outfile.write(s1)
1041
    s1 = "        outfile.write('</%s>\\n' % name_)\n"
1042
    outfile.write(s1)
1043
    s1 = "    def exportAttributes(self, outfile, level, name_='%s'):\n" % element.getName()
1044
    outfile.write(s1)
1045
    hasAttributes = 0
1046
    hasAttributes = generateExportAttributes(outfile, element, hasAttributes)
1047
    if base:
1048
        hasAttributes += 1
1049
        s1 = "        %s.exportAttributes(self, outfile, level, name_='%s')\n" % (
1050
            base,
1051
            element.getName(),
1052
        )
1053
        outfile.write(s1)
1054
    if hasAttributes == 0:
1055
        s1 = "        pass\n"
1056
        outfile.write(s1)
1057
    ##    if len(element.getChildren()) > 0 and not element.isMixed():
1058
    ##        s1 = '        showIndent(outfile, level)\n'
1059
    ##        outfile.write(s1)
1060
    s1 = "    def exportChildren(self, outfile, level, name_='%s'):\n" % element.getName()
1061
    outfile.write(s1)
1062
    hasChildren = 0
1063
    hasChildren = generateExportChildren(outfile, element, hasChildren)
1064
    if base:
1065
        hasChildren += 1
1066
        s1 = "        %s.exportChildren(self, outfile, level, name_)\n" % (base,)
1067
        outfile.write(s1)
1068
    count = countChildren(element, 0)
1069
    if count == 0:
1070
        s1 = "        outfile.write(self.valueOf_)\n"
1071
        outfile.write(s1)
1072

1073

1074
#
1075
# Generate exportLiteral method.
1076
#
1077

1078

1079
def generateExportLiteralFn_1(outfile, child, name, fill):
1080
    mappedName = mapName(name)
1081
    if (
1082
        child.getType() in StringType
1083
        or child.getType() == TokenType
1084
        or child.getType() == DateTimeType
1085
        or child.getType() == DateType
1086
    ):
1087
        s1 = "%s        showIndent(outfile, level)\n" % fill
1088
        outfile.write(s1)
1089
        s1 = "%s        outfile.write('%s=%%s,\\n' %% quote_python(self.get%s()))\n" % (
1090
            fill,
1091
            mappedName,
1092
            name.capitalize(),
1093
        )
1094
        outfile.write(s1)
1095
    elif (
1096
        child.getType() in IntegerType
1097
        or child.getType() == BooleanType
1098
        or child.getType() == PositiveIntegerType
1099
        or child.getType() == NonPositiveIntegerType
1100
        or child.getType() == NegativeIntegerType
1101
        or child.getType() == NonNegativeIntegerType
1102
    ):
1103
        s1 = "%s        showIndent(outfile, level)\n" % fill
1104
        outfile.write(s1)
1105
        s1 = "%s        outfile.write('%s=%%d,\\n' %% self.get%s())\n" % (
1106
            fill,
1107
            mappedName,
1108
            name.capitalize(),
1109
        )
1110
        outfile.write(s1)
1111
    elif child.getType() == FloatType or child.getType() == DecimalType:
1112
        s1 = "%s        showIndent(outfile, level)\n" % fill
1113
        outfile.write(s1)
1114
        s1 = "%s        outfile.write('%s=%%f,\\n' %% self.get%s())\n" % (
1115
            fill,
1116
            mappedName,
1117
            name.capitalize(),
1118
        )
1119
        outfile.write(s1)
1120
    elif child.getType() == DoubleType:
1121
        s1 = "%s        showIndent(outfile, level)\n" % fill
1122
        outfile.write(s1)
1123
        s1 = "%s        outfile.write('%s=%%e,\\n' %% self.get%s())\n" % (
1124
            fill,
1125
            name,
1126
            name.capitalize(),
1127
        )
1128
        outfile.write(s1)
1129
    else:
1130
        s1 = "%s        if self.%s:\n" % (fill, name)
1131
        outfile.write(s1)
1132
        s1 = "%s            showIndent(outfile, level)\n" % fill
1133
        outfile.write(s1)
1134
        s1 = "%s            outfile.write('%s=%s(\\n')\n" % (
1135
            fill,
1136
            name,
1137
            child.getType(),
1138
        )
1139
        outfile.write(s1)
1140
        if name == child.getType():
1141
            s1 = "%s            self.%s.exportLiteral(outfile, level)\n" % (fill, name)
1142
        else:
1143
            s1 = "%s            self.%s.exportLiteral(outfile, level, name_='%s')\n" % (
1144
                fill,
1145
                name,
1146
                name,
1147
            )
1148
        outfile.write(s1)
1149
        s1 = "%s            showIndent(outfile, level)\n" % fill
1150
        outfile.write(s1)
1151
        s1 = "%s            outfile.write('),\\n')\n" % (fill,)
1152
        outfile.write(s1)
1153

1154

1155
def generateExportLiteralFn_2(outfile, child, name, fill):
1156
    if (
1157
        child.getType() in StringType
1158
        or child.getType() == TokenType
1159
        or child.getType() == DateTimeType
1160
        or child.getType() == DateType
1161
    ):
1162
        s1 = "%s        showIndent(outfile, level)\n" % fill
1163
        outfile.write(s1)
1164
        s1 = "%s        outfile.write('%%s,\\n' %% quote_python(%s))\n" % (fill, name)
1165
        outfile.write(s1)
1166
    elif (
1167
        child.getType() in IntegerType
1168
        or child.getType() == BooleanType
1169
        or child.getType() == PositiveIntegerType
1170
        or child.getType() == NonPositiveIntegerType
1171
        or child.getType() == NegativeIntegerType
1172
        or child.getType() == NonNegativeIntegerType
1173
    ):
1174
        s1 = "%s        showIndent(outfile, level)\n" % fill
1175
        outfile.write(s1)
1176
        s1 = "%s        outfile.write('%%d,\\n' %% %s)\n" % (fill, name)
1177
        outfile.write(s1)
1178
    elif child.getType() == FloatType or child.getType() == DecimalType:
1179
        s1 = "%s        showIndent(outfile, level)\n" % fill
1180
        outfile.write(s1)
1181
        s1 = "%s        outfile.write('%%f,\\n' %% %s)\n" % (fill, name)
1182
        outfile.write(s1)
1183
    elif child.getType() == DoubleType:
1184
        s1 = "%s        showIndent(outfile, level)\n" % fill
1185
        outfile.write(s1)
1186
        s1 = "%s        outfile.write('%%e,\\n' %% %s)\n" % (fill, name)
1187
        outfile.write(s1)
1188
    else:
1189
        s1 = "%s        showIndent(outfile, level)\n" % fill
1190
        outfile.write(s1)
1191
        s1 = "%s        outfile.write('%s(\\n')\n" % (
1192
            fill,
1193
            cleanupName(child.getType()),
1194
        )
1195
        outfile.write(s1)
1196
        if name == child.getType():
1197
            s1 = "%s        %s.exportLiteral(outfile, level)\n" % (
1198
                fill,
1199
                child.getType(),
1200
            )
1201
        else:
1202
            s1 = "%s        %s.exportLiteral(outfile, level, name_='%s')\n" % (
1203
                fill,
1204
                name,
1205
                name,
1206
            )
1207
        outfile.write(s1)
1208
        s1 = "%s        showIndent(outfile, level)\n" % fill
1209
        outfile.write(s1)
1210
        s1 = "%s        outfile.write('),\\n')\n" % (fill,)
1211
        outfile.write(s1)
1212

1213

1214
def generateExportLiteralFn(outfile, prefix, element):
1215
    base = element.getBase()
1216
    s1 = "    def exportLiteral(self, outfile, level, name_='%s'):\n" % element.getName()
1217
    outfile.write(s1)
1218
    s1 = "        level += 1\n"
1219
    outfile.write(s1)
1220
    s1 = "        self.exportLiteralAttributes(outfile, level, name_)\n"
1221
    outfile.write(s1)
1222
    s1 = "        self.exportLiteralChildren(outfile, level, name_)\n"
1223
    outfile.write(s1)
1224
    s1 = "    def exportLiteralAttributes(self, outfile, level, name_):\n"
1225
    outfile.write(s1)
1226
    count = 0
1227
    attrDefs = element.getAttributeDefs()
1228
    for key in attrDefs:
1229
        attrDef = attrDefs[key]
1230
        count += 1
1231
        name = attrDef.getName()
1232
        cleanName = cleanupName(name)
1233
        capName = cleanName.capitalize()
1234
        mappedName = mapName(cleanName)
1235
        s1 = "        showIndent(outfile, level)\n"
1236
        outfile.write(s1)
1237
        ##        ipshell('(generateExportLiteral) -- Entering ipshell.\\nHit Ctrl-D to exit')
1238
        stringType = 0
1239
        data_type = attrDef.getData_type()
1240
        if data_type.find("string") >= 0:
1241
            stringType = 1
1242
        else:
1243
            stringType = 1
1244
        if stringType:
1245
            s1 = "        outfile.write('%s = \"%%s\",\\n' %% (self.get%s(),))\n" % (
1246
                mappedName,
1247
                capName,
1248
            )
1249
        else:
1250
            s1 = "        outfile.write('%s = %%s,\\n' %% (self.get%s(),))\n" % (
1251
                mappedName,
1252
                capName,
1253
            )
1254
        outfile.write(s1)
1255

1256
    if element.getAnyAttribute():
1257
        count += 1
1258
        s1 = "        for name, value in self.anyAttributes_.items():\n"
1259
        outfile.write(s1)
1260
        s1 = "            showIndent(outfile, level)\n"
1261
        outfile.write(s1)
1262
        s1 = "            outfile.write('%s = \"%s\",\\n' % (name, value,))\n"
1263
        outfile.write(s1)
1264
    if count == 0:
1265
        s1 = "        pass\n"
1266
        outfile.write(s1)
1267
    if base:
1268
        s1 = "        %s.exportLiteralAttributes(self, outfile, level, name_)\n" % (base,)
1269
        outfile.write(s1)
1270
    s1 = "    def exportLiteralChildren(self, outfile, level, name_):\n"
1271
    outfile.write(s1)
1272
    for child in element.getChildren():
1273
        name = child.getName()
1274
        name = cleanupName(name)
1275
        # unmappedName = child.getUnmappedCleanName()
1276
        # cleanName = cleanupName(name)
1277
        # mappedName = mapName(cleanName)
1278
        if element.isMixed():
1279
            s1 = "        showIndent(outfile, level)\n"
1280
            outfile.write(s1)
1281
            s1 = "        outfile.write('content_ = [\\n')\n"
1282
            outfile.write(s1)
1283
            s1 = "        for item_ in self.content_:\n"
1284
            outfile.write(s1)
1285
            s1 = "            item_.exportLiteral(outfile, level, name_)\n"
1286
            outfile.write(s1)
1287
            s1 = "        showIndent(outfile, level)\n"
1288
            outfile.write(s1)
1289
            s1 = "        outfile.write('],\\n')\n"
1290
            outfile.write(s1)
1291
        else:
1292
            if child.getMaxOccurs() > 1:
1293
                s1 = "        showIndent(outfile, level)\n"
1294
                outfile.write(s1)
1295
                s1 = "        outfile.write('%s=[\\n')\n" % name
1296
                outfile.write(s1)
1297
                s1 = "        level += 1\n"
1298
                outfile.write(s1)
1299
                s1 = "        for %s in self.%s:\n" % (name, name)
1300
                outfile.write(s1)
1301
                generateExportLiteralFn_2(outfile, child, name, "    ")
1302
                s1 = "        level -= 1\n"
1303
                outfile.write(s1)
1304
                s1 = "        showIndent(outfile, level)\n"
1305
                outfile.write(s1)
1306
                s1 = "        outfile.write('],\\n')\n"
1307
                outfile.write(s1)
1308
            else:
1309
                generateExportLiteralFn_1(outfile, child, name, "")
1310
    if len(element.getChildren()) == 0:
1311
        s1 = "        showIndent(outfile, level)\n"
1312
        outfile.write(s1)
1313
        s1 = "        outfile.write('valueOf_ = \"%s\",\\n' % (self.valueOf_,))\n"
1314
        outfile.write(s1)
1315
    if base:
1316
        s1 = "        %s.exportLiteralChildren(self, outfile, level, name_)\n" % (base,)
1317
        outfile.write(s1)
1318
    # s1 = "        level -= 1\n"
1319
    # outfile.write(s1)
1320

1321

1322
#
1323
# Generate build method.
1324
#
1325

1326

1327
def generateBuildAttributes(outfile, element, hasAttributes):
1328
    attrDefs = element.getAttributeDefs()
1329
    for key in attrDefs:
1330
        attrDef = attrDefs[key]
1331
        hasAttributes += 1
1332
        name = attrDef.getName()
1333
        cleanName = cleanupName(name)
1334
        mappedName = mapName(cleanName)
1335
        atype = attrDef.getData_type()
1336
        if (
1337
            atype in IntegerType
1338
            or atype == PositiveIntegerType
1339
            or atype == NonPositiveIntegerType
1340
            or atype == NegativeIntegerType
1341
            or atype == NonNegativeIntegerType
1342
        ):
1343
            s1 = "        if attrs.get('%s'):\n" % name
1344
            outfile.write(s1)
1345
            s1 = "            try:\n"
1346
            outfile.write(s1)
1347
            s1 = "                self.%s = int(attrs.get('%s').value)\n" % (
1348
                mappedName,
1349
                name,
1350
            )
1351
            outfile.write(s1)
1352
            s1 = "            except ValueError:\n"
1353
            outfile.write(s1)
1354
            s1 = "                raise ValueError('Bad integer attribute (%s)')\n" % (name,)
1355
            outfile.write(s1)
1356
            if atype == PositiveIntegerType:
1357
                s1 = "            if self.%s <= 0:\n" % mappedName
1358
                outfile.write(s1)
1359
                s1 = "                raise ValueError('Invalid PositiveInteger (%s)')\n" % name
1360
                outfile.write(s1)
1361
            elif atype == NonPositiveIntegerType:
1362
                s1 = "            if self.%s > 0:\n" % mappedName
1363
                outfile.write(s1)
1364
                s1 = "                raise ValueError('Invalid NonPositiveInteger (%s)')\n" % name
1365
                outfile.write(s1)
1366
            elif atype == NegativeIntegerType:
1367
                s1 = "            if self.%s >= 0:\n" % mappedName
1368
                outfile.write(s1)
1369
                s1 = "                raise ValueError('Invalid NegativeInteger (%s)')\n" % name
1370
                outfile.write(s1)
1371
            elif atype == NonNegativeIntegerType:
1372
                s1 = "            if self.%s < 0:\n" % mappedName
1373
                outfile.write(s1)
1374
                s1 = "                raise ValueError('Invalid NonNegativeInteger (%s)')\n" % name
1375
                outfile.write(s1)
1376
        elif atype == BooleanType:
1377
            s1 = "        if attrs.get('%s'):\n" % (name,)
1378
            outfile.write(s1)
1379
            s1 = "            if attrs.get('%s').value in ('true', '1'):\n" % (name,)
1380
            outfile.write(s1)
1381
            s1 = "                self.%s = 1\n" % (mappedName,)
1382
            outfile.write(s1)
1383
            s1 = "            elif attrs.get('%s').value in ('false', '0'):\n" % (name,)
1384
            outfile.write(s1)
1385
            s1 = "                self.%s = 0\n" % (mappedName,)
1386
            outfile.write(s1)
1387
            s1 = "            else:\n"
1388
            outfile.write(s1)
1389
            s1 = "                raise ValueError('Bad boolean attribute (%s)')\n" % (name,)
1390
            outfile.write(s1)
1391
        elif atype == FloatType or atype == DoubleType or atype == DecimalType:
1392
            s1 = "        if attrs.get('%s'):\n" % (name,)
1393
            outfile.write(s1)
1394
            s1 = "            try:\n"
1395
            outfile.write(s1)
1396
            s1 = "                self.%s = float(attrs.get('%s').value)\n" % (
1397
                mappedName,
1398
                name,
1399
            )
1400
            outfile.write(s1)
1401
            s1 = "            except:\n"
1402
            outfile.write(s1)
1403
            s1 = "                raise ValueError('Bad float/double attribute (%s)')\n" % (name,)
1404
            outfile.write(s1)
1405
        elif atype == TokenType:
1406
            s1 = "        if attrs.get('%s'):\n" % (name,)
1407
            outfile.write(s1)
1408
            s1 = "            self.%s = attrs.get('%s').value\n" % (
1409
                mappedName,
1410
                name,
1411
            )
1412
            outfile.write(s1)
1413
            s1 = "            self.%s = ' '.join(self.%s.split())\n" % (
1414
                mappedName,
1415
                mappedName,
1416
            )
1417
            outfile.write(s1)
1418
        else:
1419
            # Assume attr['type'] in StringType or attr['type'] == DateTimeType:
1420
            s1 = "        if attrs.get('%s'):\n" % (name,)
1421
            outfile.write(s1)
1422
            s1 = "            self.%s = attrs.get('%s').value\n" % (
1423
                mappedName,
1424
                name,
1425
            )
1426
            outfile.write(s1)
1427
    if element.getAnyAttribute():
1428
        s1 = "        self.anyAttributes_ = {}\n"
1429
        outfile.write(s1)
1430
        s1 = "        for name, value in attrs.items():\n"
1431
        outfile.write(s1)
1432
        s1List = ["            if"]
1433
        firstTime = 1
1434
        for key in attrDefs:
1435
            if firstTime:
1436
                s1List.append(' name != "%s"' % key)
1437
                firstTime = 0
1438
            else:
1439
                s1List.append(' and name != "%s"' % key)
1440
        s1List.append(":\n")
1441
        s1 = "".join(s1List)
1442
        outfile.write(s1)
1443
        s1 = "                self.anyAttributes_[name] = value\n"
1444
        outfile.write(s1)
1445
    return hasAttributes
1446

1447

1448
def generateBuildMixed_1(outfile, prefix, child, headChild, keyword, delayed):
1449
    global DelayedElements, DelayedElements_subclass
1450
    nestedElements = 1
1451
    origName = child.getName()
1452
    name = child.getCleanName()
1453
    headName = cleanupName(headChild.getName())
1454
    childType = child.getType()
1455
    if (
1456
        childType in StringType
1457
        or childType == TokenType
1458
        or childType == DateTimeType
1459
        or childType == DateType
1460
    ):
1461
        s1 = "        %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1462
        outfile.write(s1)
1463
        s1 = "            nodeName_ == '%s':\n" % origName
1464
        outfile.write(s1)
1465
        s1 = "            value_ = []\n"
1466
        outfile.write(s1)
1467
        s1 = "            for text_ in child_.childNodes:\n"
1468
        outfile.write(s1)
1469
        s1 = "                value_.append(text_.nodeValue)\n"
1470
        outfile.write(s1)
1471
        s1 = "            valuestr_ = ''.join(value_)\n"
1472
        outfile.write(s1)
1473
        if childType == TokenType:
1474
            s1 = "            valuestr_ = ' '.join(valuestr_.split())\n"
1475
            outfile.write(s1)
1476
        s1 = "            obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
1477
        outfile.write(s1)
1478
        s1 = "                MixedContainer.TypeString, '%s', valuestr_)\n" % origName
1479
        outfile.write(s1)
1480
        s1 = "            self.content_.append(obj_)\n"
1481
        outfile.write(s1)
1482
    elif (
1483
        childType in IntegerType
1484
        or childType == PositiveIntegerType
1485
        or childType == NonPositiveIntegerType
1486
        or childType == NegativeIntegerType
1487
        or childType == NonNegativeIntegerType
1488
    ):
1489
        s1 = "        %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1490
        outfile.write(s1)
1491
        s1 = "            nodeName_ == '%s':\n" % origName
1492
        outfile.write(s1)
1493
        s1 = "            if child_.firstChild:\n"
1494
        outfile.write(s1)
1495
        s1 = "                sval_ = child_.firstChild.nodeValue\n"
1496
        outfile.write(s1)
1497
        s1 = "                try:\n"
1498
        outfile.write(s1)
1499
        s1 = "                    ival_ = int(sval_)\n"
1500
        outfile.write(s1)
1501
        s1 = "                except ValueError:\n"
1502
        outfile.write(s1)
1503
        s1 = "                    raise ValueError('requires integer -- %s' % child_.toxml())\n"
1504
        outfile.write(s1)
1505
        if childType == PositiveIntegerType:
1506
            s1 = "                if ival_ <= 0:\n"
1507
            outfile.write(s1)
1508
            s1 = "                    raise ValueError('Invalid positiveInteger (%s)' % child_.toxml()))\n"
1509
            outfile.write(s1)
1510
        if childType == NonPositiveIntegerType:
1511
            s1 = "                if ival_ > 0:\n"
1512
            outfile.write(s1)
1513
            s1 = "                    raise ValueError('Invalid nonPositiveInteger (%s)' % child_.toxml()))\n"
1514
            outfile.write(s1)
1515
        if childType == NegativeIntegerType:
1516
            s1 = "                if ival_ >= 0:\n"
1517
            outfile.write(s1)
1518
            s1 = "                    raise ValueError('Invalid negativeInteger (%s)' % child_.toxml()))\n"
1519
            outfile.write(s1)
1520
        if childType == NonNegativeIntegerType:
1521
            s1 = "                if ival_ < 0:\n"
1522
            outfile.write(s1)
1523
            s1 = "                    raise ValueError('Invalid nonNegativeInteger (%s)' % child_.toxml()))\n"
1524
            outfile.write(s1)
1525
        s1 = "            else:\n"
1526
        outfile.write(s1)
1527
        s1 = "                ival_ = -1\n"
1528
        outfile.write(s1)
1529
        s1 = "            obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
1530
        outfile.write(s1)
1531
        s1 = "                MixedContainer.TypeInteger, '%s', ival_)\n" % origName
1532
        outfile.write(s1)
1533
        s1 = "            self.content_.append(obj_)\n"
1534
        outfile.write(s1)
1535
    elif childType == BooleanType:
1536
        s1 = "        %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1537
        outfile.write(s1)
1538
        s1 = "            nodeName_ == '%s':\n" % origName
1539
        outfile.write(s1)
1540
        s1 = "            if child_.firstChild:\n"
1541
        outfile.write(s1)
1542
        s1 = "                sval_ = child_.firstChild.nodeValue\n"
1543
        outfile.write(s1)
1544
        s1 = "                if sval_ in ('true', '1'):\n"
1545
        outfile.write(s1)
1546
        s1 = "                    ival_ = 1\n"
1547
        outfile.write(s1)
1548
        s1 = "                elif sval_ in ('false', '0'):\n"
1549
        outfile.write(s1)
1550
        s1 = "                    ival_ = 0\n"
1551
        outfile.write(s1)
1552
        s1 = "                else:\n"
1553
        outfile.write(s1)
1554
        s1 = "                    raise ValueError('requires boolean -- %s' % child_.toxml())\n"
1555
        outfile.write(s1)
1556
        s1 = "            obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
1557
        outfile.write(s1)
1558
        s1 = "                MixedContainer.TypeInteger, '%s', ival_)\n" % origName
1559
        outfile.write(s1)
1560
        s1 = "            self.content_.append(obj_)\n"
1561
        outfile.write(s1)
1562
    elif childType == FloatType or childType == DoubleType or childType == DecimalType:
1563
        s1 = "        %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1564
        outfile.write(s1)
1565
        s1 = "            nodeName_ == '%s':\n" % origName
1566
        outfile.write(s1)
1567
        s1 = "            if child_.firstChild:\n"
1568
        outfile.write(s1)
1569
        s1 = "                sval_ = child_.firstChild.nodeValue\n"
1570
        outfile.write(s1)
1571
        s1 = "                try:\n"
1572
        outfile.write(s1)
1573
        s1 = "                    fval_ = float(sval_)\n"
1574
        outfile.write(s1)
1575
        s1 = "                except ValueError:\n"
1576
        outfile.write(s1)
1577
        s1 = "                    raise ValueError('requires float (or double) -- %s' % child_.toxml())\n"
1578
        outfile.write(s1)
1579
        s1 = "            obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
1580
        outfile.write(s1)
1581
        s1 = "                MixedContainer.TypeFloat, '%s', fval_)\n" % origName
1582
        outfile.write(s1)
1583
        s1 = "            self.content_.append(obj_)\n"
1584
        outfile.write(s1)
1585
    else:
1586
        # Perhaps it's a complexType that is defined right here.
1587
        # Generate (later) a class for the nested types.
1588
        if not delayed and not child in DelayedElements:
1589
            DelayedElements.append(child)
1590
            DelayedElements_subclass.append(child)
1591
        s1 = "        %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1592
        outfile.write(s1)
1593
        s1 = "            nodeName_ == '%s':\n" % origName
1594
        outfile.write(s1)
1595
        s1 = "            childobj_ = %s%s.factory()\n" % (
1596
            prefix,
1597
            cleanupName(mapName(childType)),
1598
        )
1599
        outfile.write(s1)
1600
        s1 = "            childobj_.build(child_)\n"
1601
        outfile.write(s1)
1602
        s1 = "            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,\n"
1603
        outfile.write(s1)
1604
        s1 = "                MixedContainer.TypeNone, '%s', childobj_)\n" % origName
1605
        outfile.write(s1)
1606
        s1 = "            self.content_.append(obj_)\n"
1607
        outfile.write(s1)
1608

1609

1610
def generateBuildMixed(outfile, prefix, element, keyword, delayed, hasChildren):
1611
    for child in element.getChildren():
1612
        generateBuildMixed_1(outfile, prefix, child, child, keyword, delayed)
1613
        hasChildren += 1
1614
        keyword = "elif"
1615
        # Does this element have a substitutionGroup?
1616
        #   If so generate a clause for each element in the substitutionGroup.
1617
        if child.getName() in SubstitutionGroups:
1618
            for memberName in SubstitutionGroups[child.getName()]:
1619
                if memberName in ElementDict:
1620
                    member = ElementDict[memberName]
1621
                    generateBuildMixed_1(outfile, prefix, member, child, keyword, delayed)
1622
    s1 = "        %s child_.nodeType == Node.TEXT_NODE:\n" % keyword
1623
    outfile.write(s1)
1624
    s1 = "            obj_ = self.mixedclass_(MixedContainer.CategoryText,\n"
1625
    outfile.write(s1)
1626
    s1 = "                MixedContainer.TypeNone, '', child_.nodeValue)\n"
1627
    outfile.write(s1)
1628
    s1 = "            self.content_.append(obj_)\n"
1629
    outfile.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)
1634
    return hasChildren
1635

1636

1637
def generateBuildStandard_1(outfile, prefix, child, headChild, keyword, delayed):
1638
    global DelayedElements, DelayedElements_subclass
1639
    origName = child.getName()
1640
    name = cleanupName(child.getName())
1641
    mappedName = mapName(name)
1642
    headName = cleanupName(headChild.getName())
1643
    attrCount = len(child.getAttributeDefs())
1644
    # dbgprint(1, '(gbs) name: %s  type: %s  complex: %s  id: %s' % \
1645
    #    (child.getName(), child.getType(), child.isComplex(), id(child), ))
1646
    childType = child.getType()
1647
    if attrCount == 0 and (
1648
        childType in StringType
1649
        or childType == TokenType
1650
        or childType == DateTimeType
1651
        or childType == DateType
1652
    ):
1653
        s1 = "        %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1654
        outfile.write(s1)
1655
        s1 = "            nodeName_ == '%s':\n" % origName
1656
        outfile.write(s1)
1657
        s1 = "            %s_ = ''\n" % name
1658
        outfile.write(s1)
1659
        s1 = "            for text__content_ in child_.childNodes:\n"
1660
        outfile.write(s1)
1661
        s1 = "                %s_ += text__content_.nodeValue\n" % name
1662
        outfile.write(s1)
1663
        if childType == TokenType:
1664
            s1 = "            %s_ = ' '.join(%s_.split())\n" % (
1665
                name,
1666
                name,
1667
            )
1668
            outfile.write(s1)
1669
        if child.getMaxOccurs() > 1:
1670
            s1 = "            self.%s.append(%s_)\n" % (
1671
                mappedName,
1672
                name,
1673
            )
1674
            outfile.write(s1)
1675
        else:
1676
            s1 = "            self.%s = %s_\n" % (
1677
                mappedName,
1678
                name,
1679
            )
1680
            outfile.write(s1)
1681
    elif (
1682
        childType in IntegerType
1683
        or childType == PositiveIntegerType
1684
        or childType == NonPositiveIntegerType
1685
        or childType == NegativeIntegerType
1686
        or childType == NonNegativeIntegerType
1687
    ):
1688
        s1 = "        %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1689
        outfile.write(s1)
1690
        s1 = "            nodeName_ == '%s':\n" % origName
1691
        outfile.write(s1)
1692
        s1 = "            if child_.firstChild:\n"
1693
        outfile.write(s1)
1694
        s1 = "                sval_ = child_.firstChild.nodeValue\n"
1695
        outfile.write(s1)
1696
        s1 = "                try:\n"
1697
        outfile.write(s1)
1698
        s1 = "                    ival_ = int(sval_)\n"
1699
        outfile.write(s1)
1700
        s1 = "                except ValueError:\n"
1701
        outfile.write(s1)
1702
        s1 = "                    raise ValueError('requires integer -- %s' % child_.toxml())\n"
1703
        outfile.write(s1)
1704
        if childType == PositiveIntegerType:
1705
            s1 = "                if ival_ <= 0:\n"
1706
            outfile.write(s1)
1707
            s1 = "                    raise ValueError('requires positiveInteger -- %s' % child_.toxml())\n"
1708
            outfile.write(s1)
1709
        elif childType == NonPositiveIntegerType:
1710
            s1 = "                if ival_ > 0:\n"
1711
            outfile.write(s1)
1712
            s1 = "                    raise ValueError('requires nonPositiveInteger -- %s' % child_.toxml())\n"
1713
            outfile.write(s1)
1714
        elif childType == NegativeIntegerType:
1715
            s1 = "                if ival_ >= 0:\n"
1716
            outfile.write(s1)
1717
            s1 = "                    raise ValueError('requires negativeInteger -- %s' % child_.toxml())\n"
1718
            outfile.write(s1)
1719
        elif childType == NonNegativeIntegerType:
1720
            s1 = "                if ival_ < 0:\n"
1721
            outfile.write(s1)
1722
            s1 = "                    raise ValueError('requires nonNegativeInteger -- %s' % child_.toxml())\n"
1723
            outfile.write(s1)
1724
        if child.getMaxOccurs() > 1:
1725
            s1 = "                self.%s.append(ival_)\n" % (mappedName,)
1726
            outfile.write(s1)
1727
        else:
1728
            s1 = "                self.%s = ival_\n" % (mappedName,)
1729
            outfile.write(s1)
1730
    elif childType == BooleanType:
1731
        s1 = "        %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1732
        outfile.write(s1)
1733
        s1 = "            nodeName_ == '%s':\n" % origName
1734
        outfile.write(s1)
1735
        s1 = "            if child_.firstChild:\n"
1736
        outfile.write(s1)
1737
        s1 = "                sval_ = child_.firstChild.nodeValue\n"
1738
        outfile.write(s1)
1739
        s1 = "                if sval_ in ('true', '1'):\n"
1740
        outfile.write(s1)
1741
        s1 = "                    ival_ = 1\n"
1742
        outfile.write(s1)
1743
        s1 = "                elif sval_ in ('false', '0'):\n"
1744
        outfile.write(s1)
1745
        s1 = "                    ival_ = 0\n"
1746
        outfile.write(s1)
1747
        s1 = "                else:\n"
1748
        outfile.write(s1)
1749
        s1 = "                    raise ValueError('requires boolean -- %s' % child_.toxml())\n"
1750
        outfile.write(s1)
1751
        if child.getMaxOccurs() > 1:
1752
            s1 = "                self.%s.append(ival_)\n" % (mappedName,)
1753
            outfile.write(s1)
1754
        else:
1755
            s1 = "                self.%s = ival_\n" % (mappedName,)
1756
            outfile.write(s1)
1757
    elif childType == FloatType or childType == DoubleType or childType == DecimalType:
1758
        s1 = "        %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1759
        outfile.write(s1)
1760
        s1 = "            nodeName_ == '%s':\n" % origName
1761
        outfile.write(s1)
1762
        s1 = "            if child_.firstChild:\n"
1763
        outfile.write(s1)
1764
        s1 = "                sval_ = child_.firstChild.nodeValue\n"
1765
        outfile.write(s1)
1766
        s1 = "                try:\n"
1767
        outfile.write(s1)
1768
        s1 = "                    fval_ = float(sval_)\n"
1769
        outfile.write(s1)
1770
        s1 = "                except ValueError:\n"
1771
        outfile.write(s1)
1772
        s1 = "                    raise ValueError('requires float (or double) -- %s' % child_.toxml())\n"
1773
        outfile.write(s1)
1774
        if child.getMaxOccurs() > 1:
1775
            s1 = "                self.%s.append(fval_)\n" % (mappedName,)
1776
            outfile.write(s1)
1777
        else:
1778
            s1 = "                self.%s = fval_\n" % (mappedName,)
1779
            outfile.write(s1)
1780
    else:
1781
        # Perhaps it's a complexType that is defined right here.
1782
        # Generate (later) a class for the nested types.
1783
        if not delayed and not child in DelayedElements:
1784
            DelayedElements.append(child)
1785
            DelayedElements_subclass.append(child)
1786
        s1 = "        %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
1787
        outfile.write(s1)
1788
        s1 = "            nodeName_ == '%s':\n" % origName
1789
        outfile.write(s1)
1790
        s1 = "            obj_ = %s%s.factory()\n" % (
1791
            prefix,
1792
            cleanupName(mapName(childType)),
1793
        )
1794
        outfile.write(s1)
1795
        s1 = "            obj_.build(child_)\n"
1796
        outfile.write(s1)
1797
        if headChild.getMaxOccurs() > 1:
1798
            s1 = "            self.%s.append(obj_)\n" % headName
1799
            outfile.write(s1)
1800
        else:
1801
            s1 = "            self.set%s(obj_)\n" % headName.capitalize()
1802
            outfile.write(s1)
1803

1804

1805
def generateBuildStandard(outfile, prefix, element, keyword, delayed, hasChildren):
1806
    for child in element.getChildren():
1807
        # dbgprint(1, '(generateBuildStandard) %s type: %s' % (child.getName(), child.getType(),))
1808
        generateBuildStandard_1(outfile, prefix, child, child, keyword, delayed)
1809
        hasChildren += 1
1810
        keyword = "elif"
1811
        # Does this element have a substitutionGroup?
1812
        #   If so generate a clause for each element in the substitutionGroup.
1813
        childName = child.getName()
1814
        if childName in SubstitutionGroups:
1815
            # dbgprint(1, '(BldStd) found: %s in %s' % (childName, SubstitutionGroups))
1816
            for memberName in SubstitutionGroups[childName]:
1817
                memberName = cleanupName(memberName)
1818
                if memberName in ElementDict:
1819
                    member = ElementDict[memberName]
1820
                    # dbgprint(1, '(BldStd) found subst: %s/%s' % (memberName, member))
1821
                    generateBuildStandard_1(outfile, prefix, member, child, keyword, delayed)
1822
    return hasChildren
1823

1824

1825
def generateBuildFn(outfile, prefix, element, delayed):
1826
    base = element.getBase()
1827
    outfile.write("    def build(self, node_):\n")
1828
    outfile.write("        attrs = node_.attributes\n")
1829
    outfile.write("        self.buildAttributes(attrs)\n")
1830
    ##    if len(element.getChildren()) > 0:
1831
    outfile.write("        for child_ in node_.childNodes:\n")
1832
    outfile.write("            nodeName_ = child_.nodeName.split(':')[-1]\n")
1833
    outfile.write("            self.buildChildren(child_, nodeName_)\n")
1834
    outfile.write("    def buildAttributes(self, attrs):\n")
1835
    hasAttributes = generateBuildAttributes(outfile, element, 0)
1836
    if base:
1837
        hasAttributes += 1
1838
        s1 = "        %s.buildAttributes(self, attrs)\n" % (base,)
1839
        outfile.write(s1)
1840
    if hasAttributes == 0:
1841
        outfile.write("        pass\n")
1842
    outfile.write("    def buildChildren(self, child_, nodeName_):\n")
1843
    keyword = "if"
1844
    hasChildren = 0
1845
    if element.isMixed():
1846
        hasChildren = generateBuildMixed(outfile, prefix, element, keyword, delayed, hasChildren)
1847
    else:  # not element.isMixed()
1848
        hasChildren = generateBuildStandard(outfile, prefix, element, keyword, delayed, hasChildren)
1849
    if hasChildren == 0:
1850
        s1 = "        self.valueOf_ = ''\n"
1851
        outfile.write(s1)
1852
        s1 = "        for child in child_.childNodes:\n"
1853
        outfile.write(s1)
1854
        s1 = "            if child.nodeType == Node.TEXT_NODE:\n"
1855
        outfile.write(s1)
1856
        s1 = "                self.valueOf_ += child.nodeValue\n"
1857
        outfile.write(s1)
1858
    if base and base in ElementDict:
1859
        parent = ElementDict[base]
1860
        if len(parent.getChildren()) > 0:
1861
            s1 = "        %s.buildChildren(self, child_, nodeName_)\n" % (base,)
1862
            outfile.write(s1)
1863

1864

1865
def countElementChildren(element, count):
1866
    count += len(element.getChildren())
1867
    base = element.getBase()
1868
    if base and base in ElementDict:
1869
        parent = ElementDict[base]
1870
        countElementChildren(parent, count)
1871
    return count
1872

1873

1874
def buildCtorArgs_multilevel(element):
1875
    content = []
1876
    add = content.append
1877
    buildCtorArgs_multilevel_aux(add, element)
1878
    count = countElementChildren(element, 0)
1879
    if count == 0:
1880
        add(", valueOf_=''")
1881
    if element.isMixed():
1882
        add(", mixedclass_=None")
1883
        add(", content_=None")
1884
    s1 = "".join(content)
1885
    return s1
1886

1887

1888
def buildCtorArgs_multilevel_aux(add, element):
1889
    buildCtorArgs_aux(add, element)
1890
    base = element.getBase()
1891
    if base and base in ElementDict:
1892
        parent = ElementDict[base]
1893
        buildCtorArgs_multilevel_aux(add, parent)
1894

1895

1896
def buildCtorArgs_1_level(element):
1897
    content = []
1898
    add = content.append
1899
    buildCtorArgs_aux(add, element)
1900
    count = countElementChildren(element, 0)
1901
    if count == 0:
1902
        add(", valueOf_=''")
1903
    s1 = "".join(content)
1904
    return s1
1905

1906

1907
def buildCtorArgs_aux(add, element):
1908
    attrDefs = element.getAttributeDefs()
1909
    for key in attrDefs:
1910
        attrDef = attrDefs[key]
1911
        name = attrDef.getName()
1912
        mappedName = name.replace(":", "_")
1913
        mappedName = cleanupName(mapName(mappedName))
1914
        try:
1915
            atype = attrDef.getData_type()
1916
        except KeyError:
1917
            atype = StringType
1918
        if atype in StringType or atype == TokenType or atype == DateTimeType or atype == DateType:
1919
            add(", %s=''" % mappedName)
1920
        elif atype in IntegerType:
1921
            add(", %s=-1" % mappedName)
1922
        elif atype == PositiveIntegerType:
1923
            add(", %s=1" % mappedName)
1924
        elif atype == NonPositiveIntegerType:
1925
            add(", %s=0" % mappedName)
1926
        elif atype == NegativeIntegerType:
1927
            add(", %s=-1" % mappedName)
1928
        elif atype == NonNegativeIntegerType:
1929
            add(", %s=0" % mappedName)
1930
        elif atype == BooleanType:
1931
            add(", %s=0" % mappedName)
1932
        elif atype == FloatType or atype == DoubleType or atype == DecimalType:
1933
            add(", %s=0.0" % mappedName)
1934
        else:
1935
            add(", %s=None" % mappedName)
1936
    nestedElements = 0
1937
    for child in element.getChildren():
1938
        nestedElements = 1
1939
        if child.getMaxOccurs() > 1:
1940
            add(", %s=None" % child.getCleanName())
1941
        else:
1942
            childType = child.getType()
1943
            if (
1944
                childType in StringType
1945
                or childType == TokenType
1946
                or childType == DateTimeType
1947
                or childType == DateType
1948
            ):
1949
                add(", %s=''" % child.getCleanName())
1950
            elif childType in IntegerType:
1951
                add(", %s=-1" % child.getCleanName())
1952
            elif childType == PositiveIntegerType:
1953
                add(", %s=1" % child.getCleanName())
1954
            elif childType == NonPositiveIntegerType:
1955
                add(", %s=0" % child.getCleanName())
1956
            elif childType == NegativeIntegerType:
1957
                add(", %s=-1" % child.getCleanName())
1958
            elif childType == NonNegativeIntegerType:
1959
                add(", %s=0" % child.getCleanName())
1960
            elif childType == BooleanType:
1961
                add(", %s=0" % child.getCleanName())
1962
            elif childType == FloatType or childType == DoubleType or childType == DecimalType:
1963
                add(", %s=0.0" % child.getCleanName())
1964
            else:
1965
                add(", %s=None" % child.getCleanName())
1966

1967

1968
MixedCtorInitializers = """\
1969
        if mixedclass_ is None:
1970
            self.mixedclass_ = MixedContainer
1971
        else:
1972
            self.mixedclass_ = mixedclass_
1973
        if content_ is None:
1974
            self.content_ = []
1975
        else:
1976
            self.content_ = content_
1977
"""
1978

1979

1980
def generateCtor(outfile, element):
1981
    s2 = buildCtorArgs_multilevel(element)
1982
    s1 = "    def __init__(self%s):\n" % s2
1983
    outfile.write(s1)
1984
    base = element.getBase()
1985
    if base and base in ElementDict:
1986
        parent = ElementDict[base]
1987
        s2 = buildCtorParams(parent)
1988
        s1 = "        %s.__init__(self%s)\n" % (
1989
            base,
1990
            s2,
1991
        )
1992
        outfile.write(s1)
1993
    attrDefs = element.getAttributeDefs()
1994
    for key in attrDefs:
1995
        attrDef = attrDefs[key]
1996
        mappedName = cleanupName(attrDef.getName())
1997
        mappedName = mapName(mappedName)
1998
        s1 = "        self.%s = %s\n" % (mappedName, mappedName)
1999
        outfile.write(s1)
2000
        member = 1
2001
    # Generate member initializers in ctor.
2002
    if element.isMixed():
2003
        outfile.write(MixedCtorInitializers)
2004
    else:
2005
        member = 0
2006
        nestedElements = 0
2007
        for child in element.getChildren():
2008
            name = cleanupName(child.getCleanName())
2009
            if child.getMaxOccurs() > 1:
2010
                s1 = "        if %s is None:\n" % (name,)
2011
                outfile.write(s1)
2012
                s1 = "            self.%s = []\n" % (name,)
2013
                outfile.write(s1)
2014
                s1 = "        else:\n"
2015
                outfile.write(s1)
2016
                s1 = "            self.%s = %s\n" % (name, name)
2017
                outfile.write(s1)
2018
            else:
2019
                s1 = "        self.%s = %s\n" % (name, name)
2020
                outfile.write(s1)
2021
            member = 1
2022
            nestedElements = 1
2023
        if not nestedElements:
2024
            s1 = "        self.valueOf_ = valueOf_\n"
2025
            outfile.write(s1)
2026
            member = 1
2027
        if element.getAnyAttribute():
2028
            s1 = "        self.anyAttributes_ = {}\n"
2029
            outfile.write(s1)
2030
            member = 1
2031
        if not member:
2032
            outfile.write("        pass\n")
2033

2034

2035
# Generate get/set/add member functions.
2036
def generateGettersAndSetters(outfile, element):
2037
    nestedElements = 0
2038
    for child in element.getChildren():
2039
        nestedElements = 1
2040
        name = cleanupName(child.getCleanName())
2041
        unmappedName = cleanupName(child.getName())
2042
        capName = unmappedName.capitalize()
2043
        s1 = "    def get%s(self): return self.%s\n" % (capName, name)
2044
        outfile.write(s1)
2045
        s1 = "    def set%s(self, %s): self.%s = %s\n" % (capName, name, name, name)
2046
        outfile.write(s1)
2047
        if child.getMaxOccurs() > 1:
2048
            s1 = "    def add%s(self, value): self.%s.append(value)\n" % (capName, name)
2049
            outfile.write(s1)
2050
            s1 = "    def insert%s(self, index, value): self.%s[index] = value\n" % (
2051
                capName,
2052
                name,
2053
            )
2054
            outfile.write(s1)
2055
        if GenerateProperties:
2056
            s1 = "    %sProp = property(get%s, set%s)\n" % (
2057
                unmappedName,
2058
                capName,
2059
                capName,
2060
            )
2061
            outfile.write(s1)
2062
    attrDefs = element.getAttributeDefs()
2063
    for key in attrDefs:
2064
        attrDef = attrDefs[key]
2065
        name = cleanupName(attrDef.getName().replace(":", "_"))
2066
        mappedName = mapName(name)
2067
        capName = mappedName.capitalize()
2068
        s1 = "    def get%s(self): return self.%s\n" % (name.capitalize(), mappedName)
2069
        outfile.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:
2081
        s1 = "    def set%s(self, %s): self.%s = %s\n" % (
2082
            name.capitalize(),
2083
            mappedName,
2084
            mappedName,
2085
            mappedName,
2086
        )
2087
        outfile.write(s1)
2088
        if GenerateProperties:
2089
            s1 = "    %sProp = property(get%s, set%s)\n" % (
2090
                mappedName,
2091
                capName,
2092
                capName,
2093
            )
2094
            outfile.write(s1)
2095
    if not nestedElements:
2096
        s1 = "    def getValueOf_(self): return self.valueOf_\n"
2097
        outfile.write(s1)
2098
        s1 = "    def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_\n"
2099
        outfile.write(s1)
2100
    if element.getAnyAttribute():
2101
        s1 = "    def getAnyAttributes_(self): return self.anyAttributes_\n"
2102
        outfile.write(s1)
2103
        s1 = "    def setAnyAttributes_(self, anyAttributes_): self.anyAttributes_ = anyAttributes_\n"
2104
        outfile.write(s1)
2105

2106

2107
def generateClasses(outfile, prefix, element, delayed):
2108
    base = element.getBase()
2109
    wrt = outfile.write
2110
    if (not element.getChildren()) and (not element.getAttributeDefs()):
2111
        return
2112
    # If this element is an extension (has a base) and the base has
2113
    #   not been generated, then postpone it.
2114
    if base and base in ElementDict:
2115
        parent = ElementDict[base]
2116
        parentName = parent.getName()
2117
        if parentName not in AlreadyGenerated:
2118
            PostponedExtensions.append(element)
2119
            return
2120
    if element.getName() in AlreadyGenerated:
2121
        return
2122
    AlreadyGenerated.append(element.getName())
2123
    if element.getMixedExtensionError():
2124
        print(
2125
            "*** Element %s extension chain contains mixed and non-mixed content.  Not generated."
2126
            % (element.getName(),)
2127
        )
2128
        return
2129
    ElementsForSubclasses.append(element)
2130
    name = element.getCleanName()
2131
    if GenerateProperties:
2132
        if base:
2133
            s1 = "class %s%s(object, %s):\n" % (prefix, name, base)
2134
        else:
2135
            s1 = "class %s%s(object):\n" % (prefix, name)
2136
    else:
2137
        if base:
2138
            s1 = "class %s%s(%s):\n" % (prefix, name, base)
2139
        else:
2140
            s1 = "class %s%s:\n" % (prefix, name)
2141
    wrt(s1)
2142
    wrt("    subclass = None\n")
2143
    generateCtor(outfile, element)
2144
    wrt("    def factory(*args_, **kwargs_):\n")
2145
    wrt("        if %s%s.subclass:\n" % (prefix, name))
2146
    wrt("            return %s%s.subclass(*args_, **kwargs_)\n" % (prefix, name))
2147
    wrt("        else:\n")
2148
    wrt("            return %s%s(*args_, **kwargs_)\n" % (prefix, name))
2149
    wrt("    factory = staticmethod(factory)\n")
2150
    generateGettersAndSetters(outfile, element)
2151
    generateExportFn(outfile, prefix, element)
2152
    generateExportLiteralFn(outfile, prefix, element)
2153
    generateBuildFn(outfile, prefix, element, delayed)
2154
    wrt("# end class %s\n" % name)
2155
    wrt("\n\n")
2156

2157

2158
#
2159
# Generate the SAX handler class for SAX parsing.
2160
#
2161

2162
SAX_STARTELEMENT_1 = """\
2163
    def startElement(self, name, attrs):
2164
        done = 0
2165
        if name == '%s':
2166
            obj = %s.factory()
2167
            stackObj = SaxStackElement('%s', obj)
2168
            self.stack.append(stackObj)
2169
            done = 1
2170
"""
2171

2172
SAX_STARTELEMENT_2 = """\
2173
            stackObj = SaxStackElement('%s', obj)
2174
            self.stack.append(stackObj)
2175
            done = 1
2176
"""
2177

2178
SAX_STARTELEMENT_3 = """\
2179
            stackObj = SaxStackElement('%s', None)
2180
            self.stack.append(stackObj)
2181
            done = 1
2182
"""
2183

2184
SAX_STARTELEMENT_4 = """\
2185
        if not done:
2186
            self.reportError('"%s" element not allowed here.' % name)
2187
"""
2188

2189
SAX_ATTR_INTEGER = """\
2190
            val = attrs.get('%s', None)
2191
            if val is not None:
2192
                try:
2193
                    obj.set%s(int(val))
2194
                except:
2195
                    self.reportError('"%s" attribute must be integer')
2196
"""
2197

2198
SAX_ATTR_BOOLEAN = """\
2199
            val = attrs.get('%s', None)
2200
            if val is not None:
2201
                if val in ('true', '1'):
2202
                    obj.set%s(1)
2203
                elif val in ('false', '0'):
2204
                    obj.set%s(0)
2205
                else:
2206
                    self.reportError('"%s" attribute must be boolean ("true", "1", "false", "0")')
2207
"""
2208

2209
SAX_ATTR_FLOAT = """\
2210
            val = attrs.get('%s', None)
2211
            if val is not None:
2212
                try:
2213
                    obj.set%s(float(val))
2214
                except:
2215
                    self.reportError('"%s" attribute must be float')
2216
"""
2217

2218
SAX_ATTR_STRING = """\
2219
            val = attrs.get('%s', None)
2220
            if val is not None:
2221
                obj.set%s(val)
2222
"""
2223

2224

2225
def getClassName(element):
2226
    name = element.getCleanName()
2227
    return name
2228

2229

2230
def generateSaxAttributes(wrt, element):
2231
    attrDefs = element.getAttributeDefs()
2232
    for key in attrDefs:
2233
        attrDef = attrDefs[key]
2234
        name = attrDef.getName()
2235
        atype = attrDef.getData_type()
2236
        if atype in IntegerType:
2237
            s1 = SAX_ATTR_INTEGER % (name, name.capitalize(), name)
2238
            wrt(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)
2250
        elif atype == BooleanType:
2251
            s1 = SAX_ATTR_BOOLEAN % (name, name.capitalize(), name.capitalize(), name)
2252
            wrt(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)
2272
        elif atype == FloatType or atype == DoubleType or atype == DecimalType:
2273
            s1 = SAX_ATTR_FLOAT % (name, name.capitalize(), name)
2274
            wrt(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)
2286
        else:
2287
            # Assume attr['type'] in StringType or attr['type'] == DateTimeType:
2288
            s1 = SAX_ATTR_STRING % (name, name.capitalize())
2289
            wrt(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

2298
def generateSAXStartElement_1(wrt, element):
2299
    origName = element.getName()
2300
    typeName = cleanupName(mapName(element.getRawType()))
2301
    className = element.getCleanName()
2302
    s1 = "        elif name == '%s':\n" % origName
2303
    wrt(s1)
2304
    if element.isComplex():
2305
        s1 = "            obj = %s.factory()\n" % cleanupName(typeName)
2306
        wrt(s1)
2307
    element1 = SaxElementDict[element.getCleanName()]
2308
    generateSaxAttributes(wrt, element1)
2309
    if element.isComplex():
2310
        s1 = SAX_STARTELEMENT_2 % className
2311
    else:
2312
        s1 = SAX_STARTELEMENT_3 % className
2313
    wrt(s1)
2314

2315

2316
def generateSAXStartElement(outfile, root, elementList):
2317
    wrt = outfile.write
2318
    name = root.getChildren()[0].getName()
2319
    s1 = SAX_STARTELEMENT_1 % (name, name, name)
2320
    wrt(s1)
2321
    for element, parent in elementList:
2322
        generateSAXStartElement_1(wrt, element)
2323
    s1 = SAX_STARTELEMENT_4
2324
    wrt(s1)
2325
    wrt("\n")
2326

2327

2328
SAX_ENDELEMENT_1 = """\
2329
        if name == '%s':
2330
            if len(self.stack) == 1:
2331
                self.root = self.stack[-1].obj
2332
                self.stack.pop()
2333
                done = 1
2334
"""
2335

2336
SAX_ENDELEMENT_2 = """\
2337
        elif name == '%s':
2338
            if len(self.stack) >= 2:
2339
                self.stack[-2].obj.%s%s(self.stack[-1].obj)
2340
                self.stack.pop()
2341
                done = 1
2342
"""
2343

2344
SAX_ENDELEMENT_3 = """\
2345
        elif name == '%s':
2346
            if len(self.stack) >= 2:
2347
                content = self.stack[-1].content
2348
%s                self.stack[-2].obj.%s%s(content)
2349
                self.stack.pop()
2350
                done = 1
2351
"""
2352

2353
SAX_ENDELEMENT_INT = """\
2354
                if content:
2355
                    try:
2356
                        content = int(content)
2357
                    except:
2358
                        self.reportError('"%s" must be integer -- content: %%s' %% content)
2359
                else:
2360
                    content = -1
2361
"""
2362

2363
SAX_ENDELEMENT_FLOAT = """\
2364
                if content:
2365
                    try:
2366
                        content = float(content)
2367
                    except:
2368
                        self.reportError('"%s" must be float -- content: %%s' %% content)
2369
                else:
2370
                    content = -1
2371
"""
2372

2373
SAX_ENDELEMENT_BOOLEAN = """\
2374
                if content and content in ('true', '1'):
2375
                    content = 1
2376
                else:
2377
                    content = 0
2378
"""
2379

2380
SAX_ENDELEMENT_4 = """\
2381
        if not done:
2382
            self.reportError('"%s" element not allowed here.' % name)
2383
"""
2384

2385

2386
def generateParentCheck(parent):
2387
    s1 = "self.stack[-2].name == '%s'" % getClassName(parent)
2388
    return 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

2401
def generateSAXEndElement(outfile, root, elementList):
2402
    wrt = outfile.write
2403
    s1 = "    def endElement(self, name):\n"
2404
    wrt(s1)
2405
    s1 = "        done = 0\n"
2406
    wrt(s1)
2407
    name = root.getChildren()[0].getName()
2408
    s1 = SAX_ENDELEMENT_1 % (name,)
2409
    wrt(s1)
2410
    for element, parent in elementList:
2411
        # s2 = generateParentCheck(parent)
2412
        name = element.getName()
2413
        capName = element.getUnmappedCleanName().capitalize()
2414
        if element.isComplex():
2415
            if element.getMaxOccurs() > 1:
2416
                s1 = SAX_ENDELEMENT_2 % (name, "add", capName)
2417
            else:
2418
                s1 = SAX_ENDELEMENT_2 % (name, "set", capName)
2419
        else:
2420
            etype = element.getType()
2421
            if etype in IntegerType:
2422
                s3 = SAX_ENDELEMENT_INT % name
2423
            elif etype == FloatType or etype == DoubleType or etype == DecimalType:
2424
                s3 = SAX_ENDELEMENT_FLOAT % name
2425
            elif etype == BooleanType:
2426
                s3 = SAX_ENDELEMENT_BOOLEAN
2427
            else:
2428
                s3 = ""
2429
            if element.getMaxOccurs() > 1:
2430
                s1 = SAX_ENDELEMENT_3 % (name, s3, "add", capName)
2431
            else:
2432
                s1 = SAX_ENDELEMENT_3 % (name, s3, "set", capName)
2433
        wrt(s1)
2434
    s1 = SAX_ENDELEMENT_4
2435
    wrt(s1)
2436
    wrt("\n")
2437

2438

2439
SAX_HEADER = """\
2440
from xml.sax import handler, make_parser
2441

2442
class SaxStackElement:
2443
    def __init__(self, name='', obj=None):
2444
        self.name = name
2445
        self.obj = obj
2446
        self.content = ''
2447

2448
#
2449
# SAX handler
2450
#
2451
class Sax%sHandler(handler.ContentHandler):
2452
    def __init__(self):
2453
        self.stack = []
2454
        self.root = None
2455

2456
    def getRoot(self):
2457
        return self.root
2458

2459
    def setDocumentLocator(self, locator):
2460
        self.locator = locator
2461

2462
    def showError(self, msg):
2463
        print('*** (showError):', msg)
2464
        sys.exit(-1)
2465

2466
"""
2467

2468
SAX_FOOTER = """\
2469
    def characters(self, chrs, start, end):
2470
        if len(self.stack) > 0:
2471
            self.stack[-1].content += chrs[start:end]
2472

2473
    def reportError(self, mesg):
2474
        locator = self.locator
2475
        sys.stderr.write('Doc: %s  Line: %d  Column: %d\\n' % \\
2476
            (locator.getSystemId(), locator.getLineNumber(),
2477
            locator.getColumnNumber() + 1))
2478
        sys.stderr.write(mesg)
2479
        sys.stderr.write('\\n')
2480
        sys.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.
2503
def produceAllElements_nogen(element, parent, collection):
2504
    collection.append((element, parent))
2505
    for child in element.getChildren():
2506
        produceAllElements_nogen(child, element, collection)
2507

2508

2509
def generateSAXHndlr(outfile, root):
2510
    firstElement = root.getChildren()[0]
2511
    name = firstElement.getName()
2512
    s1 = SAX_HEADER % cleanupName(name.capitalize())
2513
    outfile.write(s1)
2514
    elementList = []
2515
    collection = []
2516
    produceAllElements_nogen(root, None, collection)
2517
    for element, parent in collection:
2518
        if element == root:
2519
            continue
2520
        elementList.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]
2531
    elementList1 = []
2532
    alreadySeen = []
2533
    for element, parent in elementList:
2534
        if parent == root:
2535
            continue
2536
        if element.getName() in alreadySeen:
2537
            continue
2538
        alreadySeen.append(element.getName())
2539
        elementList1.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))
2546
    generateSAXStartElement(outfile, root, elementList1)
2547
    generateSAXEndElement(outfile, root, elementList1)
2548
    s1 = SAX_FOOTER
2549
    outfile.write(s1)
2550

2551

2552
def collect(element, elements):
2553
    if element.getName() != "root":
2554
        elements.append(element)
2555
    for child in element.getChildren():
2556
        collect(child, elements)
2557

2558

2559
TEMPLATE_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

2570
import sys
2571
import getopt
2572
from xml.dom import minidom
2573
from 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

2594
def showIndent(outfile, level):
2595
    for idx in range(level):
2596
        outfile.write('    ')
2597

2598
def quote_xml(inStr):
2599
    s1 = inStr
2600
    s1 = s1.replace('&', '&amp;')
2601
    s1 = s1.replace('<', '&lt;')
2602
    s1 = s1.replace('"', '&quot;')
2603
    return s1
2604

2605
def quote_python(inStr):
2606
    s1 = inStr
2607
    if s1.find("'") == -1:
2608
        if s1.find('\\n') == -1:
2609
            return "'%%s'" %% s1
2610
        else:
2611
            return "'''%%s'''" %% s1
2612
    else:
2613
        if s1.find('"') != -1:
2614
            s1 = s1.replace('"', '\\\\"')
2615
        if s1.find('\\n') == -1:
2616
            return '"%%s"' %% s1
2617
        else:
2618
            return '\"\"\"%%s\"\"\"' %% s1
2619

2620

2621
class MixedContainer:
2622
    # Constants for category:
2623
    CategoryNone = 0
2624
    CategoryText = 1
2625
    CategorySimple = 2
2626
    CategoryComplex = 3
2627
    # Constants for content_type:
2628
    TypeNone = 0
2629
    TypeText = 1
2630
    TypeString = 2
2631
    TypeInteger = 3
2632
    TypeFloat = 4
2633
    TypeDecimal = 5
2634
    TypeDouble = 6
2635
    TypeBoolean = 7
2636
    def __init__(self, category, content_type, name, value):
2637
        self.category = category
2638
        self.content_type = content_type
2639
        self.name = name
2640
        self.value = value
2641
    def getCategory(self):
2642
        return self.category
2643
    def getContenttype(self, content_type):
2644
        return self.content_type
2645
    def getValue(self):
2646
        return self.value
2647
    def getName(self):
2648
        return self.name
2649
    def export(self, outfile, level, name):
2650
        if self.category == MixedContainer.CategoryText:
2651
            outfile.write(self.value)
2652
        elif self.category == MixedContainer.CategorySimple:
2653
            self.exportSimple(outfile, level, name)
2654
        else:    # category == MixedContainer.CategoryComplex
2655
            self.value.export(outfile, level, name)
2656
    def exportSimple(self, outfile, level, name):
2657
        if self.content_type == MixedContainer.TypeString:
2658
            outfile.write('<%%s>%%s</%%s>' %% (self.name, self.value, self.name))
2659
        elif self.content_type == MixedContainer.TypeInteger or \\
2660
                self.content_type == MixedContainer.TypeBoolean:
2661
            outfile.write('<%%s>%%d</%%s>' %% (self.name, self.value, self.name))
2662
        elif self.content_type == MixedContainer.TypeFloat or \\
2663
                self.content_type == MixedContainer.TypeDecimal:
2664
            outfile.write('<%%s>%%f</%%s>' %% (self.name, self.value, self.name))
2665
        elif self.content_type == MixedContainer.TypeDouble:
2666
            outfile.write('<%%s>%%g</%%s>' %% (self.name, self.value, self.name))
2667
    def exportLiteral(self, outfile, level, name):
2668
        if self.category == MixedContainer.CategoryText:
2669
            showIndent(outfile, level)
2670
            outfile.write('MixedContainer(%%d, %%d, "%%s", "%%s"),\\n' %% \\
2671
                (self.category, self.content_type, self.name, self.value))
2672
        elif self.category == MixedContainer.CategorySimple:
2673
            showIndent(outfile, level)
2674
            outfile.write('MixedContainer(%%d, %%d, "%%s", "%%s"),\\n' %% \\
2675
                (self.category, self.content_type, self.name, self.value))
2676
        else:    # category == MixedContainer.CategoryComplex
2677
            showIndent(outfile, level)
2678
            outfile.write('MixedContainer(%%d, %%d, "%%s",\\n' %% \\
2679
                (self.category, self.content_type, self.name,))
2680
            self.value.exportLiteral(outfile, level + 1)
2681
            showIndent(outfile, level)
2682
            outfile.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

2695
def generateHeader(outfile, prefix):
2696
    s1 = TEMPLATE_HEADER % time.ctime()
2697
    outfile.write(s1)
2698

2699

2700
TEMPLATE_MAIN = """\
2701
USAGE_TEXT = \"\"\"
2702
Usage: python <%(prefix)sParser>.py [ -s ] <in_xml_file>
2703
Options:
2704
    -s        Use the SAX parser, not the minidom parser.
2705
\"\"\"
2706

2707
def usage():
2708
    print(USAGE_TEXT)
2709
    sys.exit(-1)
2710

2711

2712
#
2713
# SAX handler used to determine the top level element.
2714
#
2715
class SaxSelectorHandler(handler.ContentHandler):
2716
    def __init__(self):
2717
        self.topElementName = None
2718
    def getTopElementName(self):
2719
        return self.topElementName
2720
    def startElement(self, name, attrs):
2721
        self.topElementName = name
2722
        raise StopIteration
2723

2724

2725
def parseSelect(inFileName):
2726
    infile = open(inFileName, 'r')
2727
    topElementName = None
2728
    parser = make_parser()
2729
    documentHandler = SaxSelectorHandler()
2730
    parser.setContentHandler(documentHandler)
2731
    try:
2732
        try:
2733
            parser.parse(infile)
2734
        except StopIteration:
2735
            topElementName = documentHandler.getTopElementName()
2736
        if topElementName is None:
2737
            raise RuntimeError('no top level element')
2738
        topElementName = topElementName.replace('-', '_').replace(':', '_')
2739
        if topElementName not in globals():
2740
            raise RuntimeError('no class for top element: %%s' %% topElementName)
2741
        topElement = globals()[topElementName]
2742
        infile.seek(0)
2743
        doc = minidom.parse(infile)
2744
    finally:
2745
        infile.close()
2746
    rootNode = doc.childNodes[0]
2747
    rootObj = topElement.factory()
2748
    rootObj.build(rootNode)
2749
    # Enable Python to collect the space used by the DOM.
2750
    doc = None
2751
    sys.stdout.write('<?xml version="1.0" ?>\\n')
2752
    rootObj.export(sys.stdout, 0)
2753
    return rootObj
2754

2755

2756
def saxParse(inFileName):
2757
    parser = make_parser()
2758
    documentHandler = Sax%(cap_name)sHandler()
2759
    parser.setDocumentHandler(documentHandler)
2760
    parser.parse('file:%%s' %% inFileName)
2761
    root = documentHandler.getRoot()
2762
    sys.stdout.write('<?xml version="1.0" ?>\\n')
2763
    root.export(sys.stdout, 0)
2764
    return root
2765

2766

2767
def saxParseString(inString):
2768
    parser = make_parser()
2769
    documentHandler = Sax%(cap_name)sHandler()
2770
    parser.setDocumentHandler(documentHandler)
2771
    parser.feed(inString)
2772
    parser.close()
2773
    rootObj = documentHandler.getRoot()
2774
    #sys.stdout.write('<?xml version="1.0" ?>\\n')
2775
    #rootObj.export(sys.stdout, 0)
2776
    return rootObj
2777

2778

2779
def parse(inFileName):
2780
    doc = minidom.parse(inFileName)
2781
    rootNode = doc.documentElement
2782
    rootObj = %(prefix)s%(root)s.factory()
2783
    rootObj.build(rootNode)
2784
    # Enable Python to collect the space used by the DOM.
2785
    doc = None
2786
    sys.stdout.write('<?xml version="1.0" ?>\\n')
2787
    rootObj.export(sys.stdout, 0, name_="%(name)s")
2788
    return rootObj
2789

2790

2791
def parseString(inString):
2792
    doc = minidom.parseString(inString)
2793
    rootNode = doc.documentElement
2794
    rootObj = %(prefix)s%(root)s.factory()
2795
    rootObj.build(rootNode)
2796
    # Enable Python to collect the space used by the DOM.
2797
    doc = None
2798
    sys.stdout.write('<?xml version="1.0" ?>\\n')
2799
    rootObj.export(sys.stdout, 0, name_="%(name)s")
2800
    return rootObj
2801

2802

2803
def parseLiteral(inFileName):
2804
    doc = minidom.parse(inFileName)
2805
    rootNode = doc.documentElement
2806
    rootObj = %(prefix)s%(root)s.factory()
2807
    rootObj.build(rootNode)
2808
    # Enable Python to collect the space used by the DOM.
2809
    doc = None
2810
    sys.stdout.write('from %(module_name)s import *\\n\\n')
2811
    sys.stdout.write('rootObj = %(name)s(\\n')
2812
    rootObj.exportLiteral(sys.stdout, 0, name_="%(name)s")
2813
    sys.stdout.write(')\\n')
2814
    return rootObj
2815

2816

2817
def main():
2818
    args = sys.argv[1:]
2819
    if len(args) == 2 and args[0] == '-s':
2820
        saxParse(args[1])
2821
    elif len(args) == 1:
2822
        parse(args[0])
2823
    else:
2824
        usage()
2825

2826

2827
if __name__ == '__main__':
2828
    main()
2829
    #import pdb
2830
    #pdb.run('main()')
2831

2832
"""
2833

2834

2835
# Fool (and straighten out) the syntax highlighting.
2836
# DUMMY = '''
2837

2838

2839
def generateMain(outfile, prefix, root):
2840
    name = root.getChildren()[0].getName()
2841
    elType = cleanupName(root.getChildren()[0].getType())
2842
    if RootElement:
2843
        rootElement = RootElement
2844
    else:
2845
        rootElement = elType
2846
    params = {
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
    }
2853
    s1 = TEMPLATE_MAIN % params
2854
    outfile.write(s1)
2855

2856

2857
def buildCtorParams(element):
2858
    content = []
2859
    add = content.append
2860
    if element.isMixed():
2861
        add(", mixedclass_")
2862
        add(", content_")
2863
    else:
2864
        buildCtorParams_aux(add, element)
2865
    s1 = "".join(content)
2866
    return s1
2867

2868

2869
def buildCtorParams_aux(add, element):
2870
    attrDefs = element.getAttributeDefs()
2871
    for key in attrDefs:
2872
        attrDef = attrDefs[key]
2873
        name = attrDef.getName()
2874
        cleanName = cleanupName(mapName(name))
2875
        add(", %s" % cleanName)
2876
    for child in element.getChildren():
2877
        add(", %s" % child.getCleanName())
2878
    base = element.getBase()
2879
    if base and base in ElementDict:
2880
        parent = ElementDict[base]
2881
        buildCtorParams_aux(add, parent)
2882

2883

2884
def get_class_behavior_args(classBehavior):
2885
    argList = []
2886
    args = classBehavior.getArgs()
2887
    args = args.getArg()
2888
    # print '(get_class_behavior_args) args:', args
2889
    for arg in args:
2890
        argList.append(arg.getName())
2891
    argString = ", ".join(argList)
2892
    return 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
#
2902
def get_impl_body(classBehavior, baseImplUrl, implUrl):
2903
    impl = "        pass\n"
2904
    if implUrl:
2905
        if baseImplUrl:
2906
            implUrl = "%s%s" % (baseImplUrl, implUrl)
2907
        try:
2908
            implFile = urlopen(implUrl)
2909
            impl = implFile.read()
2910
            implFile.close()
2911
        except HTTPError:
2912
            print("*** Implementation at %s not found." % implUrl)
2913
    return 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

2944
def generateClassBehaviors(wrt, classBehaviors, baseImplUrl):
2945
    for classBehavior in classBehaviors:
2946
        behaviorName = classBehavior.getName()
2947
        #
2948
        # Generate the core behavior.
2949
        argString = get_class_behavior_args(classBehavior)
2950
        if argString:
2951
            wrt("    def %s(self, %s, *args):\n" % (behaviorName, argString))
2952
        else:
2953
            wrt("    def %s(self, *args):\n" % (behaviorName,))
2954
        implUrl = classBehavior.getImpl_url()
2955
        impl = get_impl_body(classBehavior, baseImplUrl, implUrl)
2956
        wrt(impl)
2957
        wrt("\n")
2958
        #
2959
        # Generate the ancillaries for this behavior.
2960
        ancillaries = classBehavior.getAncillaries()
2961
        if ancillaries:
2962
            ancillaries = ancillaries.getAncillary()
2963
        if ancillaries:
2964
            for ancillary in ancillaries:
2965
                argString = get_class_behavior_args(ancillary)
2966
                if argString:
2967
                    wrt("    def %s(self, %s, *args):\n" % (ancillary.getName(), argString))
2968
                else:
2969
                    wrt("    def %s(self, *args):\n" % (ancillary.getName(),))
2970
                implUrl = ancillary.getImpl_url()
2971
                impl = get_impl_body(classBehavior, baseImplUrl, implUrl)
2972
                wrt(impl)
2973
                wrt("\n")
2974
        #
2975
        # Generate the wrapper method that calls the ancillaries and
2976
        #   the core behavior.
2977
        argString = get_class_behavior_args(classBehavior)
2978
        if argString:
2979
            wrt("    def %s_wrapper(self, %s, *args):\n" % (behaviorName, argString))
2980
        else:
2981
            wrt("    def %s_wrapper(self, *args):\n" % (behaviorName,))
2982
        if ancillaries:
2983
            for ancillary in ancillaries:
2984
                role = ancillary.getRole()
2985
                if role == "DBC-precondition":
2986
                    wrt("        if not self.%s(*args)\n" % (ancillary.getName(),))
2987
                    wrt("            return False\n")
2988
        if argString:
2989
            wrt("        result = self.%s(%s, *args)\n" % (behaviorName, argString))
2990
        else:
2991
            wrt("        result = self.%s(*args)\n" % (behaviorName,))
2992
        if ancillaries:
2993
            for ancillary in ancillaries:
2994
                role = ancillary.getRole()
2995
                if role == "DBC-postcondition":
2996
                    wrt("        if not self.%s(*args)\n" % (ancillary.getName(),))
2997
                    wrt("            return False\n")
2998
        wrt("        return result\n")
2999
        wrt("\n")
3000

3001

3002
def generateSubclass(outfile, element, prefix, xmlbehavior, behaviors, baseUrl):
3003
    wrt = outfile.write
3004
    if not element.isComplex():
3005
        return
3006
    if (not element.getChildren()) and (not element.getAttributeDefs()):
3007
        return
3008
    if element.getName() in AlreadyGenerated_subclass:
3009
        return
3010
    AlreadyGenerated_subclass.append(element.getName())
3011
    name = element.getCleanName()
3012
    wrt("class %s%s%s(supermod.%s):\n" % (prefix, name, SubclassSuffix, name))
3013
    s1 = buildCtorArgs_multilevel(element)
3014
    wrt("    def __init__(self%s):\n" % s1)
3015
    s1 = buildCtorParams(element)
3016
    wrt("        supermod.%s%s.__init__(self%s)\n" % (prefix, name, s1))
3017
    if xmlbehavior and behaviors:
3018
        wrt("\n")
3019
        wrt("    #\n")
3020
        wrt("    # XMLBehaviors\n")
3021
        wrt("    #\n")
3022
        # Get a list of behaviors for this class/subclass.
3023
        classDictionary = behaviors.get_class_dictionary()
3024
        if name in classDictionary:
3025
            classBehaviors = classDictionary[name]
3026
        else:
3027
            classBehaviors = None
3028
        if classBehaviors:
3029
            generateClassBehaviors(wrt, classBehaviors, baseUrl)
3030
    wrt("supermod.%s.subclass = %s%s\n" % (name, name, SubclassSuffix))
3031
    wrt("# end class %s%s%s\n" % (prefix, name, SubclassSuffix))
3032
    wrt("\n\n")
3033

3034

3035
TEMPLATE_SUBCLASS_HEADER = """\
3036
#!/usr/bin/env python
3037

3038
#
3039
# Generated %s by generateDS.py.
3040
#
3041

3042
import sys
3043
from xml.dom import minidom
3044
from xml.sax import handler, make_parser
3045

3046
import %s as supermod
3047

3048
"""
3049

3050
TEMPLATE_SUBCLASS_FOOTER = """\
3051

3052
#
3053
# SAX handler used to determine the top level element.
3054
#
3055
class SaxSelectorHandler(handler.ContentHandler):
3056
    def __init__(self):
3057
        self.topElementName = None
3058
    def getTopElementName(self):
3059
        return self.topElementName
3060
    def startElement(self, name, attrs):
3061
        self.topElementName = name
3062
        raise StopIteration
3063

3064

3065
def parseSelect(inFileName):
3066
    infile = open(inFileName, 'r')
3067
    topElementName = None
3068
    parser = make_parser()
3069
    documentHandler = SaxSelectorHandler()
3070
    parser.setContentHandler(documentHandler)
3071
    try:
3072
        try:
3073
            parser.parse(infile)
3074
        except StopIteration:
3075
            topElementName = documentHandler.getTopElementName()
3076
        if topElementName is None:
3077
            raise RuntimeError, 'no top level element'
3078
        topElementName = topElementName.replace('-', '_').replace(':', '_')
3079
        if topElementName not in supermod.__dict__:
3080
            raise RuntimeError, 'no class for top element: %%s' %% topElementName
3081
        topElement = supermod.__dict__[topElementName]
3082
        infile.seek(0)
3083
        doc = minidom.parse(infile)
3084
    finally:
3085
        infile.close()
3086
    rootNode = doc.childNodes[0]
3087
    rootObj = topElement.factory()
3088
    rootObj.build(rootNode)
3089
    # Enable Python to collect the space used by the DOM.
3090
    doc = None
3091
    sys.stdout.write('<?xml version="1.0" ?>\\n')
3092
    rootObj.export(sys.stdout, 0)
3093
    return rootObj
3094

3095

3096
def saxParse(inFileName):
3097
    parser = make_parser()
3098
    documentHandler = supermod.Sax%(cap_name)sHandler()
3099
    parser.setDocumentHandler(documentHandler)
3100
    parser.parse('file:%%s' %% inFileName)
3101
    rootObj = documentHandler.getRoot()
3102
    #sys.stdout.write('<?xml version="1.0" ?>\\n')
3103
    #rootObj.export(sys.stdout, 0)
3104
    return rootObj
3105

3106

3107
def saxParseString(inString):
3108
    parser = make_parser()
3109
    documentHandler = supermod.SaxContentHandler()
3110
    parser.setDocumentHandler(documentHandler)
3111
    parser.feed(inString)
3112
    parser.close()
3113
    rootObj = documentHandler.getRoot()
3114
    #sys.stdout.write('<?xml version="1.0" ?>\\n')
3115
    #rootObj.export(sys.stdout, 0)
3116
    return rootObj
3117

3118

3119
def parse(inFilename):
3120
    doc = minidom.parse(inFilename)
3121
    rootNode = doc.documentElement
3122
    rootObj = supermod.%(root)s.factory()
3123
    rootObj.build(rootNode)
3124
    # Enable Python to collect the space used by the DOM.
3125
    doc = None
3126
    sys.stdout.write('<?xml version="1.0" ?>\\n')
3127
    rootObj.export(sys.stdout, 0, name_="%(name)s")
3128
    doc = None
3129
    return rootObj
3130

3131

3132
def parseString(inString):
3133
    doc = minidom.parseString(inString)
3134
    rootNode = doc.documentElement
3135
    rootObj = supermod.%(root)s.factory()
3136
    rootObj.build(rootNode)
3137
    # Enable Python to collect the space used by the DOM.
3138
    doc = None
3139
    sys.stdout.write('<?xml version="1.0" ?>\\n')
3140
    rootObj.export(sys.stdout, 0, name_="%(name)s")
3141
    return rootObj
3142

3143

3144
def parseLiteral(inFilename):
3145
    doc = minidom.parse(inFilename)
3146
    rootNode = doc.documentElement
3147
    rootObj = supermod.%(root)s.factory()
3148
    rootObj.build(rootNode)
3149
    # Enable Python to collect the space used by the DOM.
3150
    doc = None
3151
    sys.stdout.write('from %(super)s import *\\n\\n')
3152
    sys.stdout.write('rootObj = %(name)s(\\n')
3153
    rootObj.exportLiteral(sys.stdout, 0, name_="%(name)s")
3154
    sys.stdout.write(')\\n')
3155
    return rootObj
3156

3157

3158
USAGE_TEXT = \"\"\"
3159
Usage: python ???.py <infilename>
3160
\"\"\"
3161

3162
def usage():
3163
    print(USAGE_TEXT)
3164
    sys.exit(-1)
3165

3166

3167
def main():
3168
    args = sys.argv[1:]
3169
    if len(args) != 1:
3170
        usage()
3171
    infilename = args[0]
3172
    root = parse(infilename)
3173

3174

3175
if __name__ == '__main__':
3176
    main()
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

3192
def generateSubclasses(root, subclassFilename, behaviorFilename, prefix, superModule="xxx"):
3193
    name = root.getChildren()[0].getName()
3194
    subclassFile = makeFile(subclassFilename)
3195
    if subclassFile:
3196
        # Read in the XMLBehavior file.
3197
        xmlbehavior = None
3198
        behaviors = None
3199
        baseUrl = None
3200
        if behaviorFilename:
3201
            try:
3202
                # Add the correct working directory to the path so that
3203
                #   we use the user/developers local copy.
3204
                sys.path.insert(0, ".")
3205
                import xmlbehavior_sub as xmlbehavior
3206
            except ImportError:
3207
                print("*** You have requested generation of extended methods.")
3208
                print("*** But, no xmlbehavior module is available.")
3209
                print("*** Generation of extended behavior methods is omitted.")
3210
            if xmlbehavior:
3211
                behaviors = xmlbehavior.parse(behaviorFilename)
3212
                behaviors.make_class_dictionary(cleanupName)
3213
                baseUrl = behaviors.getBase_impl_url()
3214
        wrt = subclassFile.write
3215
        wrt(TEMPLATE_SUBCLASS_HEADER % (time.ctime(), superModule))
3216
        for element in ElementsForSubclasses:
3217
            generateSubclass(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)
3232
        name = root.getChildren()[0].getName()
3233
        elType = cleanupName(root.getChildren()[0].getType())
3234
        if RootElement:
3235
            rootElement = RootElement
3236
        else:
3237
            rootElement = elType
3238
        params = {
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
        }
3245
        wrt(TEMPLATE_SUBCLASS_FOOTER % params)
3246
        subclassFile.close()
3247

3248

3249
def generateFromTree(outfile, prefix, elements, processed):
3250
    for element in elements:
3251
        name = element.getCleanName()
3252
        if 1:  # if name not in processed:
3253
            processed.append(name)
3254
            generateClasses(outfile, prefix, element, 0)
3255
            children = element.getChildren()
3256
            if children:
3257
                generateFromTree(outfile, prefix, element.getChildren(), processed)
3258

3259

3260
def generate(outfileName, subclassFilename, behaviorFilename, prefix, root, superModule):
3261
    global 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.
3267
    outfile = None
3268
    if outfileName:
3269
        outfile = makeFile(outfileName)
3270
    if not outfile:
3271
        outfile = os.tmpfile()
3272
    processed = []
3273
    generateHeader(outfile, prefix)
3274
    DelayedElements = []
3275
    DelayedElements_subclass = []
3276
    elements = root.getChildren()
3277
    generateFromTree(outfile, prefix, elements, processed)
3278
    while 1:
3279
        if len(DelayedElements) <= 0:
3280
            break
3281
        element = DelayedElements.pop()
3282
        name = element.getCleanName()
3283
        if name not in processed:
3284
            processed.append(name)
3285
            generateClasses(outfile, prefix, element, 1)
3286
    #
3287
    # Generate the elements that were postponed because we had not
3288
    #   yet generated their base class.
3289
    idx = 0
3290
    while 1:
3291
        if len(PostponedExtensions) <= 0:
3292
            break
3293
        element = PostponedExtensions.pop()
3294
        base = element.getBase()
3295
        if base and base in ElementDict:
3296
            parent = ElementDict[base]
3297
            parentName = parent.getName()
3298
            if parentName not in AlreadyGenerated:
3299
                PostponedExtensions.insert(0, element)
3300
            else:
3301
                idx += 1
3302
                generateClasses(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.
3308
    generateSAXHndlr(outfile, root)
3309
    generateMain(outfile, prefix, root)
3310
    outfile.close()
3311
    if subclassFilename:
3312
        generateSubclasses(root, subclassFilename, behaviorFilename, prefix, superModule)
3313

3314

3315
def makeFile(outFileName):
3316
    global Force
3317
    outFile = None
3318
    if (not Force) and os.path.exists(outFileName):
3319
        reply = input("File %s exists.  Overwrite? (y/n): " % outFileName)
3320
        if reply == "y":
3321
            outFile = open(outFileName, "w")
3322
    else:
3323
        outFile = open(outFileName, "w")
3324
    return outFile
3325

3326

3327
def mapName(oldName):
3328
    global NameTable
3329
    newName = oldName
3330
    if NameTable:
3331
        if oldName in NameTable:
3332
            newName = NameTable[oldName]
3333
    return newName
3334

3335

3336
def cleanupName(oldName):
3337
    newName = oldName.replace(":", "_")
3338
    newName = newName.replace("-", "_")
3339
    return newName
3340

3341

3342
## def mapName(oldName):
3343
##     return '_X_%s' % oldName
3344

3345

3346
def strip_namespace(val):
3347
    return val.split(":")[-1]
3348

3349

3350
def parseAndGenerate(
3351
    outfileName,
3352
    subclassFilename,
3353
    prefix,
3354
    xschemaFileName,
3355
    behaviorFilename,
3356
    superModule="???",
3357
):
3358
    global DelayedElements, DelayedElements_subclass, AlreadyGenerated, SaxDelayedElements, AlreadyGenerated_subclass
3359
    DelayedElements = []
3360
    DelayedElements_subclass = []
3361
    AlreadyGenerated = []
3362
    AlreadyGenerated_subclass = []
3363
    ##    parser = saxexts.make_parser("xml.sax.drivers2.drv_pyexpat")
3364
    parser = make_parser()
3365
    ##    print 'dir(parser):', dir(parser)
3366
    ##    print "Parser: %s" % parser
3367
    dh = XschemaHandler()
3368
    ##    parser.setDocumentHandler(dh)
3369
    parser.setContentHandler(dh)
3370
    parser.parse(xschemaFileName)
3371
    root = dh.getRoot()
3372
    root.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, '[[['
3383
    generate(outfileName, subclassFilename, behaviorFilename, prefix, root, superModule)
3384

3385

3386
USAGE_TEXT = """
3387
Usage: python generateDS.py [ options ] <in_xsd_file>
3388
Options:
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.
3399
                             Default is first element defined in schema.
3400
    --super="XXX"            Super module name in subclass module. Default="???"
3401

3402
Example:
3403
python generateDS.py -o generateModel_Module.py generateMetaModel_Module.xsd
3404
"""
3405

3406

3407
def usage():
3408
    print(USAGE_TEXT)
3409
    sys.exit(-1)
3410

3411

3412
def main():
3413
    global Force, GenerateProperties, SubclassSuffix, RootElement
3414
    args = sys.argv[1:]
3415
    options, args = getopt.getopt(
3416
        args,
3417
        "fyo:s:p:a:b:m",
3418
        [
3419
            "subclass-suffix=",
3420
            "root-element=",
3421
            "super=",
3422
        ],
3423
    )
3424
    prefix = ""
3425
    outFilename = None
3426
    subclassFilename = None
3427
    behaviorFilename = None
3428
    nameSpace = "xs:"
3429
    debug = 0
3430
    superModule = "???"
3431
    for option in options:
3432
        if option[0] == "-p":
3433
            prefix = option[1]
3434
        elif option[0] == "-o":
3435
            outFilename = option[1]
3436
        elif option[0] == "-s":
3437
            subclassFilename = option[1]
3438
        elif option[0] == "-f":
3439
            Force = 1
3440
        elif option[0] == "-a":
3441
            nameSpace = option[1]
3442
        elif option[0] == "-b":
3443
            behaviorFilename = option[1]
3444
        elif option[0] == "-m":
3445
            GenerateProperties = 1
3446
        elif option[0] == "--subclass-suffix":
3447
            SubclassSuffix = option[1]
3448
        elif option[0] == "--root-element":
3449
            RootElement = option[1]
3450
        elif option[0] == "--super":
3451
            superModule = option[1]
3452
    set_type_constants(nameSpace)
3453
    if behaviorFilename and not subclassFilename:
3454
        print("\n*** Error.  -b requires -s")
3455
        usage()
3456
    if len(args) != 1:
3457
        usage()
3458
    xschemaFileName = args[0]
3459
    if debug:
3460
        pass
3461
    else:
3462
        parseAndGenerate(
3463
            outFilename,
3464
            subclassFilename,
3465
            prefix,
3466
            xschemaFileName,
3467
            behaviorFilename,
3468
            superModule=superModule,
3469
        )
3470

3471

3472
if __name__ == "__main__":
3473
    main()
3474
##    import pdb
3475
##    pdb.run('main()')
3476

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.