diff --git a/generateDS.py b/generateDS.py index bf52136..94cb42d 100755 --- a/generateDS.py +++ b/generateDS.py @@ -1807,11 +1807,13 @@ class XschemaAttribute: def __init__(self, parser_generator, name, data_type='xs:string', use='optional', default=None): self._PGenr = parser_generator self.name = name + self.cleanName = self._PGenr.cleanupName(name) self.data_type = data_type self.use = use self.default = default # Enumeration values for the attribute. self.values = list() + def getCleanName(self): return self.cleanName def setName(self, name): self.name = name def getName(self): return self.name def setData_type(self, data_type): self.data_type = data_type diff --git a/type_model.py b/type_model.py index 1596eec..a493a9e 100644 --- a/type_model.py +++ b/type_model.py @@ -27,6 +27,7 @@ def __init__(self): class ComplexType(object): def __init__(self, name): self._name = name + self._is_attribute = False self._data_types = [] self._data_members = [] @@ -48,37 +49,58 @@ def Build(self, xsdTypeDict, cTypeDict): self._xsd_type = xsdTypeDict[self._name] children = self._xsd_type.getChildren() - for child in children: - if child.isComplex(): - descendent = ComplexTypeLocate(xsdTypeDict, cTypeDict, child.getType()) - self._data_types.append(descendent) - cpptype = child.getType() - jtype = child.getType() - cppname = child.getCleanName() - else: - cpptype = getCppType(child.getType()) - jtype = getJavaType(child.getType()) + if children: + for child in children: + if child.isComplex(): + descendent = ComplexTypeLocate(xsdTypeDict, cTypeDict, child.getType()) + self._data_types.append(descendent) + cpptype = child.getType() + jtype = child.getType() + cppname = child.getCleanName() + else: + cpptype = getCppType(child.getType()) + jtype = getJavaType(child.getType()) + if cpptype == 'void': + logger = logging.getLogger('type_model') + logger.warning('simpleType %s: unknown' % child.getType()) + cppname = child.getCleanName() + + member = MemberInfo() + member.elementname = child.getName() + member.membername = CppVariableName(cppname) + member.xsd_object = child + member.isComplex = child.isComplex() + if child.getMaxOccurs() > 1: + member.membername = cppname# + '_list' + member.sequenceType = cpptype + cpptype = 'std::vector<%s>' % cpptype + jtype = 'List<%s>' % jtype + member.isSequence = True + + member.ctypename = cpptype + member.jtypename = jtype + member.default = child.getDefault() + self._data_members.append(member) + else: + attributes = self._xsd_type.getAttributeDefs().values() + if attributes: + self._is_attribute = True + for attribute in attributes: + cpptype = getCppType(attribute.getType()) + jtype = getJavaType(attribute.getType()) if cpptype == 'void': logger = logging.getLogger('type_model') - logger.warning('simpleType %s: unknown' % child.getType()) - cppname = child.getCleanName() - - member = MemberInfo() - member.elementname = child.getName() - member.membername = CppVariableName(cppname) - member.xsd_object = child - member.isComplex = child.isComplex() - if child.getMaxOccurs() > 1: - member.membername = cppname# + '_list' - member.sequenceType = cpptype - cpptype = 'std::vector<%s>' % cpptype - jtype = 'List<%s>' % jtype - member.isSequence = True - - member.ctypename = cpptype - member.jtypename = jtype - member.default = child.getDefault() - self._data_members.append(member) + logger.warning('simpleType %s: unknown' % attribute.getType()) + cppname = attribute.getCleanName() + member = MemberInfo() + member.elementname = attribute.getName() + member.membername = CppVariableName(cppname) + member.xsd_object = attribute + member.isComplex = False + member.ctypename = cpptype + member.jtypename = jtype + member.default = attribute.getDefault() + self._data_members.append(member) def ComplexTypeLocate(xsdTypeDict, cTypeDict, xtypename): diff --git a/type_parser.py b/type_parser.py index 2459cfc..e99a285 100644 --- a/type_parser.py +++ b/type_parser.py @@ -91,7 +91,7 @@ def GenerateTypeParser(self, file, ctype): file.write(export) for member in ctype.getDataMembers(): - indent = ' ' * 4 + indent = ' ' * 4 cpptype = member.ctypename if cpptype == 'int': file.write(indent + "// Add child node \n"); @@ -141,7 +141,7 @@ def GenerateTypeParser(self, file, ctype): 'membername': member.membername, 'elementname': member.elementname } file.write(item) - elif member.isSequence and member.sequenceType == 'std::string': + elif member.isSequence and member.sequenceType == 'std::string': item = """ for (%(type)s::const_iterator iter = %(membername)s.begin(); iter != %(membername)s.end(); ++iter) { @@ -183,6 +183,88 @@ def GenerateTypeParser(self, file, ctype): file.write(indent + fmt % (member.membername)) file.write('}\n') + def GenerateAttributeParser(self, file, ctype): + print "generating parser for attribute %s" %ctype.getName() + start = """ +bool %s::XmlParse(const xml_node &parent) { + for (xml_attribute attr = parent.first_attribute(); attr; + attr = attr.next_attribute()) { +""" % ctype.getName() + file.write(start) + for member in ctype.getDataMembers(): + file.write(' if (strcmp(attr.name(), "%s") == 0) {\n' % + member.xsd_object.getName()) + indent = ' ' * 12 + cpptype = member.ctypename + if cpptype == 'int': + fmt = 'if (!ParseInteger(attr, &%s)) return false;\n' + file.write(indent + fmt % member.membername) + elif cpptype == 'uint64_t': + fmt = 'if (!ParseUnsignedLong(attr, &%s)) return false;\n' + file.write(indent + fmt % member.membername) + elif cpptype == 'bool': + fmt = 'if (!ParseBoolean(attr, &%s)) return false;\n' + file.write(indent + fmt % member.membername) + elif cpptype == 'std::string': + fmt = '%s = attr.value();\n' + file.write(indent + fmt % member.membername) + file.write(' }\n') + file.write(' }\n return true;\n}\n') + + static_fn = """ +bool %s::XmlParseProperty(const xml_node &parent, + auto_ptr *resultp) { + %s *ptr = new %s(); + resultp->reset(ptr); + if (!ptr->XmlParse(parent)) { + return false; + } + return true; +} +""" % (ctype.getName(), ctype.getName(), ctype.getName()) + file.write(static_fn) + + export = """ +void %s::Encode(xml_node *node_p) const { + pugi::xml_attribute attr; + +""" % (ctype.getName()) + file.write(export) + + for member in ctype.getDataMembers(): + indent = ' ' * 4 + cpptype = member.ctypename + if cpptype == 'int': + file.write(indent + "// Add child node \n"); + fmt = 'attr = node_p->append_attribute("%s");\n' + file.write(indent + fmt % member.elementname) + fmt = 'attr.set_value(%s::%s);\n\n' + file.write(indent + fmt % (ctype.getName(),member.membername)) + if cpptype == 'uint64_t': + cdecl = """ + attr = node_p->append_attribute("%(elementname)s"); + { + ostringstream oss; + oss << %(membername)s; + attr.set_value(oss.str().c_str()); + } +""" % {'elementname': member.xsd_object.getName(), 'membername': member.membername} + file.write(cdecl) + elif cpptype == 'bool': + file.write(indent + "// Add child node \n"); + fmt = 'attr = node_p->append_attribute("%s");\n' + file.write(indent + fmt % member.elementname) + fmt = 'attr.set_value(%s::%s);\n\n' + file.write(indent + fmt % (ctype.getName(),member.membername)) + elif cpptype == 'std::string': + file.write(indent + "// Add child node \n"); + fmt = 'attr = node_p->append_attribute("%s");\n' + file.write(indent + fmt % member.elementname) + fmt = 'attr.set_value(%s::%s.c_str());\n\n' + file.write(indent + fmt % (ctype.getName(),member.membername)) + file.write('}\n') + + def Generate(self, file, hdrname): header = """ @@ -203,6 +285,28 @@ def Generate(self, file, hdrname): #endif namespace autogen { +static bool ParseInteger(const pugi::xml_attribute &attr, int *valuep) { + char *endp; + *valuep = strtoul(attr.value(), &endp, 10); + while (isspace(*endp)) endp++; + return endp[0] == '\\0'; +} + +static bool ParseUnsignedLong(const pugi::xml_attribute &attr, uint64_t *valuep) { + char *endp; + *valuep = strtoull(attr.value(), &endp, 10); + while (isspace(*endp)) endp++; + return endp[0] == '\\0'; +} + +static bool ParseBoolean(const pugi::xml_attribute &attr, bool *valuep) { + if (strcmp(attr.value(), "true") ==0) + *valuep = true; + else + *valuep = false; + return true; +} + static bool ParseInteger(const pugi::xml_node &node, int *valuep) { char *endp; *valuep = strtoul(node.child_value(), &endp, 10); @@ -218,7 +322,7 @@ def Generate(self, file, hdrname): } static bool ParseBoolean(const pugi::xml_node &node, bool *valuep) { - if (strcmp(node.child_value(), "true") ==0) + if (strcmp(node.child_value(), "true") ==0) *valuep = true; else *valuep = false; @@ -264,5 +368,8 @@ def Generate(self, file, hdrname): """ % hdrname file.write(header) for ctype in self._cTypeDict.values(): - self.GenerateTypeParser(file, ctype) + if ctype._is_attribute: + self.GenerateAttributeParser(file, ctype) + else: + self.GenerateTypeParser(file, ctype) file.write('} // namespace autogen\n')