diff --git a/README b/README index 0586722811a0d27535e6be9b88a847ce07c4ab4c..8a5a8de83ddee93f3e3344a7ecd175ba2e068219 100644 --- a/README +++ b/README @@ -141,6 +141,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Change history -------------- +Version 2.11b (08/19/2013) +- A name conflict issue caused by naming anonymous types. An + anonymous type is a complexType that does not have a name + attribute and that is nested inside an element that does not have + a type attribute. Strengthened the code that generates new, + unique names. And, also fixed a problem or two in the surrounding + code. Thanks to Shahaf Abileah for reporting this and for + providing test files to reproduce the problem behavior. +- Created unit test for anonymous types. + Version 2.11a (08/16/2013) - Added ability to use XML catalog to find included/imported schemas. The -c command line option has been added to support diff --git a/generateDS.py b/generateDS.py index e4a4434237c01c4999d91383e53064349c7bd2c2..bfd59cd6e4dad8690dbb3fa1da9d6973ffc5010a 100755 --- a/generateDS.py +++ b/generateDS.py @@ -170,7 +170,7 @@ logging.disable(logging.INFO) # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.11a' +VERSION = '2.11b' ##VERSION## GenerateProperties = 0 @@ -4104,7 +4104,7 @@ def generateClasses(wrt, prefix, element, delayed): # not been generated, then postpone it. if parentName: if (parentName not in AlreadyGenerated and - parentName not in SimpleTypeDict.keys()): + parentName not in SimpleTypeDict): PostponedExtensions.append(element) return if element.getName() in AlreadyGenerated: @@ -5541,7 +5541,7 @@ def generate(outfileName, subclassFilename, behaviorFilename, parentName, parent = getParentName(element) if parentName: if (parentName in AlreadyGenerated or - parentName in SimpleTypeDict.keys()): + parentName in SimpleTypeDict): generateClasses(wrt, prefix, element, 1) else: PostponedExtensions.insert(0, element) diff --git a/generateDS.txt b/generateDS.txt index 70caed21583ffcc4fcbebd6bb270488a4b14ffb1..42d1ce0a7a85acfb1a496e3a8719bfbb1aa96417 100644 --- a/generateDS.txt +++ b/generateDS.txt @@ -11,7 +11,7 @@ generateDS -- Generate Data Structures from XML Schema .. version -:revision: 2.11a +:revision: 2.11b .. version diff --git a/gui/generateds_gui.py b/gui/generateds_gui.py index 069ed844cef59e5f3a8e78e9f5f134b4616be90a..272b6e72303e0abf1f5777c198a37e96a1c083f1 100755 --- a/gui/generateds_gui.py +++ b/gui/generateds_gui.py @@ -31,7 +31,7 @@ from libgenerateDS.gui import generateds_gui_session # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.11a' +VERSION = '2.11b' ##VERSION## diff --git a/libgenerateDS/gui/generateds_gui.py b/libgenerateDS/gui/generateds_gui.py index 069ed844cef59e5f3a8e78e9f5f134b4616be90a..272b6e72303e0abf1f5777c198a37e96a1c083f1 100755 --- a/libgenerateDS/gui/generateds_gui.py +++ b/libgenerateDS/gui/generateds_gui.py @@ -31,7 +31,7 @@ from libgenerateDS.gui import generateds_gui_session # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.11a' +VERSION = '2.11b' ##VERSION## diff --git a/librarytemplate_howto.txt b/librarytemplate_howto.txt index ce569da0ed7ccbdd745cf76848bb958cfda68cd1..9948374dab450dfbc2468774c1975a4a6750641a 100644 --- a/librarytemplate_howto.txt +++ b/librarytemplate_howto.txt @@ -8,7 +8,7 @@ How to package a generateDS.py generated library .. version -:revision: 2.11a +:revision: 2.11b .. version diff --git a/process_includes.py b/process_includes.py index c0f31072957aee9e41eca162a94d4fb82e66c36e..b53243ae4b1bd056e91edfbf3bd496d33b3002e4 100755 --- a/process_includes.py +++ b/process_includes.py @@ -30,7 +30,7 @@ from lxml import etree # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.11a' +VERSION = '2.11b' ##VERSION## Namespaces = {'xs': 'http://www.w3.org/2001/XMLSchema'} @@ -297,19 +297,8 @@ def raise_anon_complextypes(root): """ Raise each anonymous complexType to top level and give it a name. Rename if necessary to prevent duplicates. """ - element_tag = '{%s}element' % (Xsd_namespace_uri, ) - def_names = {} + def_names = collect_type_names(root) def_count = 0 - # Collect top level complexTypes. - defs = root.xpath('./xs:complexType', namespaces=Namespaces) - for node in defs: - type_name = node.get('name') - def_names[type_name] = node - # Collect top level simpleTypes. - defs = root.xpath('./xs:simpleType', namespaces=Namespaces) - for node in defs: - type_name = node.get('name') - def_names[type_name] = node # Find all complexTypes below top level. # Raise them to top level and name them. # Re-name if there is a duplicate (simpleType, complexType, or @@ -320,7 +309,15 @@ def raise_anon_complextypes(root): el = etree.Comment(text="Raised anonymous complexType definitions") el.tail = "\n\n" root.append(el) - defs = root.xpath('./*/*//xs:complexType', namespaces=Namespaces) + prefix = root.prefix + if prefix: + pattern = './*/*//%s:complexType|./*/*//%s:simpleType' % ( + prefix, prefix, ) + element_tag = '{%s}element' % (root.nsmap[prefix], ) + else: + pattern = './*/*//complexType|./*/*//simpleType' + element_tag = 'element' + defs = root.xpath(pattern, namespaces=Namespaces) for node in defs: parent = node.getparent() if parent.tag != element_tag: @@ -330,19 +327,38 @@ def raise_anon_complextypes(root): continue type_name = '%sType' % (name, ) type_name, def_count = unique_name(type_name, def_names, def_count) - def_names[type_name] = node + def_names.add(type_name) parent.set('type', type_name) node.set('name', type_name) # Move the complexType node to top level. root.append(node) +# +# Collect the names of all currently defined types (complexType, +# simpleType, element). +def collect_type_names(node): + prefix = node.prefix + if prefix: + pattern = './/%s:complexType|.//%s:simpleType|.//%s:element' % ( + prefix, prefix, prefix) + else: + pattern = './/complexType|.//simpleType|.//element' + elements = node.xpath(pattern, namespaces=node.nsmap) + names = [ + el.attrib['name'] for el in elements if + 'name' in el.attrib and el.getchildren() + ] + names = set(names) + return names + + def unique_name(type_name, def_names, def_count): orig_type_name = type_name while True: - def_count += 1 if type_name not in def_names: return type_name, def_count + def_count += 1 type_name = '%s%d' % (orig_type_name, def_count, ) diff --git a/setup.py b/setup.py index 73d8a016fb2b9f3592a4591caad85386b7ae778a..19d94e8c563ba8760925b0e5c5f8639751c5a28b 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup(name="generateDS", # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## - version="2.11a", + version="2.11b", ##VERSION## author="Dave Kuhlman", author_email="dkuhlman@rexx.com", diff --git a/tests/anonymous_type.xsd b/tests/anonymous_type.xsd new file mode 100644 index 0000000000000000000000000000000000000000..271664ff92562b1bcb22d7cd32b197bc09b40f0c --- /dev/null +++ b/tests/anonymous_type.xsd @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8" ?> +<xs:schema + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + attributeFormDefault="unqualified" + elementFormDefault="qualified" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + > + <xs:element name="FooList"> + <xs:complexType> + <xs:sequence> + <xs:element name="Foo"> + <xs:complexType> + <xs:all> + <xs:element name="FooType"> + <xs:simpleType> + <xs:restriction base="xs:string"> + </xs:restriction> + </xs:simpleType> + </xs:element> + </xs:all> + </xs:complexType> + </xs:element> + <xs:element name="Bar"> + <xs:complexType> + <xs:all> + <xs:element name="BarType"> + <xs:simpleType> + <xs:restriction base="xs:string"> + </xs:restriction> + </xs:simpleType> + </xs:element> + </xs:all> + </xs:complexType> + </xs:element> + <xs:element name="Baz"> + <xs:complexType> + <xs:all> + <xs:element name="BazType"> + <xs:simpleType> + <xs:restriction base="xs:string"> + </xs:restriction> + </xs:simpleType> + </xs:element> + </xs:all> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> +</xs:schema> diff --git a/tests/anonymous_type1_sub.py b/tests/anonymous_type1_sub.py new file mode 100644 index 0000000000000000000000000000000000000000..f6087774e745f0bb310542ae385230b515fe2e68 --- /dev/null +++ b/tests/anonymous_type1_sub.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python + +# +# Generated by generateDS.py. +# + +import sys + +import anonymous_type2_sup as supermod + +etree_ = None +Verbose_import_ = False +( + XMLParser_import_none, XMLParser_import_lxml, + XMLParser_import_elementtree +) = range(3) +XMLParser_import_library = None +try: + # lxml + from lxml import etree as etree_ + XMLParser_import_library = XMLParser_import_lxml + if Verbose_import_: + print("running with lxml.etree") +except ImportError: + try: + # cElementTree from Python 2.5+ + import xml.etree.cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree on Python 2.5+") + except ImportError: + try: + # ElementTree from Python 2.5+ + import xml.etree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree on Python 2.5+") + except ImportError: + try: + # normal cElementTree install + import cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree") + except ImportError: + try: + # normal ElementTree install + import elementtree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree") + except ImportError: + raise ImportError( + "Failed to import ElementTree from any known place") + + +def parsexml_(*args, **kwargs): + if (XMLParser_import_library == XMLParser_import_lxml and + 'parser' not in kwargs): + # Use the lxml ElementTree compatible parser so that, e.g., + # we ignore comments. + kwargs['parser'] = etree_.ETCompatXMLParser() + doc = etree_.parse(*args, **kwargs) + return doc + +# +# Globals +# + +ExternalEncoding = 'ascii' + +# +# Data representation classes +# + + +class FooListSub(supermod.FooList): + def __init__(self, Foo=None, Bar=None, Baz=None): + super(FooListSub, self).__init__(Foo, Bar, Baz, ) +supermod.FooList.subclass = FooListSub +# end class FooListSub + + +class FooType1Sub(supermod.FooType1): + def __init__(self, FooType=None): + super(FooType1Sub, self).__init__(FooType, ) +supermod.FooType1.subclass = FooType1Sub +# end class FooType1Sub + + +class BarType2Sub(supermod.BarType2): + def __init__(self, BarType=None): + super(BarType2Sub, self).__init__(BarType, ) +supermod.BarType2.subclass = BarType2Sub +# end class BarType2Sub + + +class BazType3Sub(supermod.BazType3): + def __init__(self, BazType=None): + super(BazType3Sub, self).__init__(BazType, ) +supermod.BazType3.subclass = BazType3Sub +# end class BazType3Sub + + +def get_root_tag(node): + tag = supermod.Tag_pattern_.match(node.tag).groups()[-1] + rootClass = None + rootClass = supermod.GDSClassesMapping.get(tag) + if rootClass is None and hasattr(supermod, tag): + rootClass = getattr(supermod, tag) + return tag, rootClass + + +def parse(inFilename, silence=False): + doc = parsexml_(inFilename) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'FooList' + rootClass = supermod.FooList + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None +## if not silence: +## sys.stdout.write('<?xml version="1.0" ?>\n') +## rootObj.export( +## sys.stdout, 0, name_=rootTag, +## namespacedef_='', +## pretty_print=True) + return rootObj + + +def parseEtree(inFilename, silence=False): + doc = parsexml_(inFilename) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'FooList' + rootClass = supermod.FooList + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + mapping = {} + rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping) + reverse_mapping = rootObj.gds_reverse_node_mapping(mapping) +## if not silence: +## content = etree_.tostring( +## rootElement, pretty_print=True, +## xml_declaration=True, encoding="utf-8") +## sys.stdout.write(content) +## sys.stdout.write('\n') + return rootObj, rootElement, mapping, reverse_mapping + + +def parseString(inString, silence=False): + from StringIO import StringIO + doc = parsexml_(StringIO(inString)) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'FooList' + rootClass = supermod.FooList + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None +## if not silence: +## sys.stdout.write('<?xml version="1.0" ?>\n') +## rootObj.export( +## sys.stdout, 0, name_=rootTag, +## namespacedef_='') + return rootObj + + +def parseLiteral(inFilename, silence=False): + doc = parsexml_(inFilename) + rootNode = doc.getroot() + roots = get_root_tag(rootNode) + rootClass = roots[1] + if rootClass is None: + rootClass = supermod.FooList + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None +## if not silence: +## sys.stdout.write('#from anonymous_type2_sup import *\n\n') +## sys.stdout.write('import anonymous_type2_sup as model_\n\n') +## sys.stdout.write('rootObj = model_.FooList(\n') +## rootObj.exportLiteral(sys.stdout, 0, name_="FooList") +## 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] + parse(infilename) + + +if __name__ == '__main__': + #import pdb; pdb.set_trace() + main() diff --git a/tests/anonymous_type1_sup.py b/tests/anonymous_type1_sup.py new file mode 100644 index 0000000000000000000000000000000000000000..692916a36b8dc81aa21afbe29c60d3e2126ee38a --- /dev/null +++ b/tests/anonymous_type1_sup.py @@ -0,0 +1,1093 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# Generated by generateDS.py. +# + +import sys +import getopt +import re as re_ +import base64 +import datetime as datetime_ + +etree_ = None +Verbose_import_ = False +( + XMLParser_import_none, XMLParser_import_lxml, + XMLParser_import_elementtree +) = range(3) +XMLParser_import_library = None +try: + # lxml + from lxml import etree as etree_ + XMLParser_import_library = XMLParser_import_lxml + if Verbose_import_: + print("running with lxml.etree") +except ImportError: + try: + # cElementTree from Python 2.5+ + import xml.etree.cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree on Python 2.5+") + except ImportError: + try: + # ElementTree from Python 2.5+ + import xml.etree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree on Python 2.5+") + except ImportError: + try: + # normal cElementTree install + import cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree") + except ImportError: + try: + # normal ElementTree install + import elementtree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree") + except ImportError: + raise ImportError( + "Failed to import ElementTree from any known place") + + +def parsexml_(*args, **kwargs): + if (XMLParser_import_library == XMLParser_import_lxml and + 'parser' not in kwargs): + # Use the lxml ElementTree compatible parser so that, e.g., + # we ignore comments. + kwargs['parser'] = etree_.ETCompatXMLParser() + doc = etree_.parse(*args, **kwargs) + return doc + +# +# User methods +# +# Calls to the methods in these classes are generated by generateDS.py. +# You can replace these methods by re-implementing the following class +# in a module named generatedssuper.py. + +try: + from generatedssuper import GeneratedsSuper +except ImportError, exp: + + class GeneratedsSuper(object): + tzoff_pattern = re_.compile(r'(\+|-)((0\d|1[0-3]):[0-5]\d|14:00)$') + class _FixedOffsetTZ(datetime_.tzinfo): + def __init__(self, offset, name): + self.__offset = datetime_.timedelta(minutes=offset) + self.__name = name + def utcoffset(self, dt): + return self.__offset + def tzname(self, dt): + return self.__name + def dst(self, dt): + return None + def gds_format_string(self, input_data, input_name=''): + return input_data + def gds_validate_string(self, input_data, node, input_name=''): + return input_data + def gds_format_base64(self, input_data, input_name=''): + return base64.b64encode(input_data) + def gds_validate_base64(self, input_data, node, input_name=''): + return input_data + def gds_format_integer(self, input_data, input_name=''): + return '%d' % input_data + def gds_validate_integer(self, input_data, node, input_name=''): + return input_data + def gds_format_integer_list(self, input_data, input_name=''): + return '%s' % input_data + def gds_validate_integer_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + try: + float(value) + except (TypeError, ValueError): + raise_parse_error(node, 'Requires sequence of integers') + return input_data + def gds_format_float(self, input_data, input_name=''): + return ('%.15f' % input_data).rstrip('0') + def gds_validate_float(self, input_data, node, input_name=''): + return input_data + def gds_format_float_list(self, input_data, input_name=''): + return '%s' % input_data + def gds_validate_float_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + try: + float(value) + except (TypeError, ValueError): + raise_parse_error(node, 'Requires sequence of floats') + return input_data + def gds_format_double(self, input_data, input_name=''): + return '%e' % input_data + def gds_validate_double(self, input_data, node, input_name=''): + return input_data + def gds_format_double_list(self, input_data, input_name=''): + return '%s' % input_data + def gds_validate_double_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + try: + float(value) + except (TypeError, ValueError): + raise_parse_error(node, 'Requires sequence of doubles') + return input_data + def gds_format_boolean(self, input_data, input_name=''): + return ('%s' % input_data).lower() + def gds_validate_boolean(self, input_data, node, input_name=''): + return input_data + def gds_format_boolean_list(self, input_data, input_name=''): + return '%s' % input_data + def gds_validate_boolean_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + if value not in ('true', '1', 'false', '0', ): + raise_parse_error( + node, + 'Requires sequence of booleans ' + '("true", "1", "false", "0")') + return input_data + def gds_validate_datetime(self, input_data, node, input_name=''): + return input_data + def gds_format_datetime(self, input_data, input_name=''): + if input_data.microsecond == 0: + _svalue = '%04d-%02d-%02dT%02d:%02d:%02d' % ( + input_data.year, + input_data.month, + input_data.day, + input_data.hour, + input_data.minute, + input_data.second, + ) + else: + _svalue = '%04d-%02d-%02dT%02d:%02d:%02d.%s' % ( + input_data.year, + input_data.month, + input_data.day, + input_data.hour, + input_data.minute, + input_data.second, + ('%f' % (float(input_data.microsecond) / 1000000))[2:], + ) + if input_data.tzinfo is not None: + tzoff = input_data.tzinfo.utcoffset(input_data) + if tzoff is not None: + total_seconds = tzoff.seconds + (86400 * tzoff.days) + if total_seconds == 0: + _svalue += 'Z' + else: + if total_seconds < 0: + _svalue += '-' + total_seconds *= -1 + else: + _svalue += '+' + hours = total_seconds // 3600 + minutes = (total_seconds - (hours * 3600)) // 60 + _svalue += '{0:02d}:{1:02d}'.format(hours, minutes) + return _svalue + @classmethod + def gds_parse_datetime(cls, input_data): + tz = None + if input_data[-1] == 'Z': + tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC') + input_data = input_data[:-1] + else: + results = GeneratedsSuper.tzoff_pattern.search(input_data) + if results is not None: + tzoff_parts = results.group(2).split(':') + tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1]) + if results.group(1) == '-': + tzoff *= -1 + tz = GeneratedsSuper._FixedOffsetTZ( + tzoff, results.group(0)) + input_data = input_data[:-6] + if len(input_data.split('.')) > 1: + dt = datetime_.datetime.strptime( + input_data, '%Y-%m-%dT%H:%M:%S.%f') + else: + dt = datetime_.datetime.strptime( + input_data, '%Y-%m-%dT%H:%M:%S') + dt = dt.replace(tzinfo=tz) + return dt + def gds_validate_date(self, input_data, node, input_name=''): + return input_data + def gds_format_date(self, input_data, input_name=''): + _svalue = '%04d-%02d-%02d' % ( + input_data.year, + input_data.month, + input_data.day, + ) + try: + if input_data.tzinfo is not None: + tzoff = input_data.tzinfo.utcoffset(input_data) + if tzoff is not None: + total_seconds = tzoff.seconds + (86400 * tzoff.days) + if total_seconds == 0: + _svalue += 'Z' + else: + if total_seconds < 0: + _svalue += '-' + total_seconds *= -1 + else: + _svalue += '+' + hours = total_seconds // 3600 + minutes = (total_seconds - (hours * 3600)) // 60 + _svalue += '{0:02d}:{1:02d}'.format(hours, minutes) + except AttributeError: + pass + return _svalue + @classmethod + def gds_parse_date(cls, input_data): + tz = None + if input_data[-1] == 'Z': + tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC') + input_data = input_data[:-1] + else: + results = GeneratedsSuper.tzoff_pattern.search(input_data) + if results is not None: + tzoff_parts = results.group(2).split(':') + tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1]) + if results.group(1) == '-': + tzoff *= -1 + tz = GeneratedsSuper._FixedOffsetTZ( + tzoff, results.group(0)) + input_data = input_data[:-6] + dt = datetime_.datetime.strptime(input_data, '%Y-%m-%d') + dt = dt.replace(tzinfo=tz) + return dt.date() + def gds_validate_time(self, input_data, node, input_name=''): + return input_data + def gds_format_time(self, input_data, input_name=''): + if input_data.microsecond == 0: + _svalue = '%02d:%02d:%02d' % ( + input_data.hour, + input_data.minute, + input_data.second, + ) + else: + _svalue = '%02d:%02d:%02d.%s' % ( + input_data.hour, + input_data.minute, + input_data.second, + ('%f' % (float(input_data.microsecond) / 1000000))[2:], + ) + if input_data.tzinfo is not None: + tzoff = input_data.tzinfo.utcoffset(input_data) + if tzoff is not None: + total_seconds = tzoff.seconds + (86400 * tzoff.days) + if total_seconds == 0: + _svalue += 'Z' + else: + if total_seconds < 0: + _svalue += '-' + total_seconds *= -1 + else: + _svalue += '+' + hours = total_seconds // 3600 + minutes = (total_seconds - (hours * 3600)) // 60 + _svalue += '{0:02d}:{1:02d}'.format(hours, minutes) + return _svalue + @classmethod + def gds_parse_time(cls, input_data): + tz = None + if input_data[-1] == 'Z': + tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC') + input_data = input_data[:-1] + else: + results = GeneratedsSuper.tzoff_pattern.search(input_data) + if results is not None: + tzoff_parts = results.group(2).split(':') + tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1]) + if results.group(1) == '-': + tzoff *= -1 + tz = GeneratedsSuper._FixedOffsetTZ( + tzoff, results.group(0)) + input_data = input_data[:-6] + if len(input_data.split('.')) > 1: + dt = datetime_.datetime.strptime(input_data, '%H:%M:%S.%f') + else: + dt = datetime_.datetime.strptime(input_data, '%H:%M:%S') + dt = dt.replace(tzinfo=tz) + return dt.time() + def gds_str_lower(self, instring): + return instring.lower() + def get_path_(self, node): + path_list = [] + self.get_path_list_(node, path_list) + path_list.reverse() + path = '/'.join(path_list) + return path + Tag_strip_pattern_ = re_.compile(r'\{.*\}') + def get_path_list_(self, node, path_list): + if node is None: + return + tag = GeneratedsSuper.Tag_strip_pattern_.sub('', node.tag) + if tag: + path_list.append(tag) + self.get_path_list_(node.getparent(), path_list) + def get_class_obj_(self, node, default_class=None): + class_obj1 = default_class + if 'xsi' in node.nsmap: + classname = node.get('{%s}type' % node.nsmap['xsi']) + if classname is not None: + names = classname.split(':') + if len(names) == 2: + classname = names[1] + class_obj2 = globals().get(classname) + if class_obj2 is not None: + class_obj1 = class_obj2 + return class_obj1 + def gds_build_any(self, node, type_name=None): + return None + @classmethod + def gds_reverse_node_mapping(cls, mapping): + return dict(((v, k) for k, v in mapping.iteritems())) + + +# +# 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') + +# +# Globals +# + +ExternalEncoding = 'ascii' +Tag_pattern_ = re_.compile(r'({.*})?(.*)') +String_cleanup_pat_ = re_.compile(r"[\n\r\s]+") +Namespace_extract_pat_ = re_.compile(r'{(.*)}(.*)') + +# +# Support/utility functions. +# + + +def showIndent(outfile, level, pretty_print=True): + if pretty_print: + for idx in range(level): + outfile.write(' ') + + +def quote_xml(inStr): + if not inStr: + return '' + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + return s1 + + +def quote_attrib(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + if '"' in s1: + if "'" in s1: + s1 = '"%s"' % s1.replace('"', """) + else: + s1 = "'%s'" % s1 + else: + s1 = '"%s"' % s1 + 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 + + +def get_all_text_(node): + if node.text is not None: + text = node.text + else: + text = '' + for child in node: + if child.tail is not None: + text += child.tail + return text + + +def find_attr_value_(attr_name, node): + attrs = node.attrib + attr_parts = attr_name.split(':') + value = None + if len(attr_parts) == 1: + value = attrs.get(attr_name) + elif len(attr_parts) == 2: + prefix, name = attr_parts + namespace = node.nsmap.get(prefix) + if namespace is not None: + value = attrs.get('{%s}%s' % (namespace, name, )) + return value + + +class GDSParseError(Exception): + pass + + +def raise_parse_error(node, msg): + if XMLParser_import_library == XMLParser_import_lxml: + msg = '%s (element %s/line %d)' % ( + msg, node.tag, node.sourceline, ) + else: + msg = '%s (element %s)' % (msg, node.tag, ) + raise GDSParseError(msg) + + +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 + TypeBase64 = 8 + 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, namespace, pretty_print=True): + if self.category == MixedContainer.CategoryText: + # Prevent exporting empty content as empty lines. + if self.value.strip(): + outfile.write(self.value) + elif self.category == MixedContainer.CategorySimple: + self.exportSimple(outfile, level, name) + else: # category == MixedContainer.CategoryComplex + self.value.export(outfile, level, namespace, name, pretty_print) + 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)) + elif self.content_type == MixedContainer.TypeBase64: + outfile.write('<%s>%s</%s>' % ( + self.name, base64.b64encode(self.value), self.name)) + def to_etree(self, element): + if self.category == MixedContainer.CategoryText: + # Prevent exporting empty content as empty lines. + if self.value.strip(): + if len(element) > 0: + if element[-1].tail is None: + element[-1].tail = self.value + else: + element[-1].tail += self.value + else: + if element.text is None: + element.text = self.value + else: + element.text += self.value + elif self.category == MixedContainer.CategorySimple: + subelement = etree_.SubElement(element, '%s' % self.name) + subelement.text = self.to_etree_simple() + else: # category == MixedContainer.CategoryComplex + self.value.to_etree(element) + def to_etree_simple(self): + if self.content_type == MixedContainer.TypeString: + text = self.value + elif (self.content_type == MixedContainer.TypeInteger or + self.content_type == MixedContainer.TypeBoolean): + text = '%d' % self.value + elif (self.content_type == MixedContainer.TypeFloat or + self.content_type == MixedContainer.TypeDecimal): + text = '%f' % self.value + elif self.content_type == MixedContainer.TypeDouble: + text = '%g' % self.value + elif self.content_type == MixedContainer.TypeBase64: + text = '%s' % base64.b64encode(self.value) + return text + def exportLiteral(self, outfile, level, name): + if self.category == MixedContainer.CategoryText: + showIndent(outfile, level) + outfile.write( + 'model_.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( + 'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % ( + self.category, self.content_type, self.name, self.value)) + else: # category == MixedContainer.CategoryComplex + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s",\n' % ( + self.category, self.content_type, self.name,)) + self.value.exportLiteral(outfile, level + 1) + showIndent(outfile, level) + outfile.write(')\n') + + +class MemberSpec_(object): + def __init__(self, name='', data_type='', container=0): + self.name = name + self.data_type = data_type + self.container = container + def set_name(self, name): self.name = name + def get_name(self): return self.name + def set_data_type(self, data_type): self.data_type = data_type + def get_data_type_chain(self): return self.data_type + def get_data_type(self): + if isinstance(self.data_type, list): + if len(self.data_type) > 0: + return self.data_type[-1] + else: + return 'xs:string' + else: + return self.data_type + def set_container(self, container): self.container = container + def get_container(self): return self.container + + +def _cast(typ, value): + if typ is None or value is None: + return value + return typ(value) + +# +# Data representation classes. +# + + +class FooList(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('Foo', 'FooType1', 0), + MemberSpec_('Bar', 'BarType2', 0), + MemberSpec_('Baz', 'BazType3', 0), + ] + subclass = None + superclass = None + def __init__(self, Foo=None, Bar=None, Baz=None): + self.Foo = Foo + self.Bar = Bar + self.Baz = Baz + def factory(*args_, **kwargs_): + if FooList.subclass: + return FooList.subclass(*args_, **kwargs_) + else: + return FooList(*args_, **kwargs_) + factory = staticmethod(factory) + def get_Foo(self): return self.Foo + def set_Foo(self, Foo): self.Foo = Foo + def get_Bar(self): return self.Bar + def set_Bar(self, Bar): self.Bar = Bar + def get_Baz(self): return self.Baz + def set_Baz(self, Baz): self.Baz = Baz + def hasContent_(self): + if ( + self.Foo is not None or + self.Bar is not None or + self.Baz is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='FooList', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='FooList') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_, name_, pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='FooList'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='FooList', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.Foo is not None: + self.Foo.export(outfile, level, namespace_, name_='Foo', pretty_print=pretty_print) + if self.Bar is not None: + self.Bar.export(outfile, level, namespace_, name_='Bar', pretty_print=pretty_print) + if self.Baz is not None: + self.Baz.export(outfile, level, namespace_, name_='Baz', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='FooList'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.Foo is not None: + showIndent(outfile, level) + outfile.write('Foo=model_.FooType1(\n') + self.Foo.exportLiteral(outfile, level, name_='Foo') + showIndent(outfile, level) + outfile.write('),\n') + if self.Bar is not None: + showIndent(outfile, level) + outfile.write('Bar=model_.BarType2(\n') + self.Bar.exportLiteral(outfile, level, name_='Bar') + showIndent(outfile, level) + outfile.write('),\n') + if self.Baz is not None: + showIndent(outfile, level) + outfile.write('Baz=model_.BazType3(\n') + self.Baz.exportLiteral(outfile, level, name_='Baz') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'Foo': + obj_ = FooType1.factory() + obj_.build(child_) + self.Foo = obj_ + elif nodeName_ == 'Bar': + obj_ = BarType2.factory() + obj_.build(child_) + self.Bar = obj_ + elif nodeName_ == 'Baz': + obj_ = BazType3.factory() + obj_.build(child_) + self.Baz = obj_ +# end class FooList + + +class FooType1(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('FooType', ['FooTypeType', 'xs:string'], 0), + ] + subclass = None + superclass = None + def __init__(self, FooType=None): + self.FooType = FooType + def factory(*args_, **kwargs_): + if FooType1.subclass: + return FooType1.subclass(*args_, **kwargs_) + else: + return FooType1(*args_, **kwargs_) + factory = staticmethod(factory) + def get_FooType(self): return self.FooType + def set_FooType(self, FooType): self.FooType = FooType + def validate_FooTypeType(self, value): + # Validate type FooTypeType, a restriction on xs:string. + pass + def hasContent_(self): + if ( + self.FooType is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='FooType1', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='FooType1') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_, name_, pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='FooType1'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='FooType1', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.FooType is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sFooType>%s</%sFooType>%s' % (namespace_, self.gds_format_string(quote_xml(self.FooType).encode(ExternalEncoding), input_name='FooType'), namespace_, eol_)) + def exportLiteral(self, outfile, level, name_='FooType1'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.FooType is not None: + showIndent(outfile, level) + outfile.write('FooType=%s,\n' % quote_python(self.FooType).encode(ExternalEncoding)) + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'FooType': + FooType_ = child_.text + FooType_ = self.gds_validate_string(FooType_, node, 'FooType') + self.FooType = FooType_ + self.validate_FooTypeType(self.FooType) # validate type FooTypeType +# end class FooType1 + + +class BarType2(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('BarType', ['BarTypeType', 'xs:string'], 0), + ] + subclass = None + superclass = None + def __init__(self, BarType=None): + self.BarType = BarType + def factory(*args_, **kwargs_): + if BarType2.subclass: + return BarType2.subclass(*args_, **kwargs_) + else: + return BarType2(*args_, **kwargs_) + factory = staticmethod(factory) + def get_BarType(self): return self.BarType + def set_BarType(self, BarType): self.BarType = BarType + def validate_BarTypeType(self, value): + # Validate type BarTypeType, a restriction on xs:string. + pass + def hasContent_(self): + if ( + self.BarType is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='BarType2', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='BarType2') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_, name_, pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='BarType2'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='BarType2', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.BarType is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sBarType>%s</%sBarType>%s' % (namespace_, self.gds_format_string(quote_xml(self.BarType).encode(ExternalEncoding), input_name='BarType'), namespace_, eol_)) + def exportLiteral(self, outfile, level, name_='BarType2'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.BarType is not None: + showIndent(outfile, level) + outfile.write('BarType=%s,\n' % quote_python(self.BarType).encode(ExternalEncoding)) + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'BarType': + BarType_ = child_.text + BarType_ = self.gds_validate_string(BarType_, node, 'BarType') + self.BarType = BarType_ + self.validate_BarTypeType(self.BarType) # validate type BarTypeType +# end class BarType2 + + +class BazType3(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('BazType', ['BazTypeType', 'xs:string'], 0), + ] + subclass = None + superclass = None + def __init__(self, BazType=None): + self.BazType = BazType + def factory(*args_, **kwargs_): + if BazType3.subclass: + return BazType3.subclass(*args_, **kwargs_) + else: + return BazType3(*args_, **kwargs_) + factory = staticmethod(factory) + def get_BazType(self): return self.BazType + def set_BazType(self, BazType): self.BazType = BazType + def validate_BazTypeType(self, value): + # Validate type BazTypeType, a restriction on xs:string. + pass + def hasContent_(self): + if ( + self.BazType is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='BazType3', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='BazType3') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_, name_, pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='BazType3'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='BazType3', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.BazType is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sBazType>%s</%sBazType>%s' % (namespace_, self.gds_format_string(quote_xml(self.BazType).encode(ExternalEncoding), input_name='BazType'), namespace_, eol_)) + def exportLiteral(self, outfile, level, name_='BazType3'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.BazType is not None: + showIndent(outfile, level) + outfile.write('BazType=%s,\n' % quote_python(self.BazType).encode(ExternalEncoding)) + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'BazType': + BazType_ = child_.text + BazType_ = self.gds_validate_string(BazType_, node, 'BazType') + self.BazType = BazType_ + self.validate_BazTypeType(self.BazType) # validate type BazTypeType +# end class BazType3 + + +GDSClassesMapping = { + 'Baz': BazType3, + 'Foo': FooType1, + 'Bar': BarType2, +} + + +USAGE_TEXT = """ +Usage: python <Parser>.py [ -s ] <in_xml_file> +""" + + +def usage(): + print USAGE_TEXT + sys.exit(1) + + +def get_root_tag(node): + tag = Tag_pattern_.match(node.tag).groups()[-1] + rootClass = GDSClassesMapping.get(tag) + if rootClass is None: + rootClass = globals().get(tag) + return tag, rootClass + + +def parse(inFileName, silence=False): + doc = parsexml_(inFileName) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'FooList' + rootClass = FooList + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None +## if not silence: +## sys.stdout.write('<?xml version="1.0" ?>\n') +## rootObj.export( +## sys.stdout, 0, name_=rootTag, +## namespacedef_='', +## pretty_print=True) + return rootObj + + +def parseEtree(inFileName, silence=False): + doc = parsexml_(inFileName) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'FooList' + rootClass = FooList + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + mapping = {} + rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping) + reverse_mapping = rootObj.gds_reverse_node_mapping(mapping) +## if not silence: +## content = etree_.tostring( +## rootElement, pretty_print=True, +## xml_declaration=True, encoding="utf-8") +## sys.stdout.write(content) +## sys.stdout.write('\n') + return rootObj, rootElement, mapping, reverse_mapping + + +def parseString(inString, silence=False): + from StringIO import StringIO + doc = parsexml_(StringIO(inString)) + rootNode = doc.getroot() + roots = get_root_tag(rootNode) + rootClass = roots[1] + if rootClass is None: + rootClass = FooList + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None +## if not silence: +## sys.stdout.write('<?xml version="1.0" ?>\n') +## rootObj.export( +## sys.stdout, 0, name_="FooList", +## namespacedef_='') + return rootObj + + +def parseLiteral(inFileName, silence=False): + doc = parsexml_(inFileName) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'FooList' + rootClass = FooList + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None +## if not silence: +## sys.stdout.write('#from anonymous_type2_sup import *\n\n') +## sys.stdout.write('import anonymous_type2_sup as model_\n\n') +## sys.stdout.write('rootObj = model_.rootTag(\n') +## rootObj.exportLiteral(sys.stdout, 0, name_=rootTag) +## sys.stdout.write(')\n') + return rootObj + + +def main(): + args = sys.argv[1:] + if len(args) == 1: + parse(args[0]) + else: + usage() + + +if __name__ == '__main__': + #import pdb; pdb.set_trace() + main() + + +__all__ = [ + "BarType2", + "BazType3", + "FooList", + "FooType1" +] diff --git a/tests/test.py b/tests/test.py index 8a0b622e09d798096d0d16419cc6e4d3d8408ca7..7b13b396a855192c3e1ab9fbd34d79f1acf86851 100755 --- a/tests/test.py +++ b/tests/test.py @@ -128,9 +128,9 @@ class GenTest(unittest.TestCase): 'print (node.get_name(), node.get_valueOf_())"' ) cmd = cmdTempl % (t_, t_) - print 'cmd:', cmd + #print 'cmd:', cmd result, err = self.execute(cmd) - print 'result: %s' % result + #print 'result: %s' % result self.failUnlessEqual(result, """\ ('child1', 'value1') """) @@ -453,6 +453,24 @@ class GenTest(unittest.TestCase): result, err = self.execute(cmd) self.check_result(result, err, ()) + def test_021_anonymous_type(self): + cmdTempl = ( + 'python generateDS.py --no-dates --no-versions ' + '--silence --member-specs=list -f ' + '-o tests/%s2_sup.py -s tests/%s2_sub.py ' + '--super=%s2_sup ' + 'tests/%s.xsd' + ) + t_ = 'anonymous_type' + cmd = cmdTempl % (t_, t_, t_, t_, ) + result, _ = self.execute(cmd, cwd='..') + cmd = 'diff %s1_sup.py %s2_sup.py' % (t_, t_, ) + result, err = self.execute(cmd) + self.check_result(result, err, ('sys.stdout.write',)) + cmd = 'diff %s1_sub.py %s2_sub.py' % (t_, t_, ) + result, err = self.execute(cmd) + self.check_result(result, err, ()) + def check_result(self, result, err, ignore_strings): self.failUnlessEqual(len(result), 0) self.failUnlessEqual(len(err), 0) diff --git a/tutorial/generateds_tutorial.txt b/tutorial/generateds_tutorial.txt index ee5f8b4974fe4c9c3e951aebd51919cc00421bcf..0ad7680f6df176396b16d11bdff05aa00e5d0596 100644 --- a/tutorial/generateds_tutorial.txt +++ b/tutorial/generateds_tutorial.txt @@ -11,7 +11,7 @@ generateDS -- Introduction and Tutorial .. version -:revision: 2.11a +:revision: 2.11b .. version