function makeXmlCharts(rel) {
		// HELPER FUNCS:
		function hasArea(chartType) {
			function has(type) {
				return chartType.some(function(item) {
					return item.type.name === type;
				});
			}
			if (Array.isArray(chartType)) {
				return has('area');
			}
			return chartType.name === 'area';
		}

		/* ----------------------------------------------------------------------- */

		// STEP 1: Create chart
		{
			var strXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
			// CHARTSPACE: BEGIN vvv
			strXml += '<c:chartSpace xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">';
			strXml += '<c:date1904 val="0"/>';  // ppt defaults to 1904 dates, excel to 1900
			strXml += '<c:chart>';

			// OPTION: Title
			if ( rel.opts.showTitle ) {
				strXml += genXmlTitle({
					title: rel.opts.title || 'Chart Title',
					fontSize: rel.opts.titleFontSize || DEF_FONT_TITLE_SIZE,
					color: rel.opts.titleColor,
					fontFace: rel.opts.titleFontFace,
					rotate: rel.opts.titleRotate,
					titleAlign: rel.opts.titleAlign,
					titlePos: rel.opts.titlePos
				});
				strXml += '<c:autoTitleDeleted val="0"/>';
			}
			else {
				// NOTE: Add autoTitleDeleted tag in else to prevent default creation of chart title even when showTitle is set to false
				strXml += '<c:autoTitleDeleted val="1"/>';
			}
			// Add 3D view tag
			if ( rel.opts.type.name == 'bar3D' ) {
				strXml += '<c:view3D>';
                strXml += ' <c:rotX val="' + rel.opts.v3DRotX + '"/>';
                strXml += ' <c:rotY val="' + rel.opts.v3DRotY + '"/>';
                strXml += ' <c:rAngAx val="' + (rel.opts.v3DRAngAx == false ? 0 : 1) + '"/>';
                strXml += ' <c:perspective val="' + rel.opts.v3DPerspective + '"/>';
                strXml += '</c:view3D>';
			}

            strXml += '<c:plotArea>';
			// IMPORTANT: Dont specify layout to enable auto-fit: PPT does a great job maximizing space with all 4 TRBL locations
			if ( rel.opts.layout ) {
				strXml += '<c:layout>';
				strXml += ' <c:manualLayout>';
				strXml += '  <c:layoutTarget val="inner" />';
				strXml += '  <c:xMode val="edge" />';
				strXml += '  <c:yMode val="edge" />';
				strXml += '  <c:x val="' + (rel.opts.layout.x || 0) + '" />';
				strXml += '  <c:y val="' + (rel.opts.layout.y || 0) + '" />';
				strXml += '  <c:w val="' + (rel.opts.layout.w || 1) + '" />';
				strXml += '  <c:h val="' + (rel.opts.layout.h || 1) + '" />';
				strXml += ' </c:manualLayout>';
				strXml += '</c:layout>';
			}
			else {
				strXml += '<c:layout/>';
			}
		}

		var usesSecondaryValAxis = false;

		// A: Create Chart XML -----------------------------------------------------------
		if ( Array.isArray(rel.opts.type) ) {
			rel.opts.type.forEach(function(type){
				var chartType = type.type.name;
				var data = type.data;
				var options = getMix(rel.opts, type.options);
				var valAxisId = options.secondaryValAxis ? AXIS_ID_VALUE_SECONDARY : AXIS_ID_VALUE_PRIMARY;
				var catAxisId = options.secondaryCatAxis ? AXIS_ID_CATEGORY_SECONDARY : AXIS_ID_CATEGORY_PRIMARY;
				var isMultiTypeChart = true;
				usesSecondaryValAxis = usesSecondaryValAxis || options.secondaryValAxis;
				strXml += makeChartType(chartType, data, options, valAxisId, catAxisId, isMultiTypeChart);
			});
		}
		else {
			var chartType = rel.opts.type.name;
			var isMultiTypeChart = false;
			strXml += makeChartType(chartType, rel.data, rel.opts, AXIS_ID_VALUE_PRIMARY, AXIS_ID_CATEGORY_PRIMARY, isMultiTypeChart);
		}

		// B: Axes -----------------------------------------------------------
		if ( rel.opts.type.name !== 'pie' && rel.opts.type.name !== 'doughnut' ) {
			// Param check
			if ( rel.opts.valAxes && !usesSecondaryValAxis ) {
				throw new Error('Secondary axis must be used by one of the multiple charts');
			}

			if ( rel.opts.catAxes ) {
				if ( !rel.opts.valAxes || rel.opts.valAxes.length !== rel.opts.catAxes.length ) {
					throw new Error('There must be the same number of value and category axes.');
				}
				strXml += makeCatAxis(getMix(rel.opts, rel.opts.catAxes[0]), AXIS_ID_CATEGORY_PRIMARY, AXIS_ID_VALUE_PRIMARY);
				if ( rel.opts.catAxes[1] ) {
					strXml += makeCatAxis(getMix(rel.opts, rel.opts.catAxes[1]), AXIS_ID_CATEGORY_SECONDARY, AXIS_ID_VALUE_PRIMARY);
				}
			}
			else {
				strXml += makeCatAxis(rel.opts, AXIS_ID_CATEGORY_PRIMARY, AXIS_ID_VALUE_PRIMARY);
			}

			rel.opts.hasArea = hasArea(rel.opts.type);

			if ( rel.opts.valAxes ) {
				strXml += makeValueAxis(getMix(rel.opts, rel.opts.valAxes[0]), AXIS_ID_VALUE_PRIMARY, AXIS_ID_CATEGORY_PRIMARY);
				if ( rel.opts.valAxes[1] ) {
					strXml += makeValueAxis(getMix(rel.opts, rel.opts.valAxes[1]), AXIS_ID_VALUE_SECONDARY, AXIS_ID_CATEGORY_SECONDARY);
				}
			}
			else {
				strXml += makeValueAxis(rel.opts, AXIS_ID_VALUE_PRIMARY, AXIS_ID_CATEGORY_PRIMARY, AXIS_ID_CATEGORY_SECONDARY);

				// Add series axis for 3D bar
                if ( rel.opts.type.name == 'bar3D' ) {
                    strXml += makeSerAxis(rel.opts, AXIS_ID_SERIES_PRIMARY, AXIS_ID_VALUE_PRIMARY)
                }
			}
		}

		// C: Chart Properties and plotArea Options: Border, Data Table, Fill, Legend
		{
			// NOTE: DataTable goes between '</c:valAx>' and '<c:spPr>'
			if ( rel.opts.showDataTable ) {
				strXml += '<c:dTable>';
				strXml += '  <c:showHorzBorder val="'+ (rel.opts.showDataTableHorzBorder == false ? 0 : 1) +'"/>';
				strXml += '  <c:showVertBorder val="'+ (rel.opts.showDataTableVertBorder == false ? 0 : 1) +'"/>';
				strXml += '  <c:showOutline    val="'+ (rel.opts.showDataTableOutline    == false ? 0 : 1) +'"/>';
				strXml += '  <c:showKeys       val="'+ (rel.opts.showDataTableKeys       == false ? 0 : 1) +'"/>';
				strXml += '  <c:spPr>';
				strXml += '    <a:noFill/>';
				strXml += '    <a:ln w="9525" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="tx1"><a:lumMod val="15000"/><a:lumOff val="85000"/></a:schemeClr></a:solidFill><a:round/></a:ln>';
				strXml += '    <a:effectLst/>';
				strXml += '  </c:spPr>';
				strXml += '  <c:txPr>\
					          <a:bodyPr rot="0" spcFirstLastPara="1" vertOverflow="ellipsis" vert="horz" wrap="square" anchor="ctr" anchorCtr="1"/>\
					          <a:lstStyle/>\
					          <a:p>\
					            <a:pPr rtl="0">\
					              <a:defRPr sz="1197" b="0" i="0" u="none" strike="noStrike" kern="1200" baseline="0">\
					                <a:solidFill><a:schemeClr val="tx1"><a:lumMod val="65000"/><a:lumOff val="35000"/></a:schemeClr></a:solidFill>\
					                <a:latin typeface="+mn-lt"/>\
					                <a:ea typeface="+mn-ea"/>\
					                <a:cs typeface="+mn-cs"/>\
					              </a:defRPr>\
					            </a:pPr>\
					            <a:endParaRPr lang="en-US"/>\
					          </a:p>\
					        </c:txPr>\
					      </c:dTable>';
			}

			strXml += '  <c:spPr>';

			// OPTION: Fill
			strXml += ( rel.opts.fill ? genXmlColorSelection(rel.opts.fill) : '<a:noFill/>' );

			// OPTION: Border
			strXml += ( rel.opts.border ? '<a:ln w="'+ (rel.opts.border.pt * ONEPT) +'"'+' cap="flat">'+ genXmlColorSelection( rel.opts.border.color ) +'</a:ln>' : '<a:ln><a:noFill/></a:ln>' );

			// Close shapeProp/plotArea before Legend
			strXml += '    <a:effectLst/>';
			strXml += '  </c:spPr>';
			strXml += '</c:plotArea>';

			// OPTION: Legend
			// IMPORTANT: Dont specify layout to enable auto-fit: PPT does a great job maximizing space with all 4 TRBL locations
			if ( rel.opts.showLegend ) {
				strXml += '<c:legend>';
				strXml += '<c:legendPos val="'+ rel.opts.legendPos +'"/>';
				strXml += '<c:layout/>';
				strXml += '<c:overlay val="0"/>';
				if ( rel.opts.legendFontFace || rel.opts.legendFontSize || rel.opts.legendColor ) {
					strXml += '<c:txPr>';
					strXml += '  <a:bodyPr/>';
					strXml += '  <a:lstStyle/>';
					strXml += '  <a:p>';
					strXml += '    <a:pPr>';
					strXml += ( rel.opts.legendFontSize ? '<a:defRPr sz="'+ (Number(rel.opts.legendFontSize) * 100) +'">' : '<a:defRPr>' );
					if ( rel.opts.legendColor ) strXml += genXmlColorSelection(rel.opts.legendColor);
					if ( rel.opts.legendFontFace ) strXml += '<a:latin typeface="'+ rel.opts.legendFontFace +'"/>';
	                if ( rel.opts.legendFontFace ) strXml += '<a:cs    typeface="'+ rel.opts.legendFontFace +'"/>';
					strXml += '      </a:defRPr>';
					strXml += '    </a:pPr>';
					strXml += '    <a:endParaRPr lang="en-US"/>';
					strXml += '  </a:p>';
					strXml += '</c:txPr>';
				}
				strXml += '</c:legend>';
			}
		}

		strXml += '  <c:plotVisOnly val="1"/>';
		strXml += '  <c:dispBlanksAs val="'+ rel.opts.displayBlanksAs +'"/>';
		if ( rel.opts.type.name === 'scatter' ) strXml += '<c:showDLblsOverMax val="1"/>';

		strXml += '</c:chart>';

		// D: CHARTSPACE SHAPE PROPS
		strXml += '<c:spPr>';
		strXml += '  <a:noFill/>';
		strXml += '  <a:ln w="12700" cap="flat"><a:noFill/><a:miter lim="400000"/></a:ln>';
		strXml += '  <a:effectLst/>';
		strXml += '</c:spPr>';

		// E: DATA (Add relID)
		strXml += '<c:externalData r:id="rId1"><c:autoUpdate val="0"/></c:externalData>';

		// LAST: chartSpace end
		strXml += '</c:chartSpace>';

		return strXml;
	}
Main entry point method for create charts
@see: http://www.datypic.com/sc/ooxml/s-dml-chart.xsd.html