private void printTable(ORASSNode node, int numOfTabs) {
		
		String tableName = node.getName();
		
		writer.println(getTabs(numOfTabs)     + "<xs:complexType name=\""+tableName+"_Type\">");
		writer.println(getTabs(numOfTabs + 1) + "<xs:attribute name=\""+tableName+"#\" type=\"xs:string\" use=\"required\"/>");
		
		List<ORASSNode> superTypes = node.getSupertypeNode();
		ORASSNode normalEntity = node.getNormalEntityNode();
		boolean isSubType = superTypes.size() > 0 ? true : false;
		boolean isWeakEntity = normalEntity == null ? false : true;
		
		// print all column info if it is not a subtype
		if (!isSubType) {
			writer.println(getTabs(numOfTabs + 1) + "<xs:all>");
			printColumns(node.getEntityAttributes(), numOfTabs + 2);
		}
		
		// if it is a subtype, print the reference to its supertypes
		if (isSubType) {
			Iterator<ORASSNode> itr = superTypes.iterator();
			while (itr.hasNext()) {
				ORASSNode superType = itr.next();
				String superTypeName = superType.getName();
				writer.println(getTabs(numOfTabs + 1) + "<xs:all>");
				writer.println(getTabs(numOfTabs + 2) + "<xs:element name=\""+superTypeName+"\">");
				writer.println(getTabs(numOfTabs + 3) + "<xs:complexType>");
				writer.println(getTabs(numOfTabs + 4) + "<xs:attribute name=\""+superTypeName+"_Ref\" type=\"xs:string\" use=\"required\"/>");
				writer.println(getTabs(numOfTabs + 3) + "</xs:complexType>");
				writer.println(getTabs(numOfTabs + 2) + "</xs:element>");
			}
		}
		
		// if it is a weak entity, print the reference to its normal entity	
		else if (isWeakEntity) {
			String normalEntityName = normalEntity.getName();
			writer.println(getTabs(numOfTabs + 2) + "<xs:element name=\""+normalEntityName+"\">");
			writer.println(getTabs(numOfTabs + 3) + "<xs:complexType>");
			writer.println(getTabs(numOfTabs + 4) + "<xs:attribute name=\""+normalEntityName+"_Ref\" type=\"xs:string\" use=\"required\"/>");
			writer.println(getTabs(numOfTabs + 3) + "</xs:complexType>");
			writer.println(getTabs(numOfTabs + 2) + "</xs:element>");
		}
		
		// print references to other tables
		List<ORASSNode> children = node.getChildren();
		Iterator<ORASSNode> itr = children.iterator();
		
		while (itr.hasNext()) {
			ORASSNode child = itr.next();
			String childName = child.getName();
			
			String relName = node.getRelation(child);
			List<String> entityNamesInNary = naryRels.get(relName);
			// if 'node' is the first ORASSNode in the n-ary relationship
			if (entityNamesInNary != null) {
				if (entityNamesInNary.get(0).equals(tableName))
					printEntitiesInNary(child, relName, entityNamesInNary, 1, numOfTabs + 2);
			}
			
			else {
				writer.println(getTabs(numOfTabs + 2) + "<xs:element name=\""+childName+"\" minOccurs=\"0\" maxOccurs=\"unbounded\">");
				writer.println(getTabs(numOfTabs + 3) + "<xs:complexType>");
				writer.println(getTabs(numOfTabs + 4) + "<xs:attribute name=\""+childName+"_Ref\" type=\"xs:string\" use=\"required\"/>");
				List<ColumnDetail> relAttrs = child.getRelAttributes();
				if (relAttrs.size() > 0) {
					writer.println(getTabs(numOfTabs + 4) + "<xs:all>");
					printRelColumns(relAttrs, numOfTabs + 5);
					writer.println(getTabs(numOfTabs + 4) + "</xs:all>");
				}
				writer.println(getTabs(numOfTabs + 3) + "</xs:complexType>");
				writer.println(getTabs(numOfTabs + 2) + "</xs:element>");
			}
		}
		
		writer.println(getTabs(numOfTabs + 1) + "</xs:all>");
		writer.println(getTabs(numOfTabs)     + "</xs:complexType>");
		writer.println();
		
		itr = children.iterator();
		while (itr.hasNext()) {
			ORASSNode child = itr.next();
			String childName = child.getName();
			if (!processedTables.contains(childName)) {
				processedTables.add(childName);
				printTable(child, numOfTabs);
			}
		}
	}