diff -r d8fccb2cd802 -r 468f4c8d3d5b Orb/python/orb/XSDToPackageDef.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Orb/python/orb/XSDToPackageDef.py Wed Aug 11 14:49:30 2010 +0100 @@ -0,0 +1,925 @@ +# Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. +# This component and the accompanying materials are made available under the terms of the License +# "Eclipse Public License v1.0" which accompanies this distribution, +# and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Nokia Corporation - initial contribution. +# +# Contributors: +# +# Description: +# Checks links in DITA XML and reports issues. + +""" +Created on 24 May 2010 + +@author: p2ross +""" +import os +import sys +import logging +#import pprint +#import fnmatch +#import re +import string +import time +from optparse import OptionParser#, check_choice +try: + from xml.etree import cElementTree as etree +except ImportError: + from xml.etree import ElementTree as etree +#import multiprocessing + +__version__ = "0.1.0" + + +class XsdBase(object): + PREFIX = '{http://www.w3.org/2001/XMLSchema}' + def _addSchemaPrefix(self, theTag): + return '%s%s' % (self.PREFIX, theTag) + + def _tagSchemaMatches(self, theN, theTag): + return theN.tag == self._addSchemaPrefix(theTag) + + def _tagSchemaMatchesList(self, theN, theTagS): + for aTag in theTagS: + if theN.tag == self._addSchemaPrefix(aTag): + return True + return False + + def _stripSchemaPrefix(self, theN): + """Returns theNode.tag without the schema prefix.""" + return theN.tag[len(self.PREFIX):] + +class XsdNodeBase(XsdBase): + PREFIX = '{http://www.w3.org/2001/XMLSchema}' + def __init__(self, theN): + super(XsdNodeBase, self).__init__() + self._name = theN.get('name') + self._ref = theN.get('ref') + # This will be prefix+element + self._tag = theN.tag + self._min = int(theN.get('minOccurs') or 1) + if theN.get('maxOccurs') == 'unbounded': + self._max = -1 + else: + self._max = int(theN.get('maxOccurs') or 1) + logging.debug( + 'XsdNodeBase.__init__(): tag=%s, name=%s, ref=%s, min=%d, max=%d', + self.tag, + self._name, + self._ref, + self._min, + self._max, + ) + + @property + def tag(self): + return self._tag[len(self.PREFIX):] + + @property + def attrRef(self): + return self._ref + + @property + def attrName(self): + return self._name + + @property + def isUnbounded(self): + return self._max == -1 + + @property + def minOccurs(self): + return self._min + + @property + def maxOccurs(self): + return self._max + + @property + def boundedString(self): + """Returns a natural language description of bounds.""" + if self._min == 1 and self._max == 1: + return '' + elif self._min == 0: + if self._max == 1: + # minOccurs="0" -> 'optional' + return 'optional' + elif self.isUnbounded: + # minOccurs="0" maxOccurs="unbounded" -> 'any number' + return 'any number' + else: + # minOccurs="0" maxOccurs="42" -> 'up to 42' + return 'up to %d' % self._max + elif self.isUnbounded: + # minOccurs="17" maxOccurs="unbounded" -> 'at least 17' + return 'at least %d' % self._min + # minOccurs="17" maxOccurs="42" -> 'at least 17 and up to 42' + return 'at least %d, and up to %d' % (self._min, self._max) + +class Attribute(XsdNodeBase): + """Represents an element describing an attribute.""" + def __init__(self, theN): + super(Attribute, self).__init__(theN) + assert(self._tagSchemaMatches(theN, 'attribute')) + self._default = theN.get('default') + self._use = theN.get('use') + + @property + def default(self): + return self._default + + @property + def use(self): + return self._use + +class RefBase(XsdNodeBase): + """Represents a reference to a group or element""" + def __init__(self, theN): + super(RefBase, self).__init__(theN) + assert(self._tagSchemaMatchesList(theN, ('group', 'element'))) + assert(self.attrRef is not None) + + @property + def isSequence(self): + return False + +class RefSequence(XsdNodeBase): + """Holds information on an xs:all, xs:choice or xs:sequence.""" + def __init__(self, theN): + super(RefSequence, self).__init__(theN) + assert(self._tagSchemaMatchesList(theN, ('all', 'choice', 'sequence'))), 'Tag %s not in list' % theN.tag + # List of class RefBase or, recursively, a class RefSequence + self._refS = [] + self._type = self.tag + for aChild in theN.getchildren(): + if not self._tagSchemaMatchesList(aChild, ('group', 'all', 'choice', 'sequence')): + continue + #self._type = self._stripSchemaPrefix(aChild) + if self._tagSchemaMatches(aChild, 'group'): + self._refS.append(RefBase(aChild)) + elif self._tagSchemaMatchesList( + aChild, + ('choice', 'sequence', 'any',) + ): + self._refS.append(RefSequence(aChild)) + + def genRefs(self): + """Generates the list of RefBase or RefSequence""" + for aRef in self._refS: + yield aRef + + @property + def numRefs(self): + return len(self._refS) + + @property + def refs(self): + return self._refS + + @property + def isSequence(self): + return True + + def qualifierString(self): + if self._type == 'all': + return '(any number, any order)' + elif self._type == 'choice': + return '(any number)' + elif self._type == 'sequence': + return '' + return 'Unknown' + + def joinString(self): + if self._type == 'all': + return ' or ' + elif self._type == 'choice': + return ' or ' + elif self._type == 'sequence': + return ' then ' + return '' + + @property + def seqType(self): + return self._type + +class DefBase(XsdNodeBase): + """Represents a definition of a group, element or complexType""" + def __init__(self, theN): + super(DefBase, self).__init__(theN) + assert(self._tagSchemaMatchesList(theN, ('group', 'element', 'complexType'))), 'Tag %s not in list' % theN.tag + assert(self.attrName is not None or self._tagSchemaMatches(theN, 'complexType')) + # List of class RefBase of class RefSequence + self._refS = [] + + def genRefs(self): + """Generates the list of RefBase""" + for aRef in self._refS: + yield aRef + + @property + def numRefs(self): + return len(self._refS) + + @property + def refs(self): + return self._refS + +class GroupDef(DefBase): + """Represents the definition of a group i.e. .... + See: http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-group""" + def __init__(self, theN): + super(GroupDef, self).__init__(theN) + assert(theN.tag == self._addSchemaPrefix('group')) + # http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-group + # Content: (annotation?, (all | choice | sequence)?) + self._type = None + for aChild in theN.getchildren(): + if self._tagSchemaMatchesList(aChild, ('all', 'choice', 'sequence')): + self._type = self._stripSchemaPrefix(aChild) + else: + # Unrecognised element or annotation + continue + if self._type is not None: + # Read grand children and break + for aGrandChild in aChild.getchildren(): + if aGrandChild.get('ref') is not None \ + and self._tagSchemaMatchesList( + aGrandChild, + ( + 'element', + 'group', + #'choice', + #'sequence', + #'any', + )): + self._refS.append(RefBase(aGrandChild)) + break + + def __str__(self): + #print 'TRACE:', self._refS + return self.joinString().join(['%s' % r.attrRef for r in self._refS]) \ + + ' ' \ + + self.qualifierString() + + def qualifierString(self): + if self._type == 'all': + return '(any number, any order)' + elif self._type == 'choice': + return '(any number)' + elif self._type == 'sequence': + return '' + return 'Unknown' + + def joinString(self): + if self._type == 'all': + return ' or ' + elif self._type == 'choice': + return ' or ' + elif self._type == 'sequence': + return ' then ' + return '' + + @property + def groupType(self): + return self._type + +class ComplexTypeDef(DefBase):#XsdNodeBase): + """Represents the definition of a complexType definition i.e. .... + See: http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-complexType""" + def __init__(self, theN): + super(ComplexTypeDef, self).__init__(theN) + assert(theN.tag == self._addSchemaPrefix('complexType')) + # http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-complexType + # Simplified content: ((group | all | choice | sequence)? + self._type = None + # Get xs:attribute + self._attrS = [] + for aChild in theN.getchildren(): + # We only handle complexType + if not self._tagSchemaMatchesList( + aChild, + ('group', 'all', 'choice', 'sequence', 'attribute')): + # Unrecognised element or annotation + continue + self._type = self._stripSchemaPrefix(aChild) + if self._tagSchemaMatches(aChild, 'group'): + self._refS.append(RefBase(aChild)) + elif self._tagSchemaMatchesList( + aChild, + ('choice', 'sequence', 'any',), + ): + self._refS.append(RefSequence(aChild)) + elif self._tagSchemaMatches(aChild, 'attribute'): + self._attrS.append(Attribute(aChild)) + + @property + def groupType(self): + return self._type + + def namedAttribute(self, theName): + """Returns an Attribute object or None.""" + for anA in self._attrS: + if anA.attrName == theName: + return anA + +class ElementDef(DefBase): + """Represents the definition of a element definition i.e. .... + See: http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-group""" + def __init__(self, theN): + super(ElementDef, self).__init__(theN) + assert(theN.tag == self._addSchemaPrefix('element')) + # http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-element + # Simplified content: (annotation?, ((simpleType | complexType)? + self._type = None + self._complexType = None + for aChild in theN.getchildren(): + # We only handle complexType + if not self._tagSchemaMatchesList(aChild, ('complexType',)): + # Unrecognised element or annotation + continue + # Process a + self._complexType = ComplexTypeDef(aChild) + break + + @property + def complexType(self): + return self._complexType + +class GroupRef(RefBase): + """Represents a reference of a group i.e. . + See: http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-group""" + def __init__(self, theN): + super(GroupRef, self).__init__(theN) + assert(theN.tag == self._addSchemaPrefix('group')) + +class ElementRef(RefBase): + """Represents a reference to an element i.e. . + See: http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-group""" + def __init__(self, theN): + super(ElementRef, self).__init__(theN) + assert(theN.tag == self._addSchemaPrefix('element')) + +class XsdToPackageDef(XsdBase): + """Create a PackageDef.xml file from a set of XSD files.""" + DUMP_PREFIX = ' ' + def __init__(self, thePrefix):#, theOutFile=None, theTitle=''): + super(XsdToPackageDef, self).__init__() + # Maps of group definitions and references + self._groupDefMap = {} + self._groupRefMap = {} + # Maps of element definitions and references + self._elemDefMap = {} + self._elemRefMap = {} + # Top level complex types + self._complexTypeMap = {} + # Element prefix + self._prefix = thePrefix + + ########################## + # Section: Add an XSD file + ########################## + def addXsdFile(self, thePath): + """Read an XSD and add it to the representation.""" + t = etree.parse(thePath) + r = t.getroot() + self._addGroups(r) + self._addElements(r) + self._addComplexTypes(r) + + def addXsdPath(self, thePath): + if os.path.isfile(thePath): + if os.path.splitext(thePath)[1].lower() == '.xsd': + self.addXsdFile(thePath) + elif os.path.isdir(thePath): + for aName in os.listdir(thePath): + self.addXsdPath(os.path.join(thePath, aName)) + + def _addGroups(self, root): + """Adds to the group maps.""" + for anE in root.getchildren(): + if self._tagSchemaMatches(anE, 'group'): + if anE.get('name') is not None: + self._groupDefMap[anE.get('name')] = GroupDef(anE) + elif anE.get('ref') is not None: + self._groupRefMap[anE.get('ref')] = GroupRef(anE) + + def _addElements(self, root): + """Adds to the element maps.""" + for anE in root.getchildren(): + if self._tagSchemaMatches(anE, 'element'): + if anE.get('name') is not None: + self._elemDefMap[anE.get('name')] = ElementDef(anE) + elif anE.get('ref') is not None: + self._elemRefMap[anE.get('ref')] = ElementRef(anE) + + def _addComplexTypes(self, root): + for anE in root.getchildren(): + if self._tagSchemaMatches(anE, 'complexType'): + self._complexTypeMap[anE.get('name')] = ComplexTypeDef(anE) + ########################## + # End: Add an XSD file + ########################## + + ########################## + # Section: Query the IR + ########################## + def elemContains(self, theElemName): + """Returns a list of immediate child elements that this element contains.""" + logging.debug('elemContains(%s)' % theElemName) + retVal = [] + if not self._elemDefMap.has_key(theElemName): + return retVal + myElem = self._elemDefMap[theElemName] + if myElem.complexType is not None: + logging.debug('elemContains(): complexType: %s', myElem.complexType) + #print 'myElem', myElem + for aRef in myElem.complexType.genRefs(): + logging.debug('elemContains(): complexType tag: %s, attrRef: %s', + aRef.tag, + aRef.attrRef, + ) + self._addFromComplexTypeSequence(aRef, retVal) +# myRef = aRef.attrRef +# #print 'myRef', myRef +# #if self._elemDefMap.has_key(myRef): +# # retVal.append(myRef) +# if self._groupDefMap.has_key(myRef): +# self._addContainsGroup(myRef, retVal) +# else: +# retVal.append(myRef) + logging.debug('elemContains(%s) returns %s', theElemName, str(retVal)) + return retVal + + def _addFromComplexTypeSequence(self, theRefObj, theList): + """Recursively add containing elements.""" + myRef = theRefObj.attrRef + logging.debug('_addFromComplexTypeSequence(%s):', myRef) + if theRefObj.isSequence: + for aSubRef in theRefObj.refs: + logging.debug('_addFromComplexTypeSequence(): recursing on: %s', + myRef) + self._addFromComplexTypeSequence(aSubRef, theList) + elif myRef is not None: + if self._groupDefMap.has_key(myRef): + self._addContainsGroup(myRef, theList) + else: + logging.debug('_addFromComplexTypeSequence(): adding: %s', + myRef) + theList.append(myRef) + + def _addContainsGroup(self, theRef, theList): + logging.debug('_addContainsGroup(%s)' % theRef) + assert(self._groupDefMap.has_key(theRef)) + for aRef in self._groupDefMap[theRef].genRefs(): + #print 'TRACE: aRef', aRef.tag + logging.debug('_addContainsGroup(): aRef.tag: %s aRef.attrRef: %s' \ + % (aRef.tag, aRef.attrRef)) + if aRef.tag == 'element': + theList.append(aRef.attrRef) + elif aRef.tag == 'group' and self._groupDefMap.has_key(aRef.attrRef): + self._addContainsGroup(aRef.attrRef, theList) + + ########################## + # End: Query the IR + ########################## + + ########################## + # Section: Debug/trace + ########################## + def dump(self, s=sys.stdout): + s.write(' Group definitions '.center(75, '-')+'\n') + keyS = self._groupDefMap.keys() + keyS.sort() + for k in keyS: + s.write('%40s : %s\n' % (k, self._groupDefMap[k])) + s.write(' EOL '.center(75, '-')+'\n\n') + s.write(' Group references '.center(75, '-')+'\n') + keyS = self._groupRefMap.keys() + keyS.sort() + for k in keyS: + s.write('%40s : %s\n' % (k, self._groupRefMap[k])) + s.write(' EOL '.center(75, '-')+'\n\n') + s.write(' Element definitions '.center(75, '-')+'\n') + keyS = self._elemDefMap.keys() + keyS.sort() + for k in keyS: + s.write('%40s : %s\n' % (k, self._elemDefMap[k])) + s.write(' EOL '.center(75, '-')+'\n\n') + s.write(' Element references '.center(75, '-')+'\n') + keyS = self._elemRefMap.keys() + keyS.sort() + for k in keyS: + s.write('%40s : %s\n' % (k, self._elemRefMap[k])) + s.write(' EOL '.center(75, '-')+'\n\n') + s.write(' Complex types '.center(75, '-')+'\n') + keyS = self._complexTypeMap.keys() + keyS.sort() + for k in keyS: + s.write('%40s : %s\n' % (k, self._complexTypeMap[k])) + s.write(' EOL '.center(75, '-')+'\n\n') + s.write(' Parent to child relationship '.center(75, '-')+'\n') + # A map {element_name : [parent element, ...], ...} + myPcMap = self._retContainedByMap() + keyS = myPcMap.keys() + keyS.sort() + for k in keyS: + s.write('Child: %s\n' % k) + s.write(' Contained by: %s\n' % myPcMap[k]) + s.write(' EOL '.center(75, '-')+'\n\n') + # Run through the elements + keyS = self._elemDefMap.keys() + keyS.sort() + for k in keyS: + myElem = self._elemDefMap[k] + s.write('Element: %s\n' % k) + if myElem.complexType is not None: + for aRef in myElem.complexType.genRefs(): + #print 'TRACE: aRef', aRef + if aRef.isSequence: + self._dumpSequenceRef(s, aRef, level=1) + else: + self._dumpRef(s, aRef, level=1) + else: + s.write(' No complexType\n') + s.write('\n') + + def _dumpRef(self, s, theRef, level=1): + assert(not theRef.isSequence) + if self._groupDefMap.has_key(theRef.attrRef): + s.write('%s%s %s [%s]\n' \ + % (self.DUMP_PREFIX*level, + theRef.attrRef, + '(group)', + theRef.boundedString, + #self._groupDefMap[aRef.attrRef].boundedString, + ) + ) + self._dumpGroupRef(s, theRef.attrRef, level) + #for aGm in self._groupDefMap[aRef.attrRef].genRefs(): + # print ' <%s> %s %s %s' \ + # % (aGm.tag, aGm.attrName, aGm.attrRef, aGm.boundedString) + elif self._elemDefMap.has_key(theRef.attrRef): + s.write('%s%s %s\n' % (self.DUMP_PREFIX*level, theRef.attrRef, '(element)')) + elif self._complexTypeMap.has_key(theRef.attrRef): + s.write('%s%s %s\n' % (self.DUMP_PREFIX*level, theRef.attrRef, '(complex)')) + else: + s.write('%s%s %s\n' % (self.DUMP_PREFIX*level, theRef.attrRef, '(not in my IR)')) + + def _dumpGroupRef(self, s, theR, level=1): + """Dump out references to groups, recursively using self._groupDefMap.""" + assert(self._groupDefMap.has_key(theR)) + if self._groupDefMap[theR].numRefs == 1 \ + and self._groupDefMap[theR].refs[0].tag == 'element': + s.write('%sELEMENT<%s> %s %s "%s" [%s]\n' \ + % ( + self.DUMP_PREFIX*level, + self._groupDefMap[theR].refs[0].tag, + self._groupDefMap[theR].refs[0].attrName, + self._groupDefMap[theR].refs[0].attrRef, + self._groupDefMap[theR].refs[0], + self._groupDefMap[theR].refs[0].boundedString, + ) + ) + else: + s.write('%sGROUP <%s>%s\n' \ + % (self.DUMP_PREFIX*level, self._groupDefMap[theR].tag, self._groupDefMap[theR])) + for aGm in self._groupDefMap[theR].genRefs(): + #print '%s<%s> %s %s "%s"' \ + # % (self.DUMP_PREFIX*level, aGm.tag, aGm.attrName, aGm.attrRef, aGm)#aGm.boundedString) + if aGm.tag == 'group' \ + and aGm.attrRef \ + and self._groupDefMap.has_key(aGm.attrRef): + self._dumpGroupRef(s, aGm.attrRef, level+1) + elif aGm.tag == 'element': + s.write('%sCHLDELE<%s> %s %s "%s"\n' \ + % (self.DUMP_PREFIX*level, aGm.tag, aGm.attrName, aGm.attrRef, aGm))#aGm.boundedString) + + def _dumpSequenceRef(self, s, theR, level=1): + """Dump out sequences recursively.""" + assert(theR.isSequence) + for i, aRef in enumerate(theR.genRefs()): + if i > 0: + s.write('%s[%s]\n' % (self.DUMP_PREFIX*level, theR.joinString())) + #print '%sTRACE: _dumpSequenceRef aRef: %s' % (self.DUMP_PREFIX*level, aRef) + if aRef.isSequence: + self._dumpSequenceRef(s, aRef, level=level+1) + else: + self._dumpRef(s, aRef, level=level+1) + s.write('%s[%s]\n' % (self.DUMP_PREFIX*level, theR.qualifierString())) + ########################## + # End: Debug/trace + ########################## + + ########################## + # Section: Output + ########################## + def _writeHeader(self, theS, theTitle): + self._writeLine(theS, '') + self._writeLine(theS, """""") + self._writeLine(theS, """""" % self._prefix) + self._writeLine(theS, '%s' % theTitle) + + def _writeLine(self, theS, theL): + theS.write(theL) + theS.write('\n') + + def _write(self, theS, theStr): + theS.write(theStr) + + def close(self, theS): + self._writeLine(theS, '') + theS.close() + + def _retContainedByMap(self): + """Returns a map {element_name : [parent element, ...], ...}.""" + retMap = {} + keyS = self._elemDefMap.keys() + # Ensure that every element is represented + for myName in keyS: + retMap[myName] = [] + for myName in keyS: + myContainS = self.elemContains(myName) + for aChild in myContainS: + try: + retMap[aChild].append(myName) + except KeyError: + retMap[aChild] = [myName] + return retMap + + def _retDirName(self, theName): + assert(theName.startswith(self._prefix)) + # Slice the name to get the directory + # e.g. 'cxxVariableDeclarationFile' becomes 'cxxVariable' + # Special case where all ...Ref.dita are in cxxAPIMap/ + if theName.endswith('Ref') \ + or theName == 'cxxAPIMap': + return 'cxxAPIMap' + i = len(self._prefix) + 1 + while i < len(theName) and theName[i] in string.lowercase: + i += 1 + retVal = theName[:i] + # This is a bit clunky for these special cases + if retVal in ('cxxEnumerator', 'cxxEnumerators'): + retVal = 'cxxEnumeration' + return retVal + + def _writeElementNameToFile(self, theS, theName): + if self._elemDefMap.has_key(theName) \ + and theName.startswith(self._prefix): + # Slice the name to get the directory + theDir = self._retDirName(theName) + self._writeLine(theS, '%s ' \ + % (theDir, theName, theName) + ) + else: + # Write out as a keyword + self._writeLine(theS, '%s, ' % theName) + + def _writeContentModelToStream(self, theS, theName): + assert(self._elemDefMap.has_key(theName)) + hasWritten = False + myElem = self._elemDefMap[theName] + if myElem.complexType is not None: + for aRef in myElem.complexType.genRefs(): + #print 'TRACE: aRef', aRef + if aRef.isSequence: + if self._writeContentModelSequenceRef(theS, aRef): + hasWritten = True + else: + if self._writeContentModelRef(theS, aRef): + hasWritten = True + return hasWritten + + def _writeContentModelSequenceRef(self, theS, theR): + assert(theR.isSequence) + hasWritten = False + if theR.numRefs > 0: + self._write(theS, '(') + for i, aRef in enumerate(theR.genRefs()): + if i > 0: + self._writeLine(theS, ' %s ' % theR.joinString()) + hasWritten = True + if aRef.isSequence: + if self._writeContentModelSequenceRef(theS, aRef): + hasWritten = True + else: + if self._writeContentModelRef(theS, aRef): + hasWritten = True + if theR.qualifierString(): + self._writeLine(theS, '%s' % theR.qualifierString()) + if theR.numRefs > 0: + self._write(theS, ')') + return hasWritten + + def _writeContentModelRef(self, theS, theR): + assert(not theR.isSequence) + hasWritten = False + if self._groupDefMap.has_key(theR.attrRef): + #s.write('%s %s\n' % (theR.attrRef, '(group)')) + self._writeContentModelGroupRefToStream(theS, theR)#.attrRef) + hasWritten = True + elif self._elemDefMap.has_key(theR.attrRef): + pass#s.write('%s %s\n' % (theR.attrRef, '(element)')) + elif self._complexTypeMap.has_key(theR.attrRef): + pass#s.write('%s %s\n' % (theR.attrRef, '(complex)')) + else: + #s.write('%s %s\n' % (theR.attrRef, '(not in my IR)')) + self._writeLine(theS, '%s, ' % theR.attrRef) + hasWritten = True + return hasWritten + + def _writeContentModelGroupRefToStream(self, theS, theR): + assert(self._groupDefMap.has_key(theR.attrRef)) + myGroup = self._groupDefMap[theR.attrRef] + if myGroup.numRefs == 1 \ + and myGroup.refs[0].tag == 'element': +# s.write('%sELEMENT<%s> %s %s "%s"\n' \ +# % ( +# self.DUMP_PREFIX*level, +# self._groupDefMap[theR.attrRef].refs[0].tag, +# self._groupDefMap[theR.attrRef].refs[0].attrName, +# self._groupDefMap[theR.attrRef].refs[0].attrRef, +# self._groupDefMap[theR.attrRef].refs[0], +# ) +# ) + #self._write(theS, '(') + aN = myGroup.refs[0].attrRef + self._writeElementNameToFile(theS, aN) + #self._writeLine(theS, '%s, %s' \ + # % (aN, aN, aN, theR.boundedString)) + if theR.boundedString: + self._writeLine(theS, '(%s)' % theR.boundedString) + #self._write(theS, ')') + else: + #s.write('%sGROUP <%s>%s\n' \ + # % (self.DUMP_PREFIX*level, self._groupDefMap[theR.attrRef].tag, self._groupDefMap[theR.attrRef])) + if myGroup.numRefs > 0: + self._write(theS, '(') + for i, aGm in enumerate(myGroup.genRefs()): + #print '%s<%s> %s %s "%s"' \ + # % (self.DUMP_PREFIX*level, aGm.tag, aGm.attrName, aGm.attrRef, aGm)#aGm.boundedString) + if i > 0: + self._writeLine(theS, myGroup.joinString()) + if aGm.tag == 'group' \ + and aGm.attrRef \ + and self._groupDefMap.has_key(aGm.attrRef): + self._writeContentModelGroupRefToStream(theS, aGm)#.attrRef) + elif aGm.tag == 'element' \ + and aGm.attrRef: + self._writeElementNameToFile(theS, aGm.attrRef) + #if self._elemDefMap.has_key(aGm.attrRef): + # aN = aGm.attrRef + # self._writeLine(theS, '%s, ' % (aN, aN, aN)) + #else: + # self._writeLine(theS, '%s, ' % aGm.attrRef) + #elif aGm.tag == 'element': + # s.write('%sCHLDELE<%s> %s %s "%s"\n' \ + # % (self.DUMP_PREFIX*level, aGm.tag, aGm.attrName, aGm.attrRef, aGm))#aGm.boundedString) + self._writeLine(theS, self._groupDefMap[theR.attrRef].qualifierString()) + if myGroup.numRefs > 0: + self._write(theS, ')') + + def writeToFile(self, thePath, theTitle): + myS = open(thePath, 'w') + self._writeHeader(myS, theTitle) + #self.dump() + myChildParentMap = self._retContainedByMap() + #print 'TRACE: myChildParentMap', myChildParentMap + # Run through the elements + keyS = self._elemDefMap.keys() + keyS.sort() + for myName in keyS: + myElem = self._elemDefMap[myName] + logging.info('Writing element: <%s>' % myName) + self._writeLine(myS, '' % myName) + self._writeLine(myS, 'Element: %s' % myName) + self._writeLine(myS, '') + # Section: Contained by + self._writeLine(myS, '
' % myName) + self._writeLine(myS, 'Contained by') + self._writeLine(myS, '

' % myName) + for aParent in myChildParentMap[myName]: + self._writeElementNameToFile(myS, aParent) + #if self._elemDefMap.has_key(aParent): + # self._writeLine(myS, '%s, ' \ + # % (aParent, aParent, aParent)) + #else: + # # Write out as a keyword + # self._writeLine(myS, '%s, ' % aParent) + self._writeLine(myS, '

') + self._writeLine(myS, '
') + # Section: Contains + self._writeLine(myS, + '
' % myName) + self._writeLine(myS, 'Contains') + self._writeLine(myS, '

' % myName) + myContainS = self.elemContains(myName) + myContainS.sort() + #print 'myContainS', myContainS + for aN in myContainS: + self._writeElementNameToFile(myS, aN) + self._writeLine(myS, '

') + self._writeLine(myS, '
') + # Section: Content Model + self._writeLine(myS, '
' % myName) + self._writeLine(myS, 'Content Model') + self._writeLine(myS, '

' % myName) + # Content model contents + if not self._writeContentModelToStream(myS, myName): + self._writeLine(myS, 'No content.') + self._writeLine(myS, '

') + self._writeLine(myS, '
') + # Section: Attributes - empty + self._writeLine(myS, '
' % myName) + # Section: classValue + self._writeLine(myS, '
' % myName) + self._writeLine(myS, 'Inheritance') + self._writeLine(myS, '

' % myName) + if myElem.complexType is not None: + myClassAttr = myElem.complexType.namedAttribute('class') + if myClassAttr is not None \ + and myClassAttr.default is not None: + #print 'TRACE: myClassAttr.default: "%s"' % myClassAttr.default + for aStr in myClassAttr.default[1:].strip().split(): + if aStr.find('/') != -1: + a,b = aStr.split('/') + myS.write(' %s/' % a) + myS.write('%s' % b) + self._writeLine(myS, '

') + self._writeLine(myS, '
') + self._writeLine(myS, '') + self._writeLine(myS, '') + self.close(myS) + + ########################## + # End: Output + ########################## + +def main(): + usage = """usage: %prog [options] file_or_dir +Takes a XSD file or directory and generates a packagedef.dita file with +the documentation for the XSD file(s).""" + print 'Cmd: %s' % ' '.join(sys.argv) + optParser = OptionParser(usage, version='%prog ' + __version__) + optParser.add_option("-d", action="store_true", dest="dump", default=False, + help="Dump IR (for debugging). [default: %default]") + optParser.add_option( + "-l", "--loglevel", + type="int", + dest="loglevel", + default=20, + help="Log Level (debug=10, info=20, warning=30, error=40, critical=50) [default: %default]" + ) + optParser.add_option("-o", "--out", + type="string", + dest="output", + default=None, + help="Output file. [default: %default]") +#=============================================================================== +# optParser.add_option("-u", "--unittest", +# action="store_true", +# dest="unit_test", +# default=False, +# help="Execute unit tests. [default: %default]") +#=============================================================================== + optParser.add_option("-t", "--title", type="string", dest="title", + default='C++ API Reference Content Model Definitions', + help="Title for the packagedef.dita. [default: %default]") + optParser.add_option("-p", "--prefix", type="string", dest="prefix", + default='cxx', + help="Prefix, only the elements starting with this will be documented. Use '' for all. [default: %default]") + opts, args = optParser.parse_args() + clkStart = time.clock() + # Initialise logging etc. + logging.basicConfig(level=opts.loglevel, + format='%(asctime)s %(levelname)-8s %(message)s', + #datefmt='%y-%m-%d % %H:%M:%S', + stream=sys.stdout) +#=============================================================================== +# if opts.unit_test: +# unitTest() +#=============================================================================== + if len(args) > 0: + # Your code here + myX = XsdToPackageDef(opts.prefix) + for aFile in args: + myX.addXsdPath(aFile) + myX.writeToFile(opts.output, opts.title) + if opts.dump: + myX.dump() + else: + optParser.print_help() + optParser.error("No arguments!") + return 1 + clkExec = time.clock() - clkStart + print 'CPU time = %8.3f (S)' % clkExec + print 'Bye, bye!' + return 0 + +if __name__ == '__main__': + #multiprocessing.freeze_support() + sys.exit(main()) +