3476 lines
123 KiB
Python
3476 lines
123 KiB
Python
#!/usr/bin/env python
|
|
|
|
## LICENSE
|
|
|
|
## Copyright (c) 2003 Dave Kuhlman
|
|
|
|
## Permission is hereby granted, free of charge, to any person obtaining
|
|
## a copy of this software and associated documentation files (the
|
|
## "Software"), to deal in the Software without restriction, including
|
|
## without limitation the rights to use, copy, modify, merge, publish,
|
|
## distribute, sublicense, and/or sell copies of the Software, and to
|
|
## permit persons to whom the Software is furnished to do so, subject to
|
|
## the following conditions:
|
|
|
|
## The above copyright notice and this permission notice shall be
|
|
## included in all copies or substantial portions of the Software.
|
|
|
|
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
## IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
## CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
## TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
## SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
import sys
|
|
import os.path
|
|
import time
|
|
import getopt
|
|
from urllib.request import urlopen
|
|
from urllib.error import HTTPError
|
|
from xml.sax import handler, make_parser
|
|
import xml.sax.xmlreader
|
|
|
|
##from IPython.Shell import IPShellEmbed
|
|
##args = ''
|
|
##ipshell = IPShellEmbed(args,
|
|
## banner = 'Dropping into IPython',
|
|
## exit_msg = 'Leaving Interpreter, back to program.')
|
|
|
|
# Then use the following line where and when you want to drop into the
|
|
# IPython shell:
|
|
# ipshell('<some message> -- Entering ipshell.\\nHit Ctrl-D to exit')
|
|
|
|
|
|
#
|
|
# Global variables etc.
|
|
#
|
|
GenerateProperties = 0
|
|
DelayedElements = []
|
|
DelayedElements_subclass = []
|
|
AlreadyGenerated = []
|
|
AlreadyGenerated_subclass = []
|
|
PostponedExtensions = []
|
|
ElementsForSubclasses = []
|
|
ElementDict = {}
|
|
SaxElementDict = {}
|
|
ElementDebugList = []
|
|
Force = 0
|
|
NameTable = {
|
|
"class": "klass",
|
|
"import": "emport",
|
|
"type": "ttype",
|
|
}
|
|
SubclassSuffix = "Sub"
|
|
RootElement = None
|
|
AttributeGroups = {}
|
|
SubstitutionGroups = {}
|
|
#
|
|
# SubstitutionGroups can also include simple types that are
|
|
# not (defined) elements. Keep a list of these simple types.
|
|
# These are simple types defined at top level.
|
|
SimpleElementDict = {}
|
|
|
|
|
|
def set_type_constants(nameSpace):
|
|
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
|
|
AttributeGroupType = nameSpace + "attributeGroup"
|
|
AttributeType = nameSpace + "attribute"
|
|
BooleanType = nameSpace + "boolean"
|
|
ChoiceType = nameSpace + "choice"
|
|
ComplexContentType = nameSpace + "complexContent"
|
|
ComplexTypeType = nameSpace + "complexType"
|
|
AnyAttributeType = nameSpace + "anyAttribute"
|
|
DateTimeType = nameSpace + "dateTime"
|
|
DateType = nameSpace + "date"
|
|
IntegerType = (
|
|
nameSpace + "integer",
|
|
nameSpace + "xs:unsignedShort",
|
|
nameSpace + "short",
|
|
nameSpace + "long",
|
|
)
|
|
# ShortType = nameSpace + 'short'
|
|
# LongType = nameSpace + 'long'
|
|
DecimalType = nameSpace + "decimal"
|
|
PositiveIntegerType = nameSpace + "positiveInteger"
|
|
NegativeIntegerType = nameSpace + "negativeInteger"
|
|
NonPositiveIntegerType = nameSpace + "nonPositiveInteger"
|
|
NonNegativeIntegerType = nameSpace + "nonNegativeInteger"
|
|
DoubleType = nameSpace + "double"
|
|
ElementType = nameSpace + "element"
|
|
ExtensionType = nameSpace + "extension"
|
|
FloatType = nameSpace + "float"
|
|
IDREFSType = nameSpace + "IDREFS"
|
|
IDREFType = nameSpace + "IDREF"
|
|
IDType = nameSpace + "ID"
|
|
SchemaType = nameSpace + "schema"
|
|
SequenceType = nameSpace + "sequence"
|
|
StringType = (
|
|
nameSpace + "string",
|
|
nameSpace + "duration",
|
|
nameSpace + "anyURI",
|
|
)
|
|
TokenType = nameSpace + "token"
|
|
|
|
|
|
#
|
|
# For debugging.
|
|
#
|
|
|
|
# Print only if DEBUG is true.
|
|
DEBUG = 1
|
|
|
|
|
|
def dbgprint(level, msg):
|
|
if DEBUG and level > 0:
|
|
print(msg)
|
|
|
|
|
|
def pplist(lst):
|
|
for count, item in enumerate(lst):
|
|
print("%d. %s" % (count, item))
|
|
|
|
|
|
#
|
|
# Representation of element definition.
|
|
#
|
|
|
|
|
|
def showLevel(outfile, level):
|
|
for idx in range(level):
|
|
outfile.write(" ")
|
|
|
|
|
|
class XschemaElement:
|
|
def __init__(self, attrs):
|
|
self.cleanName = ""
|
|
self.attrs = dict(attrs)
|
|
name_val = ""
|
|
type_val = ""
|
|
ref_val = ""
|
|
if "name" in self.attrs:
|
|
name_val = strip_namespace(self.attrs["name"])
|
|
if "type" in self.attrs:
|
|
# fix
|
|
# type_val = strip_namespace(self.attrs['type'])
|
|
type_val = self.attrs["type"]
|
|
if "ref" in self.attrs:
|
|
ref_val = strip_namespace(self.attrs["ref"])
|
|
if type_val and not name_val:
|
|
name_val = type_val
|
|
if ref_val and not name_val:
|
|
name_val = ref_val
|
|
if ref_val and not type_val:
|
|
type_val = ref_val
|
|
if name_val:
|
|
self.attrs["name"] = name_val
|
|
if type_val:
|
|
self.attrs["type"] = type_val
|
|
if ref_val:
|
|
self.attrs["ref"] = ref_val
|
|
self.name = name_val
|
|
self.children = []
|
|
self.maxOccurs = 1
|
|
self.complex = 0
|
|
self.complexType = 0
|
|
self.type = "NoneType"
|
|
self.mixed = 0
|
|
self.base = None
|
|
self.mixedExtensionError = 0
|
|
# Attribute definitions for the correct element.
|
|
self.attributeDefs = {}
|
|
# Attribute definitions for the current attributeGroup, if there is one.
|
|
self.attributeGroup = None
|
|
# List of names of attributes for this element.
|
|
# We will add the attribute definitions in each of these groups
|
|
# to this element in annotate().
|
|
self.attributeGroupNameList = []
|
|
self.topLevel = 0
|
|
# Does this element contain an anyAttribute?
|
|
self.anyAttribute = 0
|
|
|
|
def addChild(self, element):
|
|
self.children.append(element)
|
|
|
|
def getChildren(self):
|
|
return self.children
|
|
|
|
def getName(self):
|
|
return self.name
|
|
|
|
def getCleanName(self):
|
|
return self.cleanName
|
|
|
|
def getUnmappedCleanName(self):
|
|
return self.unmappedCleanName
|
|
|
|
def setName(self, name):
|
|
self.name = name
|
|
|
|
def getAttrs(self):
|
|
return self.attrs
|
|
|
|
def setAttrs(self, attrs):
|
|
self.attrs = attrs
|
|
|
|
def getMaxOccurs(self):
|
|
return self.maxOccurs
|
|
|
|
def getRawType(self):
|
|
return self.type
|
|
|
|
def getType(self):
|
|
returnType = self.type
|
|
if self.type in ElementDict:
|
|
typeObj = ElementDict[self.type]
|
|
typeObjType = typeObj.getRawType()
|
|
if (
|
|
typeObjType in StringType
|
|
or typeObjType == TokenType
|
|
or typeObjType == DateTimeType
|
|
or typeObjType == DateType
|
|
or typeObjType in IntegerType
|
|
or typeObjType == DecimalType
|
|
or typeObjType == PositiveIntegerType
|
|
or typeObjType == NegativeIntegerType
|
|
or typeObjType == NonPositiveIntegerType
|
|
or typeObjType == NonNegativeIntegerType
|
|
or typeObjType == BooleanType
|
|
or typeObjType == FloatType
|
|
or typeObjType == DoubleType
|
|
):
|
|
returnType = typeObjType
|
|
return returnType
|
|
|
|
def isComplex(self):
|
|
return self.complex
|
|
|
|
def addAttributeDefs(self, attrs):
|
|
self.attributeDefs.append(attrs)
|
|
|
|
def getAttributeDefs(self):
|
|
return self.attributeDefs
|
|
|
|
def isMixed(self):
|
|
return self.mixed
|
|
|
|
def setMixed(self, mixed):
|
|
self.mixed = mixed
|
|
|
|
def setBase(self, base):
|
|
self.base = base
|
|
|
|
def getBase(self):
|
|
return self.base
|
|
|
|
def getMixedExtensionError(self):
|
|
return self.mixedExtensionError
|
|
|
|
def getAttributeGroups(self):
|
|
return self.attributeGroups
|
|
|
|
def addAttribute(self, name, attribute):
|
|
self.attributeGroups[name] = attribute
|
|
|
|
def setAttributeGroup(self, attributeGroup):
|
|
self.attributeGroup = attributeGroup
|
|
|
|
def getAttributeGroup(self):
|
|
return self.attributeGroup
|
|
|
|
def setTopLevel(self, topLevel):
|
|
self.topLevel = topLevel
|
|
|
|
def getTopLevel(self):
|
|
return self.topLevel
|
|
|
|
def setAnyAttribute(self, anyAttribute):
|
|
self.anyAttribute = anyAttribute
|
|
|
|
def getAnyAttribute(self):
|
|
return self.anyAttribute
|
|
|
|
def show(self, outfile, level):
|
|
showLevel(outfile, level)
|
|
outfile.write("Name: %s Type: %s\n" % (self.name, self.getType()))
|
|
showLevel(outfile, level)
|
|
outfile.write(" - Complex: %d MaxOccurs: %d\n" % (self.complex, self.maxOccurs))
|
|
showLevel(outfile, level)
|
|
outfile.write(" - Attrs: %s\n" % self.attrs)
|
|
showLevel(outfile, level)
|
|
outfile.write(" - AttributeDefs: %s\n" % self.attributeDefs)
|
|
# ipshell('(visit_title) Entering ipshell.\nHit Ctrl-D to exit')
|
|
|
|
for attr in self.getAttributeDefs():
|
|
key = attr["name"]
|
|
try:
|
|
value = attr["value"]
|
|
except:
|
|
value = "<empty>"
|
|
showLevel(outfile, level + 1)
|
|
outfile.write("key: %s value: %s\n" % (key, value))
|
|
for child in self.children:
|
|
child.show(outfile, level + 1)
|
|
|
|
def annotate(self):
|
|
self.collect_element_dict()
|
|
self.annotate_find_type()
|
|
self.annotate_tree()
|
|
self.fix_dup_names()
|
|
self.coerce_attr_types()
|
|
self.checkMixedBases()
|
|
|
|
def collect_element_dict(self):
|
|
base = self.getBase()
|
|
if (
|
|
self.getTopLevel()
|
|
or len(self.getChildren()) > 0
|
|
or len(self.getAttributeDefs()) > 0
|
|
or base
|
|
):
|
|
ElementDict[self.name] = self
|
|
for child in self.children:
|
|
child.collect_element_dict()
|
|
|
|
def element_is_complex(self):
|
|
pass
|
|
|
|
# If it is a mixed-content element and it is defined as
|
|
# an extension, then all of its bases (base, base of base, ...)
|
|
# must be mixed-content. Mark it as an error, if not.
|
|
def checkMixedBases(self):
|
|
self.checkMixedBasesChain(self, self.mixed)
|
|
for child in self.children:
|
|
child.checkMixedBases()
|
|
|
|
def checkMixedBasesChain(self, child, childMixed):
|
|
base = self.getBase()
|
|
if base and base in ElementDict:
|
|
parent = ElementDict[base]
|
|
if childMixed != parent.isMixed():
|
|
self.mixedExtensionError = 1
|
|
return
|
|
parent.checkMixedBasesChain(child, childMixed)
|
|
|
|
def resolve_type(self):
|
|
self.complex = 0
|
|
# If it has any attributes, then it's complex.
|
|
attrDefs = self.getAttributeDefs()
|
|
if len(attrDefs) > 0:
|
|
self.complex = 1
|
|
# type_val = ''
|
|
type_val = self.resolve_type_1()
|
|
if type_val:
|
|
if type_val in ElementDict:
|
|
element = ElementDict[type_val]
|
|
type_val1 = element.resolve_type_1()
|
|
if (
|
|
type_val1 in StringType
|
|
or type_val1 == TokenType
|
|
or type_val1 == DateTimeType
|
|
or type_val1 == DateType
|
|
or type_val1 in IntegerType
|
|
or type_val1 == DecimalType
|
|
or type_val1 == PositiveIntegerType
|
|
or type_val1 == NonPositiveIntegerType
|
|
or type_val1 == NegativeIntegerType
|
|
or type_val1 == NonNegativeIntegerType
|
|
or type_val1 == BooleanType
|
|
or type_val1 == FloatType
|
|
or type_val1 == DoubleType
|
|
):
|
|
type_val = type_val1
|
|
else:
|
|
self.complex = 1
|
|
else:
|
|
if (
|
|
type_val in StringType
|
|
or type_val == TokenType
|
|
or type_val == DateTimeType
|
|
or type_val == DateType
|
|
or type_val in IntegerType
|
|
or type_val == DecimalType
|
|
or type_val == PositiveIntegerType
|
|
or type_val == NonPositiveIntegerType
|
|
or type_val == NegativeIntegerType
|
|
or type_val == NonNegativeIntegerType
|
|
or type_val == BooleanType
|
|
or type_val == FloatType
|
|
or type_val == DoubleType
|
|
):
|
|
pass
|
|
else:
|
|
type_val = StringType[0]
|
|
else:
|
|
type_val = StringType[0]
|
|
return type_val
|
|
|
|
def resolve_type_1(self):
|
|
type_val = ""
|
|
if "type" in self.attrs:
|
|
# fix
|
|
# type_val = strip_namespace(self.attrs['type'])
|
|
type_val = self.attrs["type"]
|
|
elif "ref" in self.attrs:
|
|
# fix
|
|
type_val = strip_namespace(self.attrs["ref"])
|
|
# type_val = self.attrs['ref']
|
|
elif "name" in self.attrs:
|
|
# fix
|
|
type_val = strip_namespace(self.attrs["name"])
|
|
# type_val = self.attrs['name']
|
|
return type_val
|
|
|
|
def annotate_find_type(self):
|
|
type_val = self.resolve_type()
|
|
# dbgprint(1, '(aft) n: %s t: %s c: %s id: %s' % \
|
|
# (self.name, type_val, self.complex, id(self), ))
|
|
self.attrs["type"] = type_val
|
|
self.type = type_val
|
|
if not self.complex:
|
|
SimpleElementDict[self.name] = self.name
|
|
for child in self.children:
|
|
child.annotate_find_type()
|
|
|
|
def annotate_tree(self):
|
|
# If there is a namespace, replace it with an underscore.
|
|
if self.base:
|
|
self.base = strip_namespace(self.base)
|
|
self.unmappedCleanName = cleanupName(self.name)
|
|
self.cleanName = mapName(self.unmappedCleanName)
|
|
SaxElementDict[self.cleanName] = self
|
|
self.replace_attributeGroup_names()
|
|
if "maxOccurs" in self.attrs:
|
|
maxOccurs = self.attrs["maxOccurs"]
|
|
if maxOccurs == "unbounded":
|
|
maxOccurs = 99999
|
|
else:
|
|
try:
|
|
maxOccurs = int(self.attrs["maxOccurs"])
|
|
except ValueError:
|
|
sys.stderr.write(
|
|
'*** %s maxOccurs must be integer or "unbounded".' % (self.getName(),)
|
|
)
|
|
sys.exit(-1)
|
|
else:
|
|
maxOccurs = 1
|
|
self.maxOccurs = maxOccurs
|
|
# if self.cleanName == 'Reason_XXX':
|
|
# ipshell('(annotate_tree) -- Entering ipshell.\\nHit Ctrl-D to exit')
|
|
# If it does not have a type, then make the type the same as the name.
|
|
if self.type == "NoneType" and self.name:
|
|
self.type = self.name
|
|
# Is it a mixed-content element definition?
|
|
if "mixed" in self.attrs:
|
|
mixed = self.attrs["mixed"].strip()
|
|
if mixed == "1" or mixed.lower() == "true":
|
|
self.mixed = 1
|
|
# Do it recursively for all descendents.
|
|
for child in self.children:
|
|
child.annotate_tree()
|
|
|
|
#
|
|
# For each name in the attributeGroupNameList for this element,
|
|
# add the attributes defined for that name in the global
|
|
# attributeGroup dictionary.
|
|
def replace_attributeGroup_names(self):
|
|
for groupName in self.attributeGroupNameList:
|
|
if groupName in AttributeGroups:
|
|
attrGroup = AttributeGroups[groupName]
|
|
for name in attrGroup.getKeys():
|
|
attr = attrGroup.get(name)
|
|
self.attributeDefs[name] = attr
|
|
else:
|
|
print("*** Error. attributeGroup %s not defined." % groupName)
|
|
|
|
def __str__(self):
|
|
s1 = '<"%s" XschemaElement instance at 0x%x>' % (self.getName(), id(self))
|
|
return s1
|
|
|
|
def __repr__(self):
|
|
s1 = '<"%s" XschemaElement instance at 0x%x>' % (self.getName(), id(self))
|
|
return s1
|
|
|
|
def fix_dup_names(self):
|
|
# Patch-up names that are used for both a child element and an attribute.
|
|
#
|
|
attrDefs = self.getAttributeDefs()
|
|
# Collect a list of child element names.
|
|
# Must do this for base (extension) elements also.
|
|
elementNames = []
|
|
self.collectElementNames(elementNames)
|
|
replaced = []
|
|
# Create the needed new attributes.
|
|
keys = attrDefs.keys()
|
|
for key in keys:
|
|
attr = attrDefs[key]
|
|
name = attr.getName()
|
|
if name in elementNames:
|
|
newName = name + "_attr"
|
|
newAttr = XschemaAttribute(newName)
|
|
attrDefs[newName] = newAttr
|
|
replaced.append(name)
|
|
# Remove the old (replaced) attributes.
|
|
for name in replaced:
|
|
del attrDefs[name]
|
|
for child in self.children:
|
|
child.fix_dup_names()
|
|
|
|
def collectElementNames(self, elementNames):
|
|
for child in self.children:
|
|
elementNames.append(cleanupName(child.cleanName))
|
|
base = self.getBase()
|
|
if base and base in ElementDict:
|
|
parent = ElementDict[base]
|
|
parent.collectElementNames(elementNames)
|
|
|
|
def coerce_attr_types(self):
|
|
replacements = []
|
|
attrDefs = self.getAttributeDefs()
|
|
for idx, name in enumerate(attrDefs):
|
|
attr = attrDefs[name]
|
|
attrType = attr.getData_type()
|
|
if attrType == IDType or attrType == IDREFType or attrType == IDREFSType:
|
|
attr.setData_type(StringType[0])
|
|
for child in self.children:
|
|
child.coerce_attr_types()
|
|
|
|
|
|
# end class XschemaElement
|
|
|
|
|
|
class XschemaAttributeGroup:
|
|
def __init__(self, name="", group=None):
|
|
self.name = name
|
|
if group:
|
|
self.group = group
|
|
else:
|
|
self.group = {}
|
|
|
|
def setName(self, name):
|
|
self.name = name
|
|
|
|
def getName(self):
|
|
return self.name
|
|
|
|
def setGroup(self, group):
|
|
self.group = group
|
|
|
|
def getGroup(self):
|
|
return self.group
|
|
|
|
def get(self, name, default=None):
|
|
if name in self.group:
|
|
return self.group[name]
|
|
else:
|
|
return default
|
|
|
|
def getKeys(self):
|
|
return self.group.keys()
|
|
|
|
def add(self, name, attr):
|
|
self.group[name] = attr
|
|
|
|
def delete(self, name):
|
|
# if has_key(self.group, name):
|
|
if name in self.group:
|
|
del self.group[name]
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
|
|
# end class XschemaAttributeGroup
|
|
|
|
|
|
class XschemaAttribute:
|
|
def __init__(self, name, data_type="xs:string", use="optional"):
|
|
self.name = name
|
|
self.data_type = data_type
|
|
self.use = use
|
|
|
|
def setName(self, name):
|
|
self.name = name
|
|
|
|
def getName(self):
|
|
return self.name
|
|
|
|
def setData_type(self, data_type):
|
|
self.data_type = data_type
|
|
|
|
def getData_type(self):
|
|
return self.data_type
|
|
|
|
def setUse(self, use):
|
|
self.use = use
|
|
|
|
def getUse(self):
|
|
return self.use
|
|
|
|
|
|
# end class XschemaAttribute
|
|
|
|
|
|
#
|
|
# SAX handler
|
|
#
|
|
class XschemaHandler(handler.ContentHandler):
|
|
def __init__(self):
|
|
handler.ContentHandler.__init__(self)
|
|
self.stack = []
|
|
self.root = None
|
|
self.inElement = 0
|
|
self.inComplexType = 0
|
|
self.inNonanonymousComplexType = 0
|
|
self.inSequence = 0
|
|
self.inChoice = 1
|
|
self.inAttribute = 0
|
|
self.inAttributeGroup = 0
|
|
self.inSimpleElement = 0
|
|
|
|
## self.dbgcount = 1
|
|
## self.dbgnames = []
|
|
|
|
def getRoot(self):
|
|
# ipshell('Returning root -- Entering ipshell.\\nHit Ctrl-D to exit')
|
|
return self.root
|
|
|
|
def showError(self, msg):
|
|
print(msg)
|
|
sys.exit(-1)
|
|
|
|
def startElement(self, name, attrs):
|
|
# dbgprint(1, 'before schema name: %s SchemaType: %s' % (name, SchemaType,))
|
|
if name == SchemaType:
|
|
# dbgprint(1, '(schema in)')
|
|
self.inSchema = 1
|
|
element = XschemaElement(attrs)
|
|
if len(self.stack) == 1:
|
|
element.setTopLevel(1)
|
|
self.stack.append(element)
|
|
# If there is an attribute "xmlns" and its value is
|
|
# "http://www.w3.org/2001/XMLSchema", then remember and
|
|
# use that namespace prefix.
|
|
for name, value in attrs.items():
|
|
if name[:6] == "xmlns:" and value == "http://www.w3.org/2001/XMLSchema":
|
|
nameSpace = name[6:] + ":"
|
|
set_type_constants(nameSpace)
|
|
elif name == ElementType or ((name == ComplexTypeType) and (len(self.stack) == 1)):
|
|
self.inElement = 1
|
|
self.inNonanonymousComplexType = 1
|
|
element = XschemaElement(attrs)
|
|
if len(self.stack) == 1:
|
|
element.setTopLevel(1)
|
|
if "substitutionGroup" in attrs and "name" in attrs:
|
|
substituteName = attrs["name"]
|
|
headName = attrs["substitutionGroup"]
|
|
if headName not in SubstitutionGroups:
|
|
SubstitutionGroups[headName] = []
|
|
SubstitutionGroups[headName].append(substituteName)
|
|
# dbgprint(1, '(startElement) added %s to %s' % (substituteName, headName))
|
|
if name == ComplexTypeType:
|
|
element.complexType = 1
|
|
self.stack.append(element)
|
|
elif name == ComplexTypeType:
|
|
# If it have any attributes and there is something on the stack,
|
|
# then copy the attributes to the item on top of the stack.
|
|
if len(self.stack) > 1 and len(attrs) > 0:
|
|
parentDict = self.stack[-1].getAttrs()
|
|
for key in attrs.keys():
|
|
parentDict[key] = attrs[key]
|
|
self.inComplexType = 1
|
|
elif name == SequenceType:
|
|
self.inSequence = 1
|
|
elif name == ChoiceType:
|
|
self.inChoice = 1
|
|
elif name == AttributeType:
|
|
self.inAttribute = 1
|
|
if "name" in attrs:
|
|
name = attrs["name"]
|
|
# fix-attribute-ref
|
|
elif "ref" in attrs:
|
|
name = strip_namespace(attrs["ref"])
|
|
else:
|
|
name = "no_attribute_name"
|
|
if "type" in attrs:
|
|
data_type = attrs["type"]
|
|
else:
|
|
data_type = StringType[0]
|
|
if "use" in attrs:
|
|
use = attrs["use"]
|
|
else:
|
|
use = "optional"
|
|
if self.stack[-1].attributeGroup:
|
|
# Add this attribute to a current attributeGroup.
|
|
attribute = XschemaAttribute(name, data_type, use)
|
|
self.stack[-1].attributeGroup.add(name, attribute)
|
|
else:
|
|
# Add this attribute to the element/complexType.
|
|
attribute = XschemaAttribute(name, data_type, use)
|
|
self.stack[-1].attributeDefs[name] = attribute
|
|
elif name == AttributeGroupType:
|
|
self.inAttributeGroup = 1
|
|
# If it has attribute 'name', then it's a definition.
|
|
# Prepare to save it as an attributeGroup.
|
|
if "name" in attrs:
|
|
name = strip_namespace(attrs["name"])
|
|
attributeGroup = XschemaAttributeGroup(name)
|
|
element = XschemaElement(attrs)
|
|
if len(self.stack) == 1:
|
|
element.setTopLevel(1)
|
|
element.setAttributeGroup(attributeGroup)
|
|
self.stack.append(element)
|
|
# If it has attribute 'ref', add it to the list of
|
|
# attributeGroups for this element/complexType.
|
|
if "ref" in attrs:
|
|
self.stack[-1].attributeGroupNameList.append(attrs["ref"])
|
|
elif name == ComplexContentType:
|
|
pass
|
|
elif name == ExtensionType:
|
|
if "base" in attrs and len(self.stack) > 0:
|
|
extensionBase = attrs["base"]
|
|
if (
|
|
extensionBase in StringType
|
|
or extensionBase == TokenType
|
|
or extensionBase == DateTimeType
|
|
or extensionBase == DateType
|
|
or extensionBase in IntegerType
|
|
or extensionBase == DecimalType
|
|
or extensionBase == PositiveIntegerType
|
|
or extensionBase == NegativeIntegerType
|
|
or extensionBase == NonPositiveIntegerType
|
|
or extensionBase == NonNegativeIntegerType
|
|
or extensionBase == BooleanType
|
|
or extensionBase == FloatType
|
|
or extensionBase == DoubleType
|
|
):
|
|
pass
|
|
else:
|
|
self.stack[-1].setBase(extensionBase)
|
|
elif name == AnyAttributeType:
|
|
# Mark the current element as containing anyAttribute.
|
|
self.stack[-1].setAnyAttribute(1)
|
|
|
|
def endElement(self, name):
|
|
if self.inSimpleElement:
|
|
self.inSimpleElement = 0
|
|
elif name == ElementType or (name == ComplexTypeType and self.stack[-1].complexType):
|
|
self.inElement = 0
|
|
self.inNonanonymousComplexType = 0
|
|
element = self.stack.pop()
|
|
self.stack[-1].addChild(element)
|
|
elif name == ComplexTypeType:
|
|
self.inComplexType = 0
|
|
elif name == SequenceType:
|
|
self.inSequence = 0
|
|
elif name == ChoiceType:
|
|
self.inChoice = 0
|
|
elif name == AttributeType:
|
|
self.inAttribute = 0
|
|
elif name == AttributeGroupType:
|
|
self.inAttributeGroup = 0
|
|
if self.stack[-1].attributeGroup:
|
|
# The top of the stack contains an XschemaElement which
|
|
# contains the definition of an attributeGroup.
|
|
# Save this attributeGroup in the
|
|
# global AttributeGroup dictionary.
|
|
attributeGroup = self.stack[-1].attributeGroup
|
|
name = attributeGroup.getName()
|
|
AttributeGroups[name] = attributeGroup
|
|
self.stack[-1].attributeGroup = None
|
|
self.stack.pop()
|
|
else:
|
|
# This is a reference to an attributeGroup.
|
|
# We have already added it to the list of attributeGroup names.
|
|
# Leave it. We'll fill it in during annotate.
|
|
pass
|
|
elif name == SchemaType:
|
|
self.inSchema = 0
|
|
if len(self.stack) != 1:
|
|
print("*** error stack. len(self.stack): %d" % len(self.stack))
|
|
sys.exit(-1)
|
|
self.root = self.stack[0]
|
|
elif name == ComplexContentType:
|
|
pass
|
|
elif name == ExtensionType:
|
|
pass
|
|
|
|
def characters(self, chrs):
|
|
if self.inElement:
|
|
pass
|
|
elif self.inComplexType:
|
|
pass
|
|
elif self.inSequence:
|
|
pass
|
|
elif self.inChoice:
|
|
pass
|
|
|
|
|
|
#
|
|
# Code generation
|
|
#
|
|
|
|
|
|
def generateExportFn_1(outfile, child, name, fill):
|
|
cleanName = cleanupName(name)
|
|
if (
|
|
child.getType() in StringType
|
|
or child.getType() == TokenType
|
|
or child.getType() == DateTimeType
|
|
or child.getType() == DateType
|
|
):
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('<%s>%%s</%s>\\n' %% quote_xml(self.get%s()))\n" % (
|
|
fill,
|
|
name,
|
|
name,
|
|
cleanName.capitalize(),
|
|
)
|
|
outfile.write(s1)
|
|
elif (
|
|
child.getType() in IntegerType
|
|
or child.getType() == BooleanType
|
|
or child.getType() == PositiveIntegerType
|
|
or child.getType() == NonPositiveIntegerType
|
|
or child.getType() == NegativeIntegerType
|
|
or child.getType() == NonNegativeIntegerType
|
|
):
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('<%s>%%d</%s>\\n' %% self.get%s())\n" % (
|
|
fill,
|
|
name,
|
|
name,
|
|
cleanName.capitalize(),
|
|
)
|
|
outfile.write(s1)
|
|
elif child.getType() == FloatType or child.getType() == DecimalType:
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('<%s>%%f</%s>\\n' %% self.get%s())\n" % (
|
|
fill,
|
|
name,
|
|
name,
|
|
cleanName.capitalize(),
|
|
)
|
|
outfile.write(s1)
|
|
elif child.getType() == DoubleType:
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('<%s>%%e</%s>\\n' %% self.get%s())\n" % (
|
|
fill,
|
|
name,
|
|
name,
|
|
cleanName.capitalize(),
|
|
)
|
|
outfile.write(s1)
|
|
else:
|
|
s1 = "%s if self.%s:\n" % (fill, cleanName)
|
|
outfile.write(s1)
|
|
if name == child.getType():
|
|
s1 = "%s self.%s.export(outfile, level)\n" % (fill, cleanName)
|
|
else:
|
|
s1 = "%s self.%s.export(outfile, level, name_='%s')\n" % (
|
|
fill,
|
|
cleanName,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
|
|
|
|
def generateExportFn_2(outfile, child, name, fill):
|
|
cleanName = cleanupName(name)
|
|
s1 = "%s for %s_ in self.get%s():\n" % (fill, cleanName, cleanName.capitalize())
|
|
outfile.write(s1)
|
|
if (
|
|
child.getType() in StringType
|
|
or child.getType() == TokenType
|
|
or child.getType() == DateTimeType
|
|
or child.getType() == DateType
|
|
):
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('<%s>%%s</%s>\\n' %% quote_xml(%s_))\n" % (
|
|
fill,
|
|
name,
|
|
name,
|
|
cleanName,
|
|
)
|
|
outfile.write(s1)
|
|
elif (
|
|
child.getType() in IntegerType
|
|
or child.getType() == BooleanType
|
|
or child.getType() == PositiveIntegerType
|
|
or child.getType() == NonPositiveIntegerType
|
|
or child.getType() == NegativeIntegerType
|
|
or child.getType() == NonNegativeIntegerType
|
|
):
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('<%s>%%d</%s>\\n' %% %s_)\n" % (
|
|
fill,
|
|
name,
|
|
name,
|
|
cleanName,
|
|
)
|
|
outfile.write(s1)
|
|
elif child.getType() == FloatType or child.getType() == DecimalType:
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('<%s>%%f</%s>\\n' %% %s_)\n" % (
|
|
fill,
|
|
name,
|
|
name,
|
|
cleanName,
|
|
)
|
|
outfile.write(s1)
|
|
elif child.getType() == DoubleType:
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('<%s>%%e</%s>\\n' %% %s_)\n" % (
|
|
fill,
|
|
name,
|
|
name,
|
|
cleanName,
|
|
)
|
|
outfile.write(s1)
|
|
else:
|
|
if name == child.getType():
|
|
s1 = "%s %s_.export(outfile, level)\n" % (fill, cleanName)
|
|
else:
|
|
s1 = "%s %s_.export(outfile, level, name_='%s')\n" % (
|
|
fill,
|
|
cleanName,
|
|
cleanName,
|
|
)
|
|
outfile.write(s1)
|
|
|
|
|
|
def generateExportAttributes(outfile, element, hasAttributes):
|
|
if len(element.getAttributeDefs()) > 0:
|
|
hasAttributes += 1
|
|
attrDefs = element.getAttributeDefs()
|
|
for key in attrDefs.keys():
|
|
attrDef = attrDefs[key]
|
|
name = attrDef.getName()
|
|
cleanName = cleanupName(name)
|
|
capName = cleanName.capitalize()
|
|
if attrDef.getUse() == "optional":
|
|
s1 = " if self.get%s() is not None:\n" % (capName,)
|
|
outfile.write(s1)
|
|
s1 = " outfile.write(' %s=\"%%s\"' %% (self.get%s(), ))\n" % (
|
|
name,
|
|
capName,
|
|
)
|
|
outfile.write(s1)
|
|
else:
|
|
s1 = " outfile.write(' %s=\"%%s\"' %% (self.get%s(), ))\n" % (
|
|
name,
|
|
capName,
|
|
)
|
|
outfile.write(s1)
|
|
if element.getAnyAttribute():
|
|
s1 = " for name, value in self.anyAttributes_.items():\n"
|
|
outfile.write(s1)
|
|
s1 = " outfile.write(' %s=\"%s\"' % (name, value, ))\n"
|
|
outfile.write(s1)
|
|
return hasAttributes
|
|
|
|
|
|
def generateExportChildren(outfile, element, hasChildren):
|
|
if len(element.getChildren()) > 0:
|
|
hasChildren += 1
|
|
if element.isMixed():
|
|
s1 = " for item_ in self.content_:\n"
|
|
outfile.write(s1)
|
|
s1 = " item_.export(outfile, level, name_)\n"
|
|
outfile.write(s1)
|
|
else:
|
|
for child in element.getChildren():
|
|
name = child.getName()
|
|
if child.getMaxOccurs() > 1:
|
|
generateExportFn_2(outfile, child, name, " ")
|
|
else:
|
|
generateExportFn_1(outfile, child, name, "")
|
|
## base = element.getBase()
|
|
## if base and base in ElementDict:
|
|
## parent = ElementDict[base]
|
|
## hasAttributes = generateExportChildren(outfile, parent, hasChildren)
|
|
return hasChildren
|
|
|
|
|
|
def countChildren(element, count):
|
|
count += len(element.getChildren())
|
|
base = element.getBase()
|
|
if base and base in ElementDict:
|
|
parent = ElementDict[base]
|
|
count = countChildren(parent, count)
|
|
return count
|
|
|
|
|
|
def generateExportFn(outfile, prefix, element):
|
|
base = element.getBase()
|
|
s1 = " def export(self, outfile, level, name_='%s'):\n" % element.getName()
|
|
outfile.write(s1)
|
|
s1 = " showIndent(outfile, level)\n"
|
|
outfile.write(s1)
|
|
if len(element.getAttributeDefs()) > 0:
|
|
s1 = " outfile.write('<%s' % (name_, ))\n"
|
|
outfile.write(s1)
|
|
|
|
s1 = " self.exportAttributes(outfile, level, name_='%s')\n" % element.getName()
|
|
outfile.write(s1)
|
|
if element.isMixed():
|
|
s1 = " outfile.write('>')\n"
|
|
else:
|
|
s1 = " outfile.write('>\\n')\n"
|
|
outfile.write(s1)
|
|
else:
|
|
if element.isMixed():
|
|
s1 = " outfile.write('<%s>' % name_)\n"
|
|
else:
|
|
s1 = " outfile.write('<%s>\\n' % name_)\n"
|
|
outfile.write(s1)
|
|
|
|
s1 = " self.exportChildren(outfile, level + 1, name_)\n"
|
|
outfile.write(s1)
|
|
s1 = " showIndent(outfile, level)\n"
|
|
outfile.write(s1)
|
|
s1 = " outfile.write('</%s>\\n' % name_)\n"
|
|
outfile.write(s1)
|
|
s1 = " def exportAttributes(self, outfile, level, name_='%s'):\n" % element.getName()
|
|
outfile.write(s1)
|
|
hasAttributes = 0
|
|
hasAttributes = generateExportAttributes(outfile, element, hasAttributes)
|
|
if base:
|
|
hasAttributes += 1
|
|
s1 = " %s.exportAttributes(self, outfile, level, name_='%s')\n" % (
|
|
base,
|
|
element.getName(),
|
|
)
|
|
outfile.write(s1)
|
|
if hasAttributes == 0:
|
|
s1 = " pass\n"
|
|
outfile.write(s1)
|
|
## if len(element.getChildren()) > 0 and not element.isMixed():
|
|
## s1 = ' showIndent(outfile, level)\n'
|
|
## outfile.write(s1)
|
|
s1 = " def exportChildren(self, outfile, level, name_='%s'):\n" % element.getName()
|
|
outfile.write(s1)
|
|
hasChildren = 0
|
|
hasChildren = generateExportChildren(outfile, element, hasChildren)
|
|
if base:
|
|
hasChildren += 1
|
|
s1 = " %s.exportChildren(self, outfile, level, name_)\n" % (base,)
|
|
outfile.write(s1)
|
|
count = countChildren(element, 0)
|
|
if count == 0:
|
|
s1 = " outfile.write(self.valueOf_)\n"
|
|
outfile.write(s1)
|
|
|
|
|
|
#
|
|
# Generate exportLiteral method.
|
|
#
|
|
|
|
|
|
def generateExportLiteralFn_1(outfile, child, name, fill):
|
|
mappedName = mapName(name)
|
|
if (
|
|
child.getType() in StringType
|
|
or child.getType() == TokenType
|
|
or child.getType() == DateTimeType
|
|
or child.getType() == DateType
|
|
):
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('%s=%%s,\\n' %% quote_python(self.get%s()))\n" % (
|
|
fill,
|
|
mappedName,
|
|
name.capitalize(),
|
|
)
|
|
outfile.write(s1)
|
|
elif (
|
|
child.getType() in IntegerType
|
|
or child.getType() == BooleanType
|
|
or child.getType() == PositiveIntegerType
|
|
or child.getType() == NonPositiveIntegerType
|
|
or child.getType() == NegativeIntegerType
|
|
or child.getType() == NonNegativeIntegerType
|
|
):
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('%s=%%d,\\n' %% self.get%s())\n" % (
|
|
fill,
|
|
mappedName,
|
|
name.capitalize(),
|
|
)
|
|
outfile.write(s1)
|
|
elif child.getType() == FloatType or child.getType() == DecimalType:
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('%s=%%f,\\n' %% self.get%s())\n" % (
|
|
fill,
|
|
mappedName,
|
|
name.capitalize(),
|
|
)
|
|
outfile.write(s1)
|
|
elif child.getType() == DoubleType:
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('%s=%%e,\\n' %% self.get%s())\n" % (
|
|
fill,
|
|
name,
|
|
name.capitalize(),
|
|
)
|
|
outfile.write(s1)
|
|
else:
|
|
s1 = "%s if self.%s:\n" % (fill, name)
|
|
outfile.write(s1)
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('%s=%s(\\n')\n" % (
|
|
fill,
|
|
name,
|
|
child.getType(),
|
|
)
|
|
outfile.write(s1)
|
|
if name == child.getType():
|
|
s1 = "%s self.%s.exportLiteral(outfile, level)\n" % (fill, name)
|
|
else:
|
|
s1 = "%s self.%s.exportLiteral(outfile, level, name_='%s')\n" % (
|
|
fill,
|
|
name,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('),\\n')\n" % (fill,)
|
|
outfile.write(s1)
|
|
|
|
|
|
def generateExportLiteralFn_2(outfile, child, name, fill):
|
|
if (
|
|
child.getType() in StringType
|
|
or child.getType() == TokenType
|
|
or child.getType() == DateTimeType
|
|
or child.getType() == DateType
|
|
):
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('%%s,\\n' %% quote_python(%s))\n" % (fill, name)
|
|
outfile.write(s1)
|
|
elif (
|
|
child.getType() in IntegerType
|
|
or child.getType() == BooleanType
|
|
or child.getType() == PositiveIntegerType
|
|
or child.getType() == NonPositiveIntegerType
|
|
or child.getType() == NegativeIntegerType
|
|
or child.getType() == NonNegativeIntegerType
|
|
):
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('%%d,\\n' %% %s)\n" % (fill, name)
|
|
outfile.write(s1)
|
|
elif child.getType() == FloatType or child.getType() == DecimalType:
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('%%f,\\n' %% %s)\n" % (fill, name)
|
|
outfile.write(s1)
|
|
elif child.getType() == DoubleType:
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('%%e,\\n' %% %s)\n" % (fill, name)
|
|
outfile.write(s1)
|
|
else:
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('%s(\\n')\n" % (
|
|
fill,
|
|
cleanupName(child.getType()),
|
|
)
|
|
outfile.write(s1)
|
|
if name == child.getType():
|
|
s1 = "%s %s.exportLiteral(outfile, level)\n" % (
|
|
fill,
|
|
child.getType(),
|
|
)
|
|
else:
|
|
s1 = "%s %s.exportLiteral(outfile, level, name_='%s')\n" % (
|
|
fill,
|
|
name,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
s1 = "%s showIndent(outfile, level)\n" % fill
|
|
outfile.write(s1)
|
|
s1 = "%s outfile.write('),\\n')\n" % (fill,)
|
|
outfile.write(s1)
|
|
|
|
|
|
def generateExportLiteralFn(outfile, prefix, element):
|
|
base = element.getBase()
|
|
s1 = " def exportLiteral(self, outfile, level, name_='%s'):\n" % element.getName()
|
|
outfile.write(s1)
|
|
s1 = " level += 1\n"
|
|
outfile.write(s1)
|
|
s1 = " self.exportLiteralAttributes(outfile, level, name_)\n"
|
|
outfile.write(s1)
|
|
s1 = " self.exportLiteralChildren(outfile, level, name_)\n"
|
|
outfile.write(s1)
|
|
s1 = " def exportLiteralAttributes(self, outfile, level, name_):\n"
|
|
outfile.write(s1)
|
|
count = 0
|
|
attrDefs = element.getAttributeDefs()
|
|
for key in attrDefs:
|
|
attrDef = attrDefs[key]
|
|
count += 1
|
|
name = attrDef.getName()
|
|
cleanName = cleanupName(name)
|
|
capName = cleanName.capitalize()
|
|
mappedName = mapName(cleanName)
|
|
s1 = " showIndent(outfile, level)\n"
|
|
outfile.write(s1)
|
|
## ipshell('(generateExportLiteral) -- Entering ipshell.\\nHit Ctrl-D to exit')
|
|
stringType = 0
|
|
data_type = attrDef.getData_type()
|
|
if data_type.find("string") >= 0:
|
|
stringType = 1
|
|
else:
|
|
stringType = 1
|
|
if stringType:
|
|
s1 = " outfile.write('%s = \"%%s\",\\n' %% (self.get%s(),))\n" % (
|
|
mappedName,
|
|
capName,
|
|
)
|
|
else:
|
|
s1 = " outfile.write('%s = %%s,\\n' %% (self.get%s(),))\n" % (
|
|
mappedName,
|
|
capName,
|
|
)
|
|
outfile.write(s1)
|
|
|
|
if element.getAnyAttribute():
|
|
count += 1
|
|
s1 = " for name, value in self.anyAttributes_.items():\n"
|
|
outfile.write(s1)
|
|
s1 = " showIndent(outfile, level)\n"
|
|
outfile.write(s1)
|
|
s1 = " outfile.write('%s = \"%s\",\\n' % (name, value,))\n"
|
|
outfile.write(s1)
|
|
if count == 0:
|
|
s1 = " pass\n"
|
|
outfile.write(s1)
|
|
if base:
|
|
s1 = " %s.exportLiteralAttributes(self, outfile, level, name_)\n" % (base,)
|
|
outfile.write(s1)
|
|
s1 = " def exportLiteralChildren(self, outfile, level, name_):\n"
|
|
outfile.write(s1)
|
|
for child in element.getChildren():
|
|
name = child.getName()
|
|
name = cleanupName(name)
|
|
# unmappedName = child.getUnmappedCleanName()
|
|
# cleanName = cleanupName(name)
|
|
# mappedName = mapName(cleanName)
|
|
if element.isMixed():
|
|
s1 = " showIndent(outfile, level)\n"
|
|
outfile.write(s1)
|
|
s1 = " outfile.write('content_ = [\\n')\n"
|
|
outfile.write(s1)
|
|
s1 = " for item_ in self.content_:\n"
|
|
outfile.write(s1)
|
|
s1 = " item_.exportLiteral(outfile, level, name_)\n"
|
|
outfile.write(s1)
|
|
s1 = " showIndent(outfile, level)\n"
|
|
outfile.write(s1)
|
|
s1 = " outfile.write('],\\n')\n"
|
|
outfile.write(s1)
|
|
else:
|
|
if child.getMaxOccurs() > 1:
|
|
s1 = " showIndent(outfile, level)\n"
|
|
outfile.write(s1)
|
|
s1 = " outfile.write('%s=[\\n')\n" % name
|
|
outfile.write(s1)
|
|
s1 = " level += 1\n"
|
|
outfile.write(s1)
|
|
s1 = " for %s in self.%s:\n" % (name, name)
|
|
outfile.write(s1)
|
|
generateExportLiteralFn_2(outfile, child, name, " ")
|
|
s1 = " level -= 1\n"
|
|
outfile.write(s1)
|
|
s1 = " showIndent(outfile, level)\n"
|
|
outfile.write(s1)
|
|
s1 = " outfile.write('],\\n')\n"
|
|
outfile.write(s1)
|
|
else:
|
|
generateExportLiteralFn_1(outfile, child, name, "")
|
|
if len(element.getChildren()) == 0:
|
|
s1 = " showIndent(outfile, level)\n"
|
|
outfile.write(s1)
|
|
s1 = " outfile.write('valueOf_ = \"%s\",\\n' % (self.valueOf_,))\n"
|
|
outfile.write(s1)
|
|
if base:
|
|
s1 = " %s.exportLiteralChildren(self, outfile, level, name_)\n" % (base,)
|
|
outfile.write(s1)
|
|
# s1 = " level -= 1\n"
|
|
# outfile.write(s1)
|
|
|
|
|
|
#
|
|
# Generate build method.
|
|
#
|
|
|
|
|
|
def generateBuildAttributes(outfile, element, hasAttributes):
|
|
attrDefs = element.getAttributeDefs()
|
|
for key in attrDefs:
|
|
attrDef = attrDefs[key]
|
|
hasAttributes += 1
|
|
name = attrDef.getName()
|
|
cleanName = cleanupName(name)
|
|
mappedName = mapName(cleanName)
|
|
atype = attrDef.getData_type()
|
|
if (
|
|
atype in IntegerType
|
|
or atype == PositiveIntegerType
|
|
or atype == NonPositiveIntegerType
|
|
or atype == NegativeIntegerType
|
|
or atype == NonNegativeIntegerType
|
|
):
|
|
s1 = " if attrs.get('%s'):\n" % name
|
|
outfile.write(s1)
|
|
s1 = " try:\n"
|
|
outfile.write(s1)
|
|
s1 = " self.%s = int(attrs.get('%s').value)\n" % (
|
|
mappedName,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
s1 = " except ValueError:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Bad integer attribute (%s)')\n" % (name,)
|
|
outfile.write(s1)
|
|
if atype == PositiveIntegerType:
|
|
s1 = " if self.%s <= 0:\n" % mappedName
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Invalid PositiveInteger (%s)')\n" % name
|
|
outfile.write(s1)
|
|
elif atype == NonPositiveIntegerType:
|
|
s1 = " if self.%s > 0:\n" % mappedName
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Invalid NonPositiveInteger (%s)')\n" % name
|
|
outfile.write(s1)
|
|
elif atype == NegativeIntegerType:
|
|
s1 = " if self.%s >= 0:\n" % mappedName
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Invalid NegativeInteger (%s)')\n" % name
|
|
outfile.write(s1)
|
|
elif atype == NonNegativeIntegerType:
|
|
s1 = " if self.%s < 0:\n" % mappedName
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Invalid NonNegativeInteger (%s)')\n" % name
|
|
outfile.write(s1)
|
|
elif atype == BooleanType:
|
|
s1 = " if attrs.get('%s'):\n" % (name,)
|
|
outfile.write(s1)
|
|
s1 = " if attrs.get('%s').value in ('true', '1'):\n" % (name,)
|
|
outfile.write(s1)
|
|
s1 = " self.%s = 1\n" % (mappedName,)
|
|
outfile.write(s1)
|
|
s1 = " elif attrs.get('%s').value in ('false', '0'):\n" % (name,)
|
|
outfile.write(s1)
|
|
s1 = " self.%s = 0\n" % (mappedName,)
|
|
outfile.write(s1)
|
|
s1 = " else:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Bad boolean attribute (%s)')\n" % (name,)
|
|
outfile.write(s1)
|
|
elif atype == FloatType or atype == DoubleType or atype == DecimalType:
|
|
s1 = " if attrs.get('%s'):\n" % (name,)
|
|
outfile.write(s1)
|
|
s1 = " try:\n"
|
|
outfile.write(s1)
|
|
s1 = " self.%s = float(attrs.get('%s').value)\n" % (
|
|
mappedName,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
s1 = " except:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Bad float/double attribute (%s)')\n" % (name,)
|
|
outfile.write(s1)
|
|
elif atype == TokenType:
|
|
s1 = " if attrs.get('%s'):\n" % (name,)
|
|
outfile.write(s1)
|
|
s1 = " self.%s = attrs.get('%s').value\n" % (
|
|
mappedName,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
s1 = " self.%s = ' '.join(self.%s.split())\n" % (
|
|
mappedName,
|
|
mappedName,
|
|
)
|
|
outfile.write(s1)
|
|
else:
|
|
# Assume attr['type'] in StringType or attr['type'] == DateTimeType:
|
|
s1 = " if attrs.get('%s'):\n" % (name,)
|
|
outfile.write(s1)
|
|
s1 = " self.%s = attrs.get('%s').value\n" % (
|
|
mappedName,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
if element.getAnyAttribute():
|
|
s1 = " self.anyAttributes_ = {}\n"
|
|
outfile.write(s1)
|
|
s1 = " for name, value in attrs.items():\n"
|
|
outfile.write(s1)
|
|
s1List = [" if"]
|
|
firstTime = 1
|
|
for key in attrDefs:
|
|
if firstTime:
|
|
s1List.append(' name != "%s"' % key)
|
|
firstTime = 0
|
|
else:
|
|
s1List.append(' and name != "%s"' % key)
|
|
s1List.append(":\n")
|
|
s1 = "".join(s1List)
|
|
outfile.write(s1)
|
|
s1 = " self.anyAttributes_[name] = value\n"
|
|
outfile.write(s1)
|
|
return hasAttributes
|
|
|
|
|
|
def generateBuildMixed_1(outfile, prefix, child, headChild, keyword, delayed):
|
|
global DelayedElements, DelayedElements_subclass
|
|
nestedElements = 1
|
|
origName = child.getName()
|
|
name = child.getCleanName()
|
|
headName = cleanupName(headChild.getName())
|
|
childType = child.getType()
|
|
if (
|
|
childType in StringType
|
|
or childType == TokenType
|
|
or childType == DateTimeType
|
|
or childType == DateType
|
|
):
|
|
s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " nodeName_ == '%s':\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " value_ = []\n"
|
|
outfile.write(s1)
|
|
s1 = " for text_ in child_.childNodes:\n"
|
|
outfile.write(s1)
|
|
s1 = " value_.append(text_.nodeValue)\n"
|
|
outfile.write(s1)
|
|
s1 = " valuestr_ = ''.join(value_)\n"
|
|
outfile.write(s1)
|
|
if childType == TokenType:
|
|
s1 = " valuestr_ = ' '.join(valuestr_.split())\n"
|
|
outfile.write(s1)
|
|
s1 = " obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
|
|
outfile.write(s1)
|
|
s1 = " MixedContainer.TypeString, '%s', valuestr_)\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " self.content_.append(obj_)\n"
|
|
outfile.write(s1)
|
|
elif (
|
|
childType in IntegerType
|
|
or childType == PositiveIntegerType
|
|
or childType == NonPositiveIntegerType
|
|
or childType == NegativeIntegerType
|
|
or childType == NonNegativeIntegerType
|
|
):
|
|
s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " nodeName_ == '%s':\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " if child_.firstChild:\n"
|
|
outfile.write(s1)
|
|
s1 = " sval_ = child_.firstChild.nodeValue\n"
|
|
outfile.write(s1)
|
|
s1 = " try:\n"
|
|
outfile.write(s1)
|
|
s1 = " ival_ = int(sval_)\n"
|
|
outfile.write(s1)
|
|
s1 = " except ValueError:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('requires integer -- %s' % child_.toxml())\n"
|
|
outfile.write(s1)
|
|
if childType == PositiveIntegerType:
|
|
s1 = " if ival_ <= 0:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Invalid positiveInteger (%s)' % child_.toxml()))\n"
|
|
outfile.write(s1)
|
|
if childType == NonPositiveIntegerType:
|
|
s1 = " if ival_ > 0:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Invalid nonPositiveInteger (%s)' % child_.toxml()))\n"
|
|
outfile.write(s1)
|
|
if childType == NegativeIntegerType:
|
|
s1 = " if ival_ >= 0:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Invalid negativeInteger (%s)' % child_.toxml()))\n"
|
|
outfile.write(s1)
|
|
if childType == NonNegativeIntegerType:
|
|
s1 = " if ival_ < 0:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('Invalid nonNegativeInteger (%s)' % child_.toxml()))\n"
|
|
outfile.write(s1)
|
|
s1 = " else:\n"
|
|
outfile.write(s1)
|
|
s1 = " ival_ = -1\n"
|
|
outfile.write(s1)
|
|
s1 = " obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
|
|
outfile.write(s1)
|
|
s1 = " MixedContainer.TypeInteger, '%s', ival_)\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " self.content_.append(obj_)\n"
|
|
outfile.write(s1)
|
|
elif childType == BooleanType:
|
|
s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " nodeName_ == '%s':\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " if child_.firstChild:\n"
|
|
outfile.write(s1)
|
|
s1 = " sval_ = child_.firstChild.nodeValue\n"
|
|
outfile.write(s1)
|
|
s1 = " if sval_ in ('true', '1'):\n"
|
|
outfile.write(s1)
|
|
s1 = " ival_ = 1\n"
|
|
outfile.write(s1)
|
|
s1 = " elif sval_ in ('false', '0'):\n"
|
|
outfile.write(s1)
|
|
s1 = " ival_ = 0\n"
|
|
outfile.write(s1)
|
|
s1 = " else:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('requires boolean -- %s' % child_.toxml())\n"
|
|
outfile.write(s1)
|
|
s1 = " obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
|
|
outfile.write(s1)
|
|
s1 = " MixedContainer.TypeInteger, '%s', ival_)\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " self.content_.append(obj_)\n"
|
|
outfile.write(s1)
|
|
elif childType == FloatType or childType == DoubleType or childType == DecimalType:
|
|
s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " nodeName_ == '%s':\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " if child_.firstChild:\n"
|
|
outfile.write(s1)
|
|
s1 = " sval_ = child_.firstChild.nodeValue\n"
|
|
outfile.write(s1)
|
|
s1 = " try:\n"
|
|
outfile.write(s1)
|
|
s1 = " fval_ = float(sval_)\n"
|
|
outfile.write(s1)
|
|
s1 = " except ValueError:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('requires float (or double) -- %s' % child_.toxml())\n"
|
|
outfile.write(s1)
|
|
s1 = " obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n"
|
|
outfile.write(s1)
|
|
s1 = " MixedContainer.TypeFloat, '%s', fval_)\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " self.content_.append(obj_)\n"
|
|
outfile.write(s1)
|
|
else:
|
|
# Perhaps it's a complexType that is defined right here.
|
|
# Generate (later) a class for the nested types.
|
|
if not delayed and not child in DelayedElements:
|
|
DelayedElements.append(child)
|
|
DelayedElements_subclass.append(child)
|
|
s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " nodeName_ == '%s':\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " childobj_ = %s%s.factory()\n" % (
|
|
prefix,
|
|
cleanupName(mapName(childType)),
|
|
)
|
|
outfile.write(s1)
|
|
s1 = " childobj_.build(child_)\n"
|
|
outfile.write(s1)
|
|
s1 = " obj_ = self.mixedclass_(MixedContainer.CategoryComplex,\n"
|
|
outfile.write(s1)
|
|
s1 = " MixedContainer.TypeNone, '%s', childobj_)\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " self.content_.append(obj_)\n"
|
|
outfile.write(s1)
|
|
|
|
|
|
def generateBuildMixed(outfile, prefix, element, keyword, delayed, hasChildren):
|
|
for child in element.getChildren():
|
|
generateBuildMixed_1(outfile, prefix, child, child, keyword, delayed)
|
|
hasChildren += 1
|
|
keyword = "elif"
|
|
# Does this element have a substitutionGroup?
|
|
# If so generate a clause for each element in the substitutionGroup.
|
|
if child.getName() in SubstitutionGroups:
|
|
for memberName in SubstitutionGroups[child.getName()]:
|
|
if memberName in ElementDict:
|
|
member = ElementDict[memberName]
|
|
generateBuildMixed_1(outfile, prefix, member, child, keyword, delayed)
|
|
s1 = " %s child_.nodeType == Node.TEXT_NODE:\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " obj_ = self.mixedclass_(MixedContainer.CategoryText,\n"
|
|
outfile.write(s1)
|
|
s1 = " MixedContainer.TypeNone, '', child_.nodeValue)\n"
|
|
outfile.write(s1)
|
|
s1 = " self.content_.append(obj_)\n"
|
|
outfile.write(s1)
|
|
## base = element.getBase()
|
|
## if base and base in ElementDict:
|
|
## parent = ElementDict[base]
|
|
## hasChildren = generateBuildMixed(outfile, prefix, parent, keyword, delayed, hasChildren)
|
|
return hasChildren
|
|
|
|
|
|
def generateBuildStandard_1(outfile, prefix, child, headChild, keyword, delayed):
|
|
global DelayedElements, DelayedElements_subclass
|
|
origName = child.getName()
|
|
name = cleanupName(child.getName())
|
|
mappedName = mapName(name)
|
|
headName = cleanupName(headChild.getName())
|
|
attrCount = len(child.getAttributeDefs())
|
|
# dbgprint(1, '(gbs) name: %s type: %s complex: %s id: %s' % \
|
|
# (child.getName(), child.getType(), child.isComplex(), id(child), ))
|
|
childType = child.getType()
|
|
if attrCount == 0 and (
|
|
childType in StringType
|
|
or childType == TokenType
|
|
or childType == DateTimeType
|
|
or childType == DateType
|
|
):
|
|
s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " nodeName_ == '%s':\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " %s_ = ''\n" % name
|
|
outfile.write(s1)
|
|
s1 = " for text__content_ in child_.childNodes:\n"
|
|
outfile.write(s1)
|
|
s1 = " %s_ += text__content_.nodeValue\n" % name
|
|
outfile.write(s1)
|
|
if childType == TokenType:
|
|
s1 = " %s_ = ' '.join(%s_.split())\n" % (
|
|
name,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
if child.getMaxOccurs() > 1:
|
|
s1 = " self.%s.append(%s_)\n" % (
|
|
mappedName,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
else:
|
|
s1 = " self.%s = %s_\n" % (
|
|
mappedName,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
elif (
|
|
childType in IntegerType
|
|
or childType == PositiveIntegerType
|
|
or childType == NonPositiveIntegerType
|
|
or childType == NegativeIntegerType
|
|
or childType == NonNegativeIntegerType
|
|
):
|
|
s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " nodeName_ == '%s':\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " if child_.firstChild:\n"
|
|
outfile.write(s1)
|
|
s1 = " sval_ = child_.firstChild.nodeValue\n"
|
|
outfile.write(s1)
|
|
s1 = " try:\n"
|
|
outfile.write(s1)
|
|
s1 = " ival_ = int(sval_)\n"
|
|
outfile.write(s1)
|
|
s1 = " except ValueError:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('requires integer -- %s' % child_.toxml())\n"
|
|
outfile.write(s1)
|
|
if childType == PositiveIntegerType:
|
|
s1 = " if ival_ <= 0:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('requires positiveInteger -- %s' % child_.toxml())\n"
|
|
outfile.write(s1)
|
|
elif childType == NonPositiveIntegerType:
|
|
s1 = " if ival_ > 0:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('requires nonPositiveInteger -- %s' % child_.toxml())\n"
|
|
outfile.write(s1)
|
|
elif childType == NegativeIntegerType:
|
|
s1 = " if ival_ >= 0:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('requires negativeInteger -- %s' % child_.toxml())\n"
|
|
outfile.write(s1)
|
|
elif childType == NonNegativeIntegerType:
|
|
s1 = " if ival_ < 0:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('requires nonNegativeInteger -- %s' % child_.toxml())\n"
|
|
outfile.write(s1)
|
|
if child.getMaxOccurs() > 1:
|
|
s1 = " self.%s.append(ival_)\n" % (mappedName,)
|
|
outfile.write(s1)
|
|
else:
|
|
s1 = " self.%s = ival_\n" % (mappedName,)
|
|
outfile.write(s1)
|
|
elif childType == BooleanType:
|
|
s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " nodeName_ == '%s':\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " if child_.firstChild:\n"
|
|
outfile.write(s1)
|
|
s1 = " sval_ = child_.firstChild.nodeValue\n"
|
|
outfile.write(s1)
|
|
s1 = " if sval_ in ('true', '1'):\n"
|
|
outfile.write(s1)
|
|
s1 = " ival_ = 1\n"
|
|
outfile.write(s1)
|
|
s1 = " elif sval_ in ('false', '0'):\n"
|
|
outfile.write(s1)
|
|
s1 = " ival_ = 0\n"
|
|
outfile.write(s1)
|
|
s1 = " else:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('requires boolean -- %s' % child_.toxml())\n"
|
|
outfile.write(s1)
|
|
if child.getMaxOccurs() > 1:
|
|
s1 = " self.%s.append(ival_)\n" % (mappedName,)
|
|
outfile.write(s1)
|
|
else:
|
|
s1 = " self.%s = ival_\n" % (mappedName,)
|
|
outfile.write(s1)
|
|
elif childType == FloatType or childType == DoubleType or childType == DecimalType:
|
|
s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " nodeName_ == '%s':\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " if child_.firstChild:\n"
|
|
outfile.write(s1)
|
|
s1 = " sval_ = child_.firstChild.nodeValue\n"
|
|
outfile.write(s1)
|
|
s1 = " try:\n"
|
|
outfile.write(s1)
|
|
s1 = " fval_ = float(sval_)\n"
|
|
outfile.write(s1)
|
|
s1 = " except ValueError:\n"
|
|
outfile.write(s1)
|
|
s1 = " raise ValueError('requires float (or double) -- %s' % child_.toxml())\n"
|
|
outfile.write(s1)
|
|
if child.getMaxOccurs() > 1:
|
|
s1 = " self.%s.append(fval_)\n" % (mappedName,)
|
|
outfile.write(s1)
|
|
else:
|
|
s1 = " self.%s = fval_\n" % (mappedName,)
|
|
outfile.write(s1)
|
|
else:
|
|
# Perhaps it's a complexType that is defined right here.
|
|
# Generate (later) a class for the nested types.
|
|
if not delayed and not child in DelayedElements:
|
|
DelayedElements.append(child)
|
|
DelayedElements_subclass.append(child)
|
|
s1 = " %s child_.nodeType == Node.ELEMENT_NODE and \\\n" % keyword
|
|
outfile.write(s1)
|
|
s1 = " nodeName_ == '%s':\n" % origName
|
|
outfile.write(s1)
|
|
s1 = " obj_ = %s%s.factory()\n" % (
|
|
prefix,
|
|
cleanupName(mapName(childType)),
|
|
)
|
|
outfile.write(s1)
|
|
s1 = " obj_.build(child_)\n"
|
|
outfile.write(s1)
|
|
if headChild.getMaxOccurs() > 1:
|
|
s1 = " self.%s.append(obj_)\n" % headName
|
|
outfile.write(s1)
|
|
else:
|
|
s1 = " self.set%s(obj_)\n" % headName.capitalize()
|
|
outfile.write(s1)
|
|
|
|
|
|
def generateBuildStandard(outfile, prefix, element, keyword, delayed, hasChildren):
|
|
for child in element.getChildren():
|
|
# dbgprint(1, '(generateBuildStandard) %s type: %s' % (child.getName(), child.getType(),))
|
|
generateBuildStandard_1(outfile, prefix, child, child, keyword, delayed)
|
|
hasChildren += 1
|
|
keyword = "elif"
|
|
# Does this element have a substitutionGroup?
|
|
# If so generate a clause for each element in the substitutionGroup.
|
|
childName = child.getName()
|
|
if childName in SubstitutionGroups:
|
|
# dbgprint(1, '(BldStd) found: %s in %s' % (childName, SubstitutionGroups))
|
|
for memberName in SubstitutionGroups[childName]:
|
|
memberName = cleanupName(memberName)
|
|
if memberName in ElementDict:
|
|
member = ElementDict[memberName]
|
|
# dbgprint(1, '(BldStd) found subst: %s/%s' % (memberName, member))
|
|
generateBuildStandard_1(outfile, prefix, member, child, keyword, delayed)
|
|
return hasChildren
|
|
|
|
|
|
def generateBuildFn(outfile, prefix, element, delayed):
|
|
base = element.getBase()
|
|
outfile.write(" def build(self, node_):\n")
|
|
outfile.write(" attrs = node_.attributes\n")
|
|
outfile.write(" self.buildAttributes(attrs)\n")
|
|
## if len(element.getChildren()) > 0:
|
|
outfile.write(" for child_ in node_.childNodes:\n")
|
|
outfile.write(" nodeName_ = child_.nodeName.split(':')[-1]\n")
|
|
outfile.write(" self.buildChildren(child_, nodeName_)\n")
|
|
outfile.write(" def buildAttributes(self, attrs):\n")
|
|
hasAttributes = generateBuildAttributes(outfile, element, 0)
|
|
if base:
|
|
hasAttributes += 1
|
|
s1 = " %s.buildAttributes(self, attrs)\n" % (base,)
|
|
outfile.write(s1)
|
|
if hasAttributes == 0:
|
|
outfile.write(" pass\n")
|
|
outfile.write(" def buildChildren(self, child_, nodeName_):\n")
|
|
keyword = "if"
|
|
hasChildren = 0
|
|
if element.isMixed():
|
|
hasChildren = generateBuildMixed(outfile, prefix, element, keyword, delayed, hasChildren)
|
|
else: # not element.isMixed()
|
|
hasChildren = generateBuildStandard(outfile, prefix, element, keyword, delayed, hasChildren)
|
|
if hasChildren == 0:
|
|
s1 = " self.valueOf_ = ''\n"
|
|
outfile.write(s1)
|
|
s1 = " for child in child_.childNodes:\n"
|
|
outfile.write(s1)
|
|
s1 = " if child.nodeType == Node.TEXT_NODE:\n"
|
|
outfile.write(s1)
|
|
s1 = " self.valueOf_ += child.nodeValue\n"
|
|
outfile.write(s1)
|
|
if base and base in ElementDict:
|
|
parent = ElementDict[base]
|
|
if len(parent.getChildren()) > 0:
|
|
s1 = " %s.buildChildren(self, child_, nodeName_)\n" % (base,)
|
|
outfile.write(s1)
|
|
|
|
|
|
def countElementChildren(element, count):
|
|
count += len(element.getChildren())
|
|
base = element.getBase()
|
|
if base and base in ElementDict:
|
|
parent = ElementDict[base]
|
|
countElementChildren(parent, count)
|
|
return count
|
|
|
|
|
|
def buildCtorArgs_multilevel(element):
|
|
content = []
|
|
add = content.append
|
|
buildCtorArgs_multilevel_aux(add, element)
|
|
count = countElementChildren(element, 0)
|
|
if count == 0:
|
|
add(", valueOf_=''")
|
|
if element.isMixed():
|
|
add(", mixedclass_=None")
|
|
add(", content_=None")
|
|
s1 = "".join(content)
|
|
return s1
|
|
|
|
|
|
def buildCtorArgs_multilevel_aux(add, element):
|
|
buildCtorArgs_aux(add, element)
|
|
base = element.getBase()
|
|
if base and base in ElementDict:
|
|
parent = ElementDict[base]
|
|
buildCtorArgs_multilevel_aux(add, parent)
|
|
|
|
|
|
def buildCtorArgs_1_level(element):
|
|
content = []
|
|
add = content.append
|
|
buildCtorArgs_aux(add, element)
|
|
count = countElementChildren(element, 0)
|
|
if count == 0:
|
|
add(", valueOf_=''")
|
|
s1 = "".join(content)
|
|
return s1
|
|
|
|
|
|
def buildCtorArgs_aux(add, element):
|
|
attrDefs = element.getAttributeDefs()
|
|
for key in attrDefs:
|
|
attrDef = attrDefs[key]
|
|
name = attrDef.getName()
|
|
mappedName = name.replace(":", "_")
|
|
mappedName = cleanupName(mapName(mappedName))
|
|
try:
|
|
atype = attrDef.getData_type()
|
|
except KeyError:
|
|
atype = StringType
|
|
if atype in StringType or atype == TokenType or atype == DateTimeType or atype == DateType:
|
|
add(", %s=''" % mappedName)
|
|
elif atype in IntegerType:
|
|
add(", %s=-1" % mappedName)
|
|
elif atype == PositiveIntegerType:
|
|
add(", %s=1" % mappedName)
|
|
elif atype == NonPositiveIntegerType:
|
|
add(", %s=0" % mappedName)
|
|
elif atype == NegativeIntegerType:
|
|
add(", %s=-1" % mappedName)
|
|
elif atype == NonNegativeIntegerType:
|
|
add(", %s=0" % mappedName)
|
|
elif atype == BooleanType:
|
|
add(", %s=0" % mappedName)
|
|
elif atype == FloatType or atype == DoubleType or atype == DecimalType:
|
|
add(", %s=0.0" % mappedName)
|
|
else:
|
|
add(", %s=None" % mappedName)
|
|
nestedElements = 0
|
|
for child in element.getChildren():
|
|
nestedElements = 1
|
|
if child.getMaxOccurs() > 1:
|
|
add(", %s=None" % child.getCleanName())
|
|
else:
|
|
childType = child.getType()
|
|
if (
|
|
childType in StringType
|
|
or childType == TokenType
|
|
or childType == DateTimeType
|
|
or childType == DateType
|
|
):
|
|
add(", %s=''" % child.getCleanName())
|
|
elif childType in IntegerType:
|
|
add(", %s=-1" % child.getCleanName())
|
|
elif childType == PositiveIntegerType:
|
|
add(", %s=1" % child.getCleanName())
|
|
elif childType == NonPositiveIntegerType:
|
|
add(", %s=0" % child.getCleanName())
|
|
elif childType == NegativeIntegerType:
|
|
add(", %s=-1" % child.getCleanName())
|
|
elif childType == NonNegativeIntegerType:
|
|
add(", %s=0" % child.getCleanName())
|
|
elif childType == BooleanType:
|
|
add(", %s=0" % child.getCleanName())
|
|
elif childType == FloatType or childType == DoubleType or childType == DecimalType:
|
|
add(", %s=0.0" % child.getCleanName())
|
|
else:
|
|
add(", %s=None" % child.getCleanName())
|
|
|
|
|
|
MixedCtorInitializers = """\
|
|
if mixedclass_ is None:
|
|
self.mixedclass_ = MixedContainer
|
|
else:
|
|
self.mixedclass_ = mixedclass_
|
|
if content_ is None:
|
|
self.content_ = []
|
|
else:
|
|
self.content_ = content_
|
|
"""
|
|
|
|
|
|
def generateCtor(outfile, element):
|
|
s2 = buildCtorArgs_multilevel(element)
|
|
s1 = " def __init__(self%s):\n" % s2
|
|
outfile.write(s1)
|
|
base = element.getBase()
|
|
if base and base in ElementDict:
|
|
parent = ElementDict[base]
|
|
s2 = buildCtorParams(parent)
|
|
s1 = " %s.__init__(self%s)\n" % (
|
|
base,
|
|
s2,
|
|
)
|
|
outfile.write(s1)
|
|
attrDefs = element.getAttributeDefs()
|
|
for key in attrDefs:
|
|
attrDef = attrDefs[key]
|
|
mappedName = cleanupName(attrDef.getName())
|
|
mappedName = mapName(mappedName)
|
|
s1 = " self.%s = %s\n" % (mappedName, mappedName)
|
|
outfile.write(s1)
|
|
member = 1
|
|
# Generate member initializers in ctor.
|
|
if element.isMixed():
|
|
outfile.write(MixedCtorInitializers)
|
|
else:
|
|
member = 0
|
|
nestedElements = 0
|
|
for child in element.getChildren():
|
|
name = cleanupName(child.getCleanName())
|
|
if child.getMaxOccurs() > 1:
|
|
s1 = " if %s is None:\n" % (name,)
|
|
outfile.write(s1)
|
|
s1 = " self.%s = []\n" % (name,)
|
|
outfile.write(s1)
|
|
s1 = " else:\n"
|
|
outfile.write(s1)
|
|
s1 = " self.%s = %s\n" % (name, name)
|
|
outfile.write(s1)
|
|
else:
|
|
s1 = " self.%s = %s\n" % (name, name)
|
|
outfile.write(s1)
|
|
member = 1
|
|
nestedElements = 1
|
|
if not nestedElements:
|
|
s1 = " self.valueOf_ = valueOf_\n"
|
|
outfile.write(s1)
|
|
member = 1
|
|
if element.getAnyAttribute():
|
|
s1 = " self.anyAttributes_ = {}\n"
|
|
outfile.write(s1)
|
|
member = 1
|
|
if not member:
|
|
outfile.write(" pass\n")
|
|
|
|
|
|
# Generate get/set/add member functions.
|
|
def generateGettersAndSetters(outfile, element):
|
|
nestedElements = 0
|
|
for child in element.getChildren():
|
|
nestedElements = 1
|
|
name = cleanupName(child.getCleanName())
|
|
unmappedName = cleanupName(child.getName())
|
|
capName = unmappedName.capitalize()
|
|
s1 = " def get%s(self): return self.%s\n" % (capName, name)
|
|
outfile.write(s1)
|
|
s1 = " def set%s(self, %s): self.%s = %s\n" % (capName, name, name, name)
|
|
outfile.write(s1)
|
|
if child.getMaxOccurs() > 1:
|
|
s1 = " def add%s(self, value): self.%s.append(value)\n" % (capName, name)
|
|
outfile.write(s1)
|
|
s1 = " def insert%s(self, index, value): self.%s[index] = value\n" % (
|
|
capName,
|
|
name,
|
|
)
|
|
outfile.write(s1)
|
|
if GenerateProperties:
|
|
s1 = " %sProp = property(get%s, set%s)\n" % (
|
|
unmappedName,
|
|
capName,
|
|
capName,
|
|
)
|
|
outfile.write(s1)
|
|
attrDefs = element.getAttributeDefs()
|
|
for key in attrDefs:
|
|
attrDef = attrDefs[key]
|
|
name = cleanupName(attrDef.getName().replace(":", "_"))
|
|
mappedName = mapName(name)
|
|
capName = mappedName.capitalize()
|
|
s1 = " def get%s(self): return self.%s\n" % (name.capitalize(), mappedName)
|
|
outfile.write(s1)
|
|
#
|
|
# What? An attribute cannot occur multiple times on the same
|
|
# element. No attribute is a list of values. Right?
|
|
## if element.getMaxOccurs() > 1:
|
|
## s1 = ' def add%s(self, %s): self.%s.append(%s)\n' % \
|
|
## (capName, mappedName, mappedName, mappedName)
|
|
## outfile.write(s1)
|
|
## s1 = ' def set%s(self, %s, index): self.%s[index] = %s\n' % \
|
|
## (name.capitalize(), mappedName, mappedName, mappedName)
|
|
## outfile.write(s1)
|
|
## else:
|
|
s1 = " def set%s(self, %s): self.%s = %s\n" % (
|
|
name.capitalize(),
|
|
mappedName,
|
|
mappedName,
|
|
mappedName,
|
|
)
|
|
outfile.write(s1)
|
|
if GenerateProperties:
|
|
s1 = " %sProp = property(get%s, set%s)\n" % (
|
|
mappedName,
|
|
capName,
|
|
capName,
|
|
)
|
|
outfile.write(s1)
|
|
if not nestedElements:
|
|
s1 = " def getValueOf_(self): return self.valueOf_\n"
|
|
outfile.write(s1)
|
|
s1 = " def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_\n"
|
|
outfile.write(s1)
|
|
if element.getAnyAttribute():
|
|
s1 = " def getAnyAttributes_(self): return self.anyAttributes_\n"
|
|
outfile.write(s1)
|
|
s1 = " def setAnyAttributes_(self, anyAttributes_): self.anyAttributes_ = anyAttributes_\n"
|
|
outfile.write(s1)
|
|
|
|
|
|
def generateClasses(outfile, prefix, element, delayed):
|
|
base = element.getBase()
|
|
wrt = outfile.write
|
|
if (not element.getChildren()) and (not element.getAttributeDefs()):
|
|
return
|
|
# If this element is an extension (has a base) and the base has
|
|
# not been generated, then postpone it.
|
|
if base and base in ElementDict:
|
|
parent = ElementDict[base]
|
|
parentName = parent.getName()
|
|
if parentName not in AlreadyGenerated:
|
|
PostponedExtensions.append(element)
|
|
return
|
|
if element.getName() in AlreadyGenerated:
|
|
return
|
|
AlreadyGenerated.append(element.getName())
|
|
if element.getMixedExtensionError():
|
|
print(
|
|
"*** Element %s extension chain contains mixed and non-mixed content. Not generated."
|
|
% (element.getName(),)
|
|
)
|
|
return
|
|
ElementsForSubclasses.append(element)
|
|
name = element.getCleanName()
|
|
if GenerateProperties:
|
|
if base:
|
|
s1 = "class %s%s(object, %s):\n" % (prefix, name, base)
|
|
else:
|
|
s1 = "class %s%s(object):\n" % (prefix, name)
|
|
else:
|
|
if base:
|
|
s1 = "class %s%s(%s):\n" % (prefix, name, base)
|
|
else:
|
|
s1 = "class %s%s:\n" % (prefix, name)
|
|
wrt(s1)
|
|
wrt(" subclass = None\n")
|
|
generateCtor(outfile, element)
|
|
wrt(" def factory(*args_, **kwargs_):\n")
|
|
wrt(" if %s%s.subclass:\n" % (prefix, name))
|
|
wrt(" return %s%s.subclass(*args_, **kwargs_)\n" % (prefix, name))
|
|
wrt(" else:\n")
|
|
wrt(" return %s%s(*args_, **kwargs_)\n" % (prefix, name))
|
|
wrt(" factory = staticmethod(factory)\n")
|
|
generateGettersAndSetters(outfile, element)
|
|
generateExportFn(outfile, prefix, element)
|
|
generateExportLiteralFn(outfile, prefix, element)
|
|
generateBuildFn(outfile, prefix, element, delayed)
|
|
wrt("# end class %s\n" % name)
|
|
wrt("\n\n")
|
|
|
|
|
|
#
|
|
# Generate the SAX handler class for SAX parsing.
|
|
#
|
|
|
|
SAX_STARTELEMENT_1 = """\
|
|
def startElement(self, name, attrs):
|
|
done = 0
|
|
if name == '%s':
|
|
obj = %s.factory()
|
|
stackObj = SaxStackElement('%s', obj)
|
|
self.stack.append(stackObj)
|
|
done = 1
|
|
"""
|
|
|
|
SAX_STARTELEMENT_2 = """\
|
|
stackObj = SaxStackElement('%s', obj)
|
|
self.stack.append(stackObj)
|
|
done = 1
|
|
"""
|
|
|
|
SAX_STARTELEMENT_3 = """\
|
|
stackObj = SaxStackElement('%s', None)
|
|
self.stack.append(stackObj)
|
|
done = 1
|
|
"""
|
|
|
|
SAX_STARTELEMENT_4 = """\
|
|
if not done:
|
|
self.reportError('"%s" element not allowed here.' % name)
|
|
"""
|
|
|
|
SAX_ATTR_INTEGER = """\
|
|
val = attrs.get('%s', None)
|
|
if val is not None:
|
|
try:
|
|
obj.set%s(int(val))
|
|
except:
|
|
self.reportError('"%s" attribute must be integer')
|
|
"""
|
|
|
|
SAX_ATTR_BOOLEAN = """\
|
|
val = attrs.get('%s', None)
|
|
if val is not None:
|
|
if val in ('true', '1'):
|
|
obj.set%s(1)
|
|
elif val in ('false', '0'):
|
|
obj.set%s(0)
|
|
else:
|
|
self.reportError('"%s" attribute must be boolean ("true", "1", "false", "0")')
|
|
"""
|
|
|
|
SAX_ATTR_FLOAT = """\
|
|
val = attrs.get('%s', None)
|
|
if val is not None:
|
|
try:
|
|
obj.set%s(float(val))
|
|
except:
|
|
self.reportError('"%s" attribute must be float')
|
|
"""
|
|
|
|
SAX_ATTR_STRING = """\
|
|
val = attrs.get('%s', None)
|
|
if val is not None:
|
|
obj.set%s(val)
|
|
"""
|
|
|
|
|
|
def getClassName(element):
|
|
name = element.getCleanName()
|
|
return name
|
|
|
|
|
|
def generateSaxAttributes(wrt, element):
|
|
attrDefs = element.getAttributeDefs()
|
|
for key in attrDefs:
|
|
attrDef = attrDefs[key]
|
|
name = attrDef.getName()
|
|
atype = attrDef.getData_type()
|
|
if atype in IntegerType:
|
|
s1 = SAX_ATTR_INTEGER % (name, name.capitalize(), name)
|
|
wrt(s1)
|
|
## s1 = " if attrs.get('%s'):\n" % name
|
|
## wrt(s1)
|
|
## s1 = ' try:\n'
|
|
## wrt(s1)
|
|
## s1 = " self.%s = int(attrs.get('%s').value)\n" % \
|
|
## (name, name)
|
|
## wrt(s1)
|
|
## s1 = ' except ValueError:\n'
|
|
## wrt(s1)
|
|
## s1 = " raise ValueError('Bad integer')\n"
|
|
## wrt(s1)
|
|
elif atype == BooleanType:
|
|
s1 = SAX_ATTR_BOOLEAN % (name, name.capitalize(), name.capitalize(), name)
|
|
wrt(s1)
|
|
## wrt(s1)
|
|
## s1 = " if attrs.get('%s'):\n" % name
|
|
## wrt(s1)
|
|
## s1 = " if attrs.get('%s').value in ('true', '1'):\n" % \
|
|
## name
|
|
## wrt(s1)
|
|
## s1 = " self.%s = 1\n" % \
|
|
## name
|
|
## wrt(s1)
|
|
## s1 = " elif attrs.get('%s').value in ('false', '0'):\n" % \
|
|
## name
|
|
## wrt(s1)
|
|
## s1 = " self.%s = 0\n" % \
|
|
## name
|
|
## wrt(s1)
|
|
## s1 = ' else:\n'
|
|
## wrt(s1)
|
|
## s1 = " raise ValueError('Bad boolean')\n"
|
|
## wrt(s1)
|
|
elif atype == FloatType or atype == DoubleType or atype == DecimalType:
|
|
s1 = SAX_ATTR_FLOAT % (name, name.capitalize(), name)
|
|
wrt(s1)
|
|
## s1 = " if attrs.get('%s'):\n" % name
|
|
## wrt(s1)
|
|
## s1 = ' try:\n'
|
|
## wrt(s1)
|
|
## s1 = " self.%s = float(attrs.get('%s').value)\n" % \
|
|
## (name, name)
|
|
## wrt(s1)
|
|
## s1 = ' except:\n'
|
|
## wrt(s1)
|
|
## s1 = " raise ValueError('Bad float/double')\n"
|
|
## wrt(s1)
|
|
else:
|
|
# Assume attr['type'] in StringType or attr['type'] == DateTimeType:
|
|
s1 = SAX_ATTR_STRING % (name, name.capitalize())
|
|
wrt(s1)
|
|
|
|
|
|
## s1 = " if attrs.get('%s'):\n" % name
|
|
## wrt(s1)
|
|
## s1 = " self.%s = attrs.get('%s').value\n" % (name, name)
|
|
## wrt(s1)
|
|
|
|
|
|
def generateSAXStartElement_1(wrt, element):
|
|
origName = element.getName()
|
|
typeName = cleanupName(mapName(element.getRawType()))
|
|
className = element.getCleanName()
|
|
s1 = " elif name == '%s':\n" % origName
|
|
wrt(s1)
|
|
if element.isComplex():
|
|
s1 = " obj = %s.factory()\n" % cleanupName(typeName)
|
|
wrt(s1)
|
|
element1 = SaxElementDict[element.getCleanName()]
|
|
generateSaxAttributes(wrt, element1)
|
|
if element.isComplex():
|
|
s1 = SAX_STARTELEMENT_2 % className
|
|
else:
|
|
s1 = SAX_STARTELEMENT_3 % className
|
|
wrt(s1)
|
|
|
|
|
|
def generateSAXStartElement(outfile, root, elementList):
|
|
wrt = outfile.write
|
|
name = root.getChildren()[0].getName()
|
|
s1 = SAX_STARTELEMENT_1 % (name, name, name)
|
|
wrt(s1)
|
|
for element, parent in elementList:
|
|
generateSAXStartElement_1(wrt, element)
|
|
s1 = SAX_STARTELEMENT_4
|
|
wrt(s1)
|
|
wrt("\n")
|
|
|
|
|
|
SAX_ENDELEMENT_1 = """\
|
|
if name == '%s':
|
|
if len(self.stack) == 1:
|
|
self.root = self.stack[-1].obj
|
|
self.stack.pop()
|
|
done = 1
|
|
"""
|
|
|
|
SAX_ENDELEMENT_2 = """\
|
|
elif name == '%s':
|
|
if len(self.stack) >= 2:
|
|
self.stack[-2].obj.%s%s(self.stack[-1].obj)
|
|
self.stack.pop()
|
|
done = 1
|
|
"""
|
|
|
|
SAX_ENDELEMENT_3 = """\
|
|
elif name == '%s':
|
|
if len(self.stack) >= 2:
|
|
content = self.stack[-1].content
|
|
%s self.stack[-2].obj.%s%s(content)
|
|
self.stack.pop()
|
|
done = 1
|
|
"""
|
|
|
|
SAX_ENDELEMENT_INT = """\
|
|
if content:
|
|
try:
|
|
content = int(content)
|
|
except:
|
|
self.reportError('"%s" must be integer -- content: %%s' %% content)
|
|
else:
|
|
content = -1
|
|
"""
|
|
|
|
SAX_ENDELEMENT_FLOAT = """\
|
|
if content:
|
|
try:
|
|
content = float(content)
|
|
except:
|
|
self.reportError('"%s" must be float -- content: %%s' %% content)
|
|
else:
|
|
content = -1
|
|
"""
|
|
|
|
SAX_ENDELEMENT_BOOLEAN = """\
|
|
if content and content in ('true', '1'):
|
|
content = 1
|
|
else:
|
|
content = 0
|
|
"""
|
|
|
|
SAX_ENDELEMENT_4 = """\
|
|
if not done:
|
|
self.reportError('"%s" element not allowed here.' % name)
|
|
"""
|
|
|
|
|
|
def generateParentCheck(parent):
|
|
s1 = "self.stack[-2].name == '%s'" % getClassName(parent)
|
|
return s1
|
|
|
|
|
|
## strList = []
|
|
## for parent in parentList:
|
|
## strList.append("self.stack[-2].name == '%s'" % \
|
|
## parent.getName())
|
|
## s1 = ' or '.join(strList)
|
|
## if len(parentList) > 1:
|
|
## s1 = '(%s)' % s1
|
|
## return s1
|
|
|
|
|
|
def generateSAXEndElement(outfile, root, elementList):
|
|
wrt = outfile.write
|
|
s1 = " def endElement(self, name):\n"
|
|
wrt(s1)
|
|
s1 = " done = 0\n"
|
|
wrt(s1)
|
|
name = root.getChildren()[0].getName()
|
|
s1 = SAX_ENDELEMENT_1 % (name,)
|
|
wrt(s1)
|
|
for element, parent in elementList:
|
|
# s2 = generateParentCheck(parent)
|
|
name = element.getName()
|
|
capName = element.getUnmappedCleanName().capitalize()
|
|
if element.isComplex():
|
|
if element.getMaxOccurs() > 1:
|
|
s1 = SAX_ENDELEMENT_2 % (name, "add", capName)
|
|
else:
|
|
s1 = SAX_ENDELEMENT_2 % (name, "set", capName)
|
|
else:
|
|
etype = element.getType()
|
|
if etype in IntegerType:
|
|
s3 = SAX_ENDELEMENT_INT % name
|
|
elif etype == FloatType or etype == DoubleType or etype == DecimalType:
|
|
s3 = SAX_ENDELEMENT_FLOAT % name
|
|
elif etype == BooleanType:
|
|
s3 = SAX_ENDELEMENT_BOOLEAN
|
|
else:
|
|
s3 = ""
|
|
if element.getMaxOccurs() > 1:
|
|
s1 = SAX_ENDELEMENT_3 % (name, s3, "add", capName)
|
|
else:
|
|
s1 = SAX_ENDELEMENT_3 % (name, s3, "set", capName)
|
|
wrt(s1)
|
|
s1 = SAX_ENDELEMENT_4
|
|
wrt(s1)
|
|
wrt("\n")
|
|
|
|
|
|
SAX_HEADER = """\
|
|
from xml.sax import handler, make_parser
|
|
|
|
class SaxStackElement:
|
|
def __init__(self, name='', obj=None):
|
|
self.name = name
|
|
self.obj = obj
|
|
self.content = ''
|
|
|
|
#
|
|
# SAX handler
|
|
#
|
|
class Sax%sHandler(handler.ContentHandler):
|
|
def __init__(self):
|
|
self.stack = []
|
|
self.root = None
|
|
|
|
def getRoot(self):
|
|
return self.root
|
|
|
|
def setDocumentLocator(self, locator):
|
|
self.locator = locator
|
|
|
|
def showError(self, msg):
|
|
print('*** (showError):', msg)
|
|
sys.exit(-1)
|
|
|
|
"""
|
|
|
|
SAX_FOOTER = """\
|
|
def characters(self, chrs, start, end):
|
|
if len(self.stack) > 0:
|
|
self.stack[-1].content += chrs[start:end]
|
|
|
|
def reportError(self, mesg):
|
|
locator = self.locator
|
|
sys.stderr.write('Doc: %s Line: %d Column: %d\\n' % \\
|
|
(locator.getSystemId(), locator.getLineNumber(),
|
|
locator.getColumnNumber() + 1))
|
|
sys.stderr.write(mesg)
|
|
sys.stderr.write('\\n')
|
|
sys.exit(-1)
|
|
#raise RuntimeError
|
|
|
|
"""
|
|
|
|
|
|
##def produceAllElements(element, parent):
|
|
## if element.getType() in StringType or \
|
|
## element.getType() in IntegerType or \
|
|
## element.getType() == DecimalType or \
|
|
## element.getType() == FloatType or \
|
|
## element.getType() == DoubleType or \
|
|
## element.getType() == BooleanType or \
|
|
## len(element.getChildren()) != 0:
|
|
## yield (element, parent)
|
|
## for child in element.getChildren():
|
|
## for element1, parent1 in produceAllElements(child, element):
|
|
## yield (element1, parent1)
|
|
|
|
|
|
#
|
|
# This version of produceAllElements does not use 'yield' and is,
|
|
# therefore, usable with older versions of Python.
|
|
def produceAllElements_nogen(element, parent, collection):
|
|
collection.append((element, parent))
|
|
for child in element.getChildren():
|
|
produceAllElements_nogen(child, element, collection)
|
|
|
|
|
|
def generateSAXHndlr(outfile, root):
|
|
firstElement = root.getChildren()[0]
|
|
name = firstElement.getName()
|
|
s1 = SAX_HEADER % cleanupName(name.capitalize())
|
|
outfile.write(s1)
|
|
elementList = []
|
|
collection = []
|
|
produceAllElements_nogen(root, None, collection)
|
|
for element, parent in collection:
|
|
if element == root:
|
|
continue
|
|
elementList.append((element, parent))
|
|
## print '(gsh) element: %s/%s/%d parent: %s/%s/%d' % \
|
|
## (element.getUnmappedCleanName(), element.getType(), id(element),
|
|
## #(element.getName(), element.getType(), id(element),
|
|
## parent.getName(), parent.getType(), id(parent))
|
|
## if parent.getName() == 'booster':
|
|
## ipshell('at booster -- Entering ipshell.\\nHit Ctrl-D to exit')
|
|
## if element in elementDict:
|
|
## elementDict[element].append(parent)
|
|
## else:
|
|
## elementDict[element] = [parent]
|
|
elementList1 = []
|
|
alreadySeen = []
|
|
for element, parent in elementList:
|
|
if parent == root:
|
|
continue
|
|
if element.getName() in alreadySeen:
|
|
continue
|
|
alreadySeen.append(element.getName())
|
|
elementList1.append((element, parent))
|
|
## print '+' * 20
|
|
## for element, parent in elementList1:
|
|
## print '(gsh) element: %s/%s/%d parent: %s/%s/%d' % \
|
|
## (element.getUnmappedCleanName(), element.getType(), id(element),
|
|
## #(element.getName(), element.getType(), id(element),
|
|
## parent.getName(), parent.getType(), id(parent))
|
|
generateSAXStartElement(outfile, root, elementList1)
|
|
generateSAXEndElement(outfile, root, elementList1)
|
|
s1 = SAX_FOOTER
|
|
outfile.write(s1)
|
|
|
|
|
|
def collect(element, elements):
|
|
if element.getName() != "root":
|
|
elements.append(element)
|
|
for child in element.getChildren():
|
|
collect(child, elements)
|
|
|
|
|
|
TEMPLATE_HEADER = """\
|
|
#!/usr/bin/env python3
|
|
|
|
#
|
|
# Generated %s by generateDS.py.
|
|
# Update it with: python generateDS.py -o generateModel_Module.py generateMetaModel_Module.xsd
|
|
#
|
|
# WARNING! All changes made in this file will be lost!
|
|
#
|
|
|
|
|
|
import sys
|
|
import getopt
|
|
from xml.dom import minidom
|
|
from xml.dom import Node
|
|
|
|
#
|
|
# If you have installed IPython you can uncomment and use the following.
|
|
# IPython is available from http://ipython.scipy.org/.
|
|
#
|
|
|
|
## from IPython.Shell import IPShellEmbed
|
|
## args = ''
|
|
## ipshell = IPShellEmbed(args,
|
|
## banner = 'Dropping into IPython',
|
|
## exit_msg = 'Leaving Interpreter, back to program.')
|
|
|
|
# Then use the following line where and when you want to drop into the
|
|
# IPython shell:
|
|
# ipshell('<some message> -- Entering ipshell.\\nHit Ctrl-D to exit')
|
|
|
|
#
|
|
# Support/utility functions.
|
|
#
|
|
|
|
def showIndent(outfile, level):
|
|
for idx in range(level):
|
|
outfile.write(' ')
|
|
|
|
def quote_xml(inStr):
|
|
s1 = inStr
|
|
s1 = s1.replace('&', '&')
|
|
s1 = s1.replace('<', '<')
|
|
s1 = s1.replace('"', '"')
|
|
return s1
|
|
|
|
def quote_python(inStr):
|
|
s1 = inStr
|
|
if s1.find("'") == -1:
|
|
if s1.find('\\n') == -1:
|
|
return "'%%s'" %% s1
|
|
else:
|
|
return "'''%%s'''" %% s1
|
|
else:
|
|
if s1.find('"') != -1:
|
|
s1 = s1.replace('"', '\\\\"')
|
|
if s1.find('\\n') == -1:
|
|
return '"%%s"' %% s1
|
|
else:
|
|
return '\"\"\"%%s\"\"\"' %% s1
|
|
|
|
|
|
class MixedContainer:
|
|
# Constants for category:
|
|
CategoryNone = 0
|
|
CategoryText = 1
|
|
CategorySimple = 2
|
|
CategoryComplex = 3
|
|
# Constants for content_type:
|
|
TypeNone = 0
|
|
TypeText = 1
|
|
TypeString = 2
|
|
TypeInteger = 3
|
|
TypeFloat = 4
|
|
TypeDecimal = 5
|
|
TypeDouble = 6
|
|
TypeBoolean = 7
|
|
def __init__(self, category, content_type, name, value):
|
|
self.category = category
|
|
self.content_type = content_type
|
|
self.name = name
|
|
self.value = value
|
|
def getCategory(self):
|
|
return self.category
|
|
def getContenttype(self, content_type):
|
|
return self.content_type
|
|
def getValue(self):
|
|
return self.value
|
|
def getName(self):
|
|
return self.name
|
|
def export(self, outfile, level, name):
|
|
if self.category == MixedContainer.CategoryText:
|
|
outfile.write(self.value)
|
|
elif self.category == MixedContainer.CategorySimple:
|
|
self.exportSimple(outfile, level, name)
|
|
else: # category == MixedContainer.CategoryComplex
|
|
self.value.export(outfile, level, name)
|
|
def exportSimple(self, outfile, level, name):
|
|
if self.content_type == MixedContainer.TypeString:
|
|
outfile.write('<%%s>%%s</%%s>' %% (self.name, self.value, self.name))
|
|
elif self.content_type == MixedContainer.TypeInteger or \\
|
|
self.content_type == MixedContainer.TypeBoolean:
|
|
outfile.write('<%%s>%%d</%%s>' %% (self.name, self.value, self.name))
|
|
elif self.content_type == MixedContainer.TypeFloat or \\
|
|
self.content_type == MixedContainer.TypeDecimal:
|
|
outfile.write('<%%s>%%f</%%s>' %% (self.name, self.value, self.name))
|
|
elif self.content_type == MixedContainer.TypeDouble:
|
|
outfile.write('<%%s>%%g</%%s>' %% (self.name, self.value, self.name))
|
|
def exportLiteral(self, outfile, level, name):
|
|
if self.category == MixedContainer.CategoryText:
|
|
showIndent(outfile, level)
|
|
outfile.write('MixedContainer(%%d, %%d, "%%s", "%%s"),\\n' %% \\
|
|
(self.category, self.content_type, self.name, self.value))
|
|
elif self.category == MixedContainer.CategorySimple:
|
|
showIndent(outfile, level)
|
|
outfile.write('MixedContainer(%%d, %%d, "%%s", "%%s"),\\n' %% \\
|
|
(self.category, self.content_type, self.name, self.value))
|
|
else: # category == MixedContainer.CategoryComplex
|
|
showIndent(outfile, level)
|
|
outfile.write('MixedContainer(%%d, %%d, "%%s",\\n' %% \\
|
|
(self.category, self.content_type, self.name,))
|
|
self.value.exportLiteral(outfile, level + 1)
|
|
showIndent(outfile, level)
|
|
outfile.write(')\\n')
|
|
|
|
|
|
#
|
|
# Data representation classes.
|
|
#
|
|
|
|
"""
|
|
|
|
# Fool (and straighten out) the syntax highlighting.
|
|
# DUMMY = '''
|
|
|
|
|
|
def generateHeader(outfile, prefix):
|
|
s1 = TEMPLATE_HEADER % time.ctime()
|
|
outfile.write(s1)
|
|
|
|
|
|
TEMPLATE_MAIN = """\
|
|
USAGE_TEXT = \"\"\"
|
|
Usage: python <%(prefix)sParser>.py [ -s ] <in_xml_file>
|
|
Options:
|
|
-s Use the SAX parser, not the minidom parser.
|
|
\"\"\"
|
|
|
|
def usage():
|
|
print(USAGE_TEXT)
|
|
sys.exit(-1)
|
|
|
|
|
|
#
|
|
# SAX handler used to determine the top level element.
|
|
#
|
|
class SaxSelectorHandler(handler.ContentHandler):
|
|
def __init__(self):
|
|
self.topElementName = None
|
|
def getTopElementName(self):
|
|
return self.topElementName
|
|
def startElement(self, name, attrs):
|
|
self.topElementName = name
|
|
raise StopIteration
|
|
|
|
|
|
def parseSelect(inFileName):
|
|
infile = open(inFileName, 'r')
|
|
topElementName = None
|
|
parser = make_parser()
|
|
documentHandler = SaxSelectorHandler()
|
|
parser.setContentHandler(documentHandler)
|
|
try:
|
|
try:
|
|
parser.parse(infile)
|
|
except StopIteration:
|
|
topElementName = documentHandler.getTopElementName()
|
|
if topElementName is None:
|
|
raise RuntimeError('no top level element')
|
|
topElementName = topElementName.replace('-', '_').replace(':', '_')
|
|
if topElementName not in globals():
|
|
raise RuntimeError('no class for top element: %%s' %% topElementName)
|
|
topElement = globals()[topElementName]
|
|
infile.seek(0)
|
|
doc = minidom.parse(infile)
|
|
finally:
|
|
infile.close()
|
|
rootNode = doc.childNodes[0]
|
|
rootObj = topElement.factory()
|
|
rootObj.build(rootNode)
|
|
# Enable Python to collect the space used by the DOM.
|
|
doc = None
|
|
sys.stdout.write('<?xml version="1.0" ?>\\n')
|
|
rootObj.export(sys.stdout, 0)
|
|
return rootObj
|
|
|
|
|
|
def saxParse(inFileName):
|
|
parser = make_parser()
|
|
documentHandler = Sax%(cap_name)sHandler()
|
|
parser.setDocumentHandler(documentHandler)
|
|
parser.parse('file:%%s' %% inFileName)
|
|
root = documentHandler.getRoot()
|
|
sys.stdout.write('<?xml version="1.0" ?>\\n')
|
|
root.export(sys.stdout, 0)
|
|
return root
|
|
|
|
|
|
def saxParseString(inString):
|
|
parser = make_parser()
|
|
documentHandler = Sax%(cap_name)sHandler()
|
|
parser.setDocumentHandler(documentHandler)
|
|
parser.feed(inString)
|
|
parser.close()
|
|
rootObj = documentHandler.getRoot()
|
|
#sys.stdout.write('<?xml version="1.0" ?>\\n')
|
|
#rootObj.export(sys.stdout, 0)
|
|
return rootObj
|
|
|
|
|
|
def parse(inFileName):
|
|
doc = minidom.parse(inFileName)
|
|
rootNode = doc.documentElement
|
|
rootObj = %(prefix)s%(root)s.factory()
|
|
rootObj.build(rootNode)
|
|
# Enable Python to collect the space used by the DOM.
|
|
doc = None
|
|
sys.stdout.write('<?xml version="1.0" ?>\\n')
|
|
rootObj.export(sys.stdout, 0, name_="%(name)s")
|
|
return rootObj
|
|
|
|
|
|
def parseString(inString):
|
|
doc = minidom.parseString(inString)
|
|
rootNode = doc.documentElement
|
|
rootObj = %(prefix)s%(root)s.factory()
|
|
rootObj.build(rootNode)
|
|
# Enable Python to collect the space used by the DOM.
|
|
doc = None
|
|
sys.stdout.write('<?xml version="1.0" ?>\\n')
|
|
rootObj.export(sys.stdout, 0, name_="%(name)s")
|
|
return rootObj
|
|
|
|
|
|
def parseLiteral(inFileName):
|
|
doc = minidom.parse(inFileName)
|
|
rootNode = doc.documentElement
|
|
rootObj = %(prefix)s%(root)s.factory()
|
|
rootObj.build(rootNode)
|
|
# Enable Python to collect the space used by the DOM.
|
|
doc = None
|
|
sys.stdout.write('from %(module_name)s import *\\n\\n')
|
|
sys.stdout.write('rootObj = %(name)s(\\n')
|
|
rootObj.exportLiteral(sys.stdout, 0, name_="%(name)s")
|
|
sys.stdout.write(')\\n')
|
|
return rootObj
|
|
|
|
|
|
def main():
|
|
args = sys.argv[1:]
|
|
if len(args) == 2 and args[0] == '-s':
|
|
saxParse(args[1])
|
|
elif len(args) == 1:
|
|
parse(args[0])
|
|
else:
|
|
usage()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
#import pdb
|
|
#pdb.run('main()')
|
|
|
|
"""
|
|
|
|
|
|
# Fool (and straighten out) the syntax highlighting.
|
|
# DUMMY = '''
|
|
|
|
|
|
def generateMain(outfile, prefix, root):
|
|
name = root.getChildren()[0].getName()
|
|
elType = cleanupName(root.getChildren()[0].getType())
|
|
if RootElement:
|
|
rootElement = RootElement
|
|
else:
|
|
rootElement = elType
|
|
params = {
|
|
"prefix": prefix,
|
|
"cap_name": cleanupName(name.capitalize()),
|
|
"name": cleanupName(name),
|
|
"module_name": os.path.splitext(os.path.basename(outfile.name))[0],
|
|
"root": rootElement,
|
|
}
|
|
s1 = TEMPLATE_MAIN % params
|
|
outfile.write(s1)
|
|
|
|
|
|
def buildCtorParams(element):
|
|
content = []
|
|
add = content.append
|
|
if element.isMixed():
|
|
add(", mixedclass_")
|
|
add(", content_")
|
|
else:
|
|
buildCtorParams_aux(add, element)
|
|
s1 = "".join(content)
|
|
return s1
|
|
|
|
|
|
def buildCtorParams_aux(add, element):
|
|
attrDefs = element.getAttributeDefs()
|
|
for key in attrDefs:
|
|
attrDef = attrDefs[key]
|
|
name = attrDef.getName()
|
|
cleanName = cleanupName(mapName(name))
|
|
add(", %s" % cleanName)
|
|
for child in element.getChildren():
|
|
add(", %s" % child.getCleanName())
|
|
base = element.getBase()
|
|
if base and base in ElementDict:
|
|
parent = ElementDict[base]
|
|
buildCtorParams_aux(add, parent)
|
|
|
|
|
|
def get_class_behavior_args(classBehavior):
|
|
argList = []
|
|
args = classBehavior.getArgs()
|
|
args = args.getArg()
|
|
# print '(get_class_behavior_args) args:', args
|
|
for arg in args:
|
|
argList.append(arg.getName())
|
|
argString = ", ".join(argList)
|
|
return argString
|
|
|
|
|
|
#
|
|
# Retrieve the implementation body via an HTTP request to a
|
|
# URL formed from the concatenation of the baseImplUrl and the
|
|
# implUrl.
|
|
# An alternative implementation of get_impl_body() that also
|
|
# looks in the local file system is commented out below.
|
|
#
|
|
def get_impl_body(classBehavior, baseImplUrl, implUrl):
|
|
impl = " pass\n"
|
|
if implUrl:
|
|
if baseImplUrl:
|
|
implUrl = "%s%s" % (baseImplUrl, implUrl)
|
|
try:
|
|
implFile = urlopen(implUrl)
|
|
impl = implFile.read()
|
|
implFile.close()
|
|
except HTTPError:
|
|
print("*** Implementation at %s not found." % implUrl)
|
|
return impl
|
|
|
|
|
|
###
|
|
### This alternative implementation of get_impl_body() tries the URL
|
|
### via http first, then, if that fails, looks in a directory on
|
|
### the local file system (baseImplUrl) for a file (implUrl)
|
|
### containing the implementation body.
|
|
###
|
|
##def get_impl_body(classBehavior, baseImplUrl, implUrl):
|
|
## impl = ' pass\n'
|
|
## if implUrl:
|
|
## trylocal = 0
|
|
## if baseImplUrl:
|
|
## implUrl = '%s%s' % (baseImplUrl, implUrl)
|
|
## try:
|
|
## implFile = urlopen(implUrl)
|
|
## impl = implFile.read()
|
|
## implFile.close()
|
|
## except:
|
|
## trylocal = 1
|
|
## if trylocal:
|
|
## try:
|
|
## implFile = open(implUrl)
|
|
## impl = implFile.read()
|
|
## implFile.close()
|
|
## except:
|
|
## print ('*** Implementation at %s not found.' % implUrl)
|
|
## return impl
|
|
|
|
|
|
def generateClassBehaviors(wrt, classBehaviors, baseImplUrl):
|
|
for classBehavior in classBehaviors:
|
|
behaviorName = classBehavior.getName()
|
|
#
|
|
# Generate the core behavior.
|
|
argString = get_class_behavior_args(classBehavior)
|
|
if argString:
|
|
wrt(" def %s(self, %s, *args):\n" % (behaviorName, argString))
|
|
else:
|
|
wrt(" def %s(self, *args):\n" % (behaviorName,))
|
|
implUrl = classBehavior.getImpl_url()
|
|
impl = get_impl_body(classBehavior, baseImplUrl, implUrl)
|
|
wrt(impl)
|
|
wrt("\n")
|
|
#
|
|
# Generate the ancillaries for this behavior.
|
|
ancillaries = classBehavior.getAncillaries()
|
|
if ancillaries:
|
|
ancillaries = ancillaries.getAncillary()
|
|
if ancillaries:
|
|
for ancillary in ancillaries:
|
|
argString = get_class_behavior_args(ancillary)
|
|
if argString:
|
|
wrt(" def %s(self, %s, *args):\n" % (ancillary.getName(), argString))
|
|
else:
|
|
wrt(" def %s(self, *args):\n" % (ancillary.getName(),))
|
|
implUrl = ancillary.getImpl_url()
|
|
impl = get_impl_body(classBehavior, baseImplUrl, implUrl)
|
|
wrt(impl)
|
|
wrt("\n")
|
|
#
|
|
# Generate the wrapper method that calls the ancillaries and
|
|
# the core behavior.
|
|
argString = get_class_behavior_args(classBehavior)
|
|
if argString:
|
|
wrt(" def %s_wrapper(self, %s, *args):\n" % (behaviorName, argString))
|
|
else:
|
|
wrt(" def %s_wrapper(self, *args):\n" % (behaviorName,))
|
|
if ancillaries:
|
|
for ancillary in ancillaries:
|
|
role = ancillary.getRole()
|
|
if role == "DBC-precondition":
|
|
wrt(" if not self.%s(*args)\n" % (ancillary.getName(),))
|
|
wrt(" return False\n")
|
|
if argString:
|
|
wrt(" result = self.%s(%s, *args)\n" % (behaviorName, argString))
|
|
else:
|
|
wrt(" result = self.%s(*args)\n" % (behaviorName,))
|
|
if ancillaries:
|
|
for ancillary in ancillaries:
|
|
role = ancillary.getRole()
|
|
if role == "DBC-postcondition":
|
|
wrt(" if not self.%s(*args)\n" % (ancillary.getName(),))
|
|
wrt(" return False\n")
|
|
wrt(" return result\n")
|
|
wrt("\n")
|
|
|
|
|
|
def generateSubclass(outfile, element, prefix, xmlbehavior, behaviors, baseUrl):
|
|
wrt = outfile.write
|
|
if not element.isComplex():
|
|
return
|
|
if (not element.getChildren()) and (not element.getAttributeDefs()):
|
|
return
|
|
if element.getName() in AlreadyGenerated_subclass:
|
|
return
|
|
AlreadyGenerated_subclass.append(element.getName())
|
|
name = element.getCleanName()
|
|
wrt("class %s%s%s(supermod.%s):\n" % (prefix, name, SubclassSuffix, name))
|
|
s1 = buildCtorArgs_multilevel(element)
|
|
wrt(" def __init__(self%s):\n" % s1)
|
|
s1 = buildCtorParams(element)
|
|
wrt(" supermod.%s%s.__init__(self%s)\n" % (prefix, name, s1))
|
|
if xmlbehavior and behaviors:
|
|
wrt("\n")
|
|
wrt(" #\n")
|
|
wrt(" # XMLBehaviors\n")
|
|
wrt(" #\n")
|
|
# Get a list of behaviors for this class/subclass.
|
|
classDictionary = behaviors.get_class_dictionary()
|
|
if name in classDictionary:
|
|
classBehaviors = classDictionary[name]
|
|
else:
|
|
classBehaviors = None
|
|
if classBehaviors:
|
|
generateClassBehaviors(wrt, classBehaviors, baseUrl)
|
|
wrt("supermod.%s.subclass = %s%s\n" % (name, name, SubclassSuffix))
|
|
wrt("# end class %s%s%s\n" % (prefix, name, SubclassSuffix))
|
|
wrt("\n\n")
|
|
|
|
|
|
TEMPLATE_SUBCLASS_HEADER = """\
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
# Generated %s by generateDS.py.
|
|
#
|
|
|
|
import sys
|
|
from xml.dom import minidom
|
|
from xml.sax import handler, make_parser
|
|
|
|
import %s as supermod
|
|
|
|
"""
|
|
|
|
TEMPLATE_SUBCLASS_FOOTER = """\
|
|
|
|
#
|
|
# SAX handler used to determine the top level element.
|
|
#
|
|
class SaxSelectorHandler(handler.ContentHandler):
|
|
def __init__(self):
|
|
self.topElementName = None
|
|
def getTopElementName(self):
|
|
return self.topElementName
|
|
def startElement(self, name, attrs):
|
|
self.topElementName = name
|
|
raise StopIteration
|
|
|
|
|
|
def parseSelect(inFileName):
|
|
infile = open(inFileName, 'r')
|
|
topElementName = None
|
|
parser = make_parser()
|
|
documentHandler = SaxSelectorHandler()
|
|
parser.setContentHandler(documentHandler)
|
|
try:
|
|
try:
|
|
parser.parse(infile)
|
|
except StopIteration:
|
|
topElementName = documentHandler.getTopElementName()
|
|
if topElementName is None:
|
|
raise RuntimeError, 'no top level element'
|
|
topElementName = topElementName.replace('-', '_').replace(':', '_')
|
|
if topElementName not in supermod.__dict__:
|
|
raise RuntimeError, 'no class for top element: %%s' %% topElementName
|
|
topElement = supermod.__dict__[topElementName]
|
|
infile.seek(0)
|
|
doc = minidom.parse(infile)
|
|
finally:
|
|
infile.close()
|
|
rootNode = doc.childNodes[0]
|
|
rootObj = topElement.factory()
|
|
rootObj.build(rootNode)
|
|
# Enable Python to collect the space used by the DOM.
|
|
doc = None
|
|
sys.stdout.write('<?xml version="1.0" ?>\\n')
|
|
rootObj.export(sys.stdout, 0)
|
|
return rootObj
|
|
|
|
|
|
def saxParse(inFileName):
|
|
parser = make_parser()
|
|
documentHandler = supermod.Sax%(cap_name)sHandler()
|
|
parser.setDocumentHandler(documentHandler)
|
|
parser.parse('file:%%s' %% inFileName)
|
|
rootObj = documentHandler.getRoot()
|
|
#sys.stdout.write('<?xml version="1.0" ?>\\n')
|
|
#rootObj.export(sys.stdout, 0)
|
|
return rootObj
|
|
|
|
|
|
def saxParseString(inString):
|
|
parser = make_parser()
|
|
documentHandler = supermod.SaxContentHandler()
|
|
parser.setDocumentHandler(documentHandler)
|
|
parser.feed(inString)
|
|
parser.close()
|
|
rootObj = documentHandler.getRoot()
|
|
#sys.stdout.write('<?xml version="1.0" ?>\\n')
|
|
#rootObj.export(sys.stdout, 0)
|
|
return rootObj
|
|
|
|
|
|
def parse(inFilename):
|
|
doc = minidom.parse(inFilename)
|
|
rootNode = doc.documentElement
|
|
rootObj = supermod.%(root)s.factory()
|
|
rootObj.build(rootNode)
|
|
# Enable Python to collect the space used by the DOM.
|
|
doc = None
|
|
sys.stdout.write('<?xml version="1.0" ?>\\n')
|
|
rootObj.export(sys.stdout, 0, name_="%(name)s")
|
|
doc = None
|
|
return rootObj
|
|
|
|
|
|
def parseString(inString):
|
|
doc = minidom.parseString(inString)
|
|
rootNode = doc.documentElement
|
|
rootObj = supermod.%(root)s.factory()
|
|
rootObj.build(rootNode)
|
|
# Enable Python to collect the space used by the DOM.
|
|
doc = None
|
|
sys.stdout.write('<?xml version="1.0" ?>\\n')
|
|
rootObj.export(sys.stdout, 0, name_="%(name)s")
|
|
return rootObj
|
|
|
|
|
|
def parseLiteral(inFilename):
|
|
doc = minidom.parse(inFilename)
|
|
rootNode = doc.documentElement
|
|
rootObj = supermod.%(root)s.factory()
|
|
rootObj.build(rootNode)
|
|
# Enable Python to collect the space used by the DOM.
|
|
doc = None
|
|
sys.stdout.write('from %(super)s import *\\n\\n')
|
|
sys.stdout.write('rootObj = %(name)s(\\n')
|
|
rootObj.exportLiteral(sys.stdout, 0, name_="%(name)s")
|
|
sys.stdout.write(')\\n')
|
|
return rootObj
|
|
|
|
|
|
USAGE_TEXT = \"\"\"
|
|
Usage: python ???.py <infilename>
|
|
\"\"\"
|
|
|
|
def usage():
|
|
print(USAGE_TEXT)
|
|
sys.exit(-1)
|
|
|
|
|
|
def main():
|
|
args = sys.argv[1:]
|
|
if len(args) != 1:
|
|
usage()
|
|
infilename = args[0]
|
|
root = parse(infilename)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
#import pdb
|
|
#pdb.run('main()')
|
|
|
|
|
|
"""
|
|
|
|
##def isMember(item, lst):
|
|
## for item1 in lst:
|
|
## if item == item1:
|
|
## print '(isMember) found name: %s' % item
|
|
## return True
|
|
## print '(isMember) did not find name: %s' % item
|
|
## return False
|
|
|
|
|
|
def generateSubclasses(root, subclassFilename, behaviorFilename, prefix, superModule="xxx"):
|
|
name = root.getChildren()[0].getName()
|
|
subclassFile = makeFile(subclassFilename)
|
|
if subclassFile:
|
|
# Read in the XMLBehavior file.
|
|
xmlbehavior = None
|
|
behaviors = None
|
|
baseUrl = None
|
|
if behaviorFilename:
|
|
try:
|
|
# Add the correct working directory to the path so that
|
|
# we use the user/developers local copy.
|
|
sys.path.insert(0, ".")
|
|
import xmlbehavior_sub as xmlbehavior
|
|
except ImportError:
|
|
print("*** You have requested generation of extended methods.")
|
|
print("*** But, no xmlbehavior module is available.")
|
|
print("*** Generation of extended behavior methods is omitted.")
|
|
if xmlbehavior:
|
|
behaviors = xmlbehavior.parse(behaviorFilename)
|
|
behaviors.make_class_dictionary(cleanupName)
|
|
baseUrl = behaviors.getBase_impl_url()
|
|
wrt = subclassFile.write
|
|
wrt(TEMPLATE_SUBCLASS_HEADER % (time.ctime(), superModule))
|
|
for element in ElementsForSubclasses:
|
|
generateSubclass(subclassFile, element, prefix, xmlbehavior, behaviors, baseUrl)
|
|
## processed = []
|
|
## for element in root.getChildren():
|
|
## name = element.getCleanName()
|
|
## if name not in processed:
|
|
## processed.append(name)
|
|
## generateSubclass(subclassFile, element, prefix, xmlbehavior, behaviors, baseUrl)
|
|
## while 1:
|
|
## if len(DelayedElements_subclass) <= 0:
|
|
## break
|
|
## element = DelayedElements_subclass.pop()
|
|
## name = element.getCleanName()
|
|
## if name not in processed:
|
|
## processed.append(name)
|
|
## generateSubclass(subclassFile, element, prefix, xmlbehavior, behaviors, baseUrl)
|
|
name = root.getChildren()[0].getName()
|
|
elType = cleanupName(root.getChildren()[0].getType())
|
|
if RootElement:
|
|
rootElement = RootElement
|
|
else:
|
|
rootElement = elType
|
|
params = {
|
|
"cap_name": cleanupName(name).capitalize(),
|
|
"name": cleanupName(name),
|
|
"module_name": os.path.splitext(os.path.basename(subclassFilename))[0],
|
|
"root": rootElement,
|
|
"super": superModule,
|
|
}
|
|
wrt(TEMPLATE_SUBCLASS_FOOTER % params)
|
|
subclassFile.close()
|
|
|
|
|
|
def generateFromTree(outfile, prefix, elements, processed):
|
|
for element in elements:
|
|
name = element.getCleanName()
|
|
if 1: # if name not in processed:
|
|
processed.append(name)
|
|
generateClasses(outfile, prefix, element, 0)
|
|
children = element.getChildren()
|
|
if children:
|
|
generateFromTree(outfile, prefix, element.getChildren(), processed)
|
|
|
|
|
|
def generate(outfileName, subclassFilename, behaviorFilename, prefix, root, superModule):
|
|
global DelayedElements, DelayedElements_subclass
|
|
# Create an output file.
|
|
# Note that even if the user does not request an output file,
|
|
# we still need to go through the process of generating classes
|
|
# because it produces data structures needed during generation of
|
|
# subclasses.
|
|
outfile = None
|
|
if outfileName:
|
|
outfile = makeFile(outfileName)
|
|
if not outfile:
|
|
outfile = os.tmpfile()
|
|
processed = []
|
|
generateHeader(outfile, prefix)
|
|
DelayedElements = []
|
|
DelayedElements_subclass = []
|
|
elements = root.getChildren()
|
|
generateFromTree(outfile, prefix, elements, processed)
|
|
while 1:
|
|
if len(DelayedElements) <= 0:
|
|
break
|
|
element = DelayedElements.pop()
|
|
name = element.getCleanName()
|
|
if name not in processed:
|
|
processed.append(name)
|
|
generateClasses(outfile, prefix, element, 1)
|
|
#
|
|
# Generate the elements that were postponed because we had not
|
|
# yet generated their base class.
|
|
idx = 0
|
|
while 1:
|
|
if len(PostponedExtensions) <= 0:
|
|
break
|
|
element = PostponedExtensions.pop()
|
|
base = element.getBase()
|
|
if base and base in ElementDict:
|
|
parent = ElementDict[base]
|
|
parentName = parent.getName()
|
|
if parentName not in AlreadyGenerated:
|
|
PostponedExtensions.insert(0, element)
|
|
else:
|
|
idx += 1
|
|
generateClasses(outfile, prefix, element, 1)
|
|
#
|
|
# Disable the generation of SAX handler/parser.
|
|
# It failed when we stopped putting simple types into ElementDict.
|
|
# When there are duplicate names, the SAX parser probably does
|
|
# not work anyway.
|
|
generateSAXHndlr(outfile, root)
|
|
generateMain(outfile, prefix, root)
|
|
outfile.close()
|
|
if subclassFilename:
|
|
generateSubclasses(root, subclassFilename, behaviorFilename, prefix, superModule)
|
|
|
|
|
|
def makeFile(outFileName):
|
|
global Force
|
|
outFile = None
|
|
if (not Force) and os.path.exists(outFileName):
|
|
reply = input("File %s exists. Overwrite? (y/n): " % outFileName)
|
|
if reply == "y":
|
|
outFile = open(outFileName, "w")
|
|
else:
|
|
outFile = open(outFileName, "w")
|
|
return outFile
|
|
|
|
|
|
def mapName(oldName):
|
|
global NameTable
|
|
newName = oldName
|
|
if NameTable:
|
|
if oldName in NameTable:
|
|
newName = NameTable[oldName]
|
|
return newName
|
|
|
|
|
|
def cleanupName(oldName):
|
|
newName = oldName.replace(":", "_")
|
|
newName = newName.replace("-", "_")
|
|
return newName
|
|
|
|
|
|
## def mapName(oldName):
|
|
## return '_X_%s' % oldName
|
|
|
|
|
|
def strip_namespace(val):
|
|
return val.split(":")[-1]
|
|
|
|
|
|
def parseAndGenerate(
|
|
outfileName,
|
|
subclassFilename,
|
|
prefix,
|
|
xschemaFileName,
|
|
behaviorFilename,
|
|
superModule="???",
|
|
):
|
|
global DelayedElements, DelayedElements_subclass, AlreadyGenerated, SaxDelayedElements, AlreadyGenerated_subclass
|
|
DelayedElements = []
|
|
DelayedElements_subclass = []
|
|
AlreadyGenerated = []
|
|
AlreadyGenerated_subclass = []
|
|
## parser = saxexts.make_parser("xml.sax.drivers2.drv_pyexpat")
|
|
parser = make_parser()
|
|
## print 'dir(parser):', dir(parser)
|
|
## print "Parser: %s" % parser
|
|
dh = XschemaHandler()
|
|
## parser.setDocumentHandler(dh)
|
|
parser.setContentHandler(dh)
|
|
parser.parse(xschemaFileName)
|
|
root = dh.getRoot()
|
|
root.annotate()
|
|
## print 'ElementDict:', ElementDict
|
|
## for name, obj in ElementDict.items():
|
|
## print ' ', name, obj.getName(), obj.type
|
|
## print '=' * 50
|
|
## root.show(sys.stdout, 0)
|
|
## print '=' * 50
|
|
## response = input('Press Enter')
|
|
## root.show(sys.stdout, 0)
|
|
## print '=' * 50
|
|
## print ']]] root: ', root, '[[['
|
|
generate(outfileName, subclassFilename, behaviorFilename, prefix, root, superModule)
|
|
|
|
|
|
USAGE_TEXT = """
|
|
Usage: python generateDS.py [ options ] <in_xsd_file>
|
|
Options:
|
|
-o <outfilename> Output file name for data representation classes
|
|
-s <subclassfilename> Output file name for subclasses
|
|
-p <prefix> Prefix string to be prepended to the class names
|
|
-n <mappingfilename> Transform names with table in mappingfilename.
|
|
-f Force creation of output files. Do not ask.
|
|
-a <namespaceabbrev> Namespace abbreviation, e.g. "xsd:". Default = 'xs:'.
|
|
-b <behaviorfilename> Input file name for behaviors added to subclasses
|
|
-m Generate properties for member variables
|
|
--subclass-suffix="XXX" Append XXX to the generated subclass names. Default="Sub".
|
|
--root-element="XXX" Assume XXX is root element of instance docs.
|
|
Default is first element defined in schema.
|
|
--super="XXX" Super module name in subclass module. Default="???"
|
|
|
|
Example:
|
|
python generateDS.py -o generateModel_Module.py generateMetaModel_Module.xsd
|
|
"""
|
|
|
|
|
|
def usage():
|
|
print(USAGE_TEXT)
|
|
sys.exit(-1)
|
|
|
|
|
|
def main():
|
|
global Force, GenerateProperties, SubclassSuffix, RootElement
|
|
args = sys.argv[1:]
|
|
options, args = getopt.getopt(
|
|
args,
|
|
"fyo:s:p:a:b:m",
|
|
[
|
|
"subclass-suffix=",
|
|
"root-element=",
|
|
"super=",
|
|
],
|
|
)
|
|
prefix = ""
|
|
outFilename = None
|
|
subclassFilename = None
|
|
behaviorFilename = None
|
|
nameSpace = "xs:"
|
|
debug = 0
|
|
superModule = "???"
|
|
for option in options:
|
|
if option[0] == "-p":
|
|
prefix = option[1]
|
|
elif option[0] == "-o":
|
|
outFilename = option[1]
|
|
elif option[0] == "-s":
|
|
subclassFilename = option[1]
|
|
elif option[0] == "-f":
|
|
Force = 1
|
|
elif option[0] == "-a":
|
|
nameSpace = option[1]
|
|
elif option[0] == "-b":
|
|
behaviorFilename = option[1]
|
|
elif option[0] == "-m":
|
|
GenerateProperties = 1
|
|
elif option[0] == "--subclass-suffix":
|
|
SubclassSuffix = option[1]
|
|
elif option[0] == "--root-element":
|
|
RootElement = option[1]
|
|
elif option[0] == "--super":
|
|
superModule = option[1]
|
|
set_type_constants(nameSpace)
|
|
if behaviorFilename and not subclassFilename:
|
|
print("\n*** Error. -b requires -s")
|
|
usage()
|
|
if len(args) != 1:
|
|
usage()
|
|
xschemaFileName = args[0]
|
|
if debug:
|
|
pass
|
|
else:
|
|
parseAndGenerate(
|
|
outFilename,
|
|
subclassFilename,
|
|
prefix,
|
|
xschemaFileName,
|
|
behaviorFilename,
|
|
superModule=superModule,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
## import pdb
|
|
## pdb.run('main()')
|