docs: function parse_xlml_xml(d, _opts) {
  	var opts = _opts || {};
  	make_ssf(SSF);
  	var str = debom(xlml_normalize(d));
  	if(opts && opts.type == 'binary' && typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
  	if(str.substr(0,1000).indexOf("<html") >= 0) return HTML_.to_workbook(str, opts);
  	var Rn;
  	var state = [], tmp;
  	if(DENSE != null && opts.dense == null) opts.dense = DENSE;
  	var sheets = {}, sheetnames = [], cursheet = (opts.dense ? [] : {}), sheetname = "";
  	var table = {}, cell = ({}), row = {};
  	var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
  	var c = 0, r = 0;
  	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
  	var styles = {}, stag = {};
  	var ss = "", fidx = 0;
  	var mergecells = [];
  	var Props = {}, Custprops = {}, pidx = 0, cp = {};
  	var comments = [], comment = {};
  	var cstys = [], csty, seencol = false;
  	var arrayf = [];
  	var rowinfo = [], rowobj = {};
  	var Workbook = ({ Sheets:[], WBProps:{date1904:false} }), wsprops = {};
  	xlmlregex.lastIndex = 0;
  	str = str.replace(/<!--([\s\S]*?)-->/mg,"");
  	while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
  		case 'Data':
  			if(state[state.length-1][1]) break;
  			if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]=="Comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts);
  			else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
  			break;
  		case 'Cell':
  			if(Rn[1]==='/'){
  				if(comments.length > 0) cell.c = comments;
  				if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) {
  					if(opts.dense) {
  						if(!cursheet[r]) cursheet[r] = [];
  						cursheet[r][c] = cell;
  					} else cursheet[encode_col(c) + encode_row(r)] = cell;
  				}
  				if(cell.HRef) {
  					cell.l = {Target:cell.HRef, Tooltip:cell.HRefScreenTip};
  					delete cell.HRef; delete cell.HRefScreenTip;
  				}
  				if(cell.MergeAcross || cell.MergeDown) {
  					var cc = c + (parseInt(cell.MergeAcross,10)|0);
  					var rr = r + (parseInt(cell.MergeDown,10)|0);
  					mergecells.push({s:{c:c,r:r},e:{c:cc,r:rr}});
  				}
  				if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
  				else if(cell.MergeAcross || cell.MergeDown) {
  for(var cma = c; cma <= cc; ++cma) {
  						for(var cmd = r; cmd <= rr; ++cmd) {
  							if(cma > c || cmd > r) {
  								if(opts.dense) {
  									if(!cursheet[cmd]) cursheet[cmd] = [];
  									cursheet[cmd][cma] = {t:'z'};
  								} else cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
  							}
  						}
  					}
  					c = cc + 1;
  				}
  				else ++c;
  			} else {
  				cell = xlml_parsexmltagobj(Rn[0]);
  				if(cell.Index) c = +cell.Index - 1;
  				if(c < refguess.s.c) refguess.s.c = c;
  				if(c > refguess.e.c) refguess.e.c = c;
  				if(Rn[0].slice(-2) === "/>") ++c;
  				comments = [];
  			}
  			break;
  		case 'Row':
  			if(Rn[1]==='/' || Rn[0].slice(-2) === "/>") {
  				if(r < refguess.s.r) refguess.s.r = r;
  				if(r > refguess.e.r) refguess.e.r = r;
  				if(Rn[0].slice(-2) === "/>") {
  					row = xlml_parsexmltag(Rn[0]);
  					if(row.Index) r = +row.Index - 1;
  				}
  				c = 0; ++r;
  			} else {
  				row = xlml_parsexmltag(Rn[0]);
  				if(row.Index) r = +row.Index - 1;
  				rowobj = {};
  				if(row.AutoFitHeight == "0" || row.Height) {
  					rowobj.hpx = parseInt(row.Height, 10); rowobj.hpt = px2pt(rowobj.hpx);
  					rowinfo[r] = rowobj;
  				}
  				if(row.Hidden == "1") { rowobj.hidden = true; rowinfo[r] = rowobj; }
  			}
  			break;
  		case 'Worksheet': /* TODO: read range from FullRows/FullColumns */
  			if(Rn[1]==='/'){
  				if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
  				sheetnames.push(sheetname);
  				if(refguess.s.r <= refguess.e.r && refguess.s.c <= refguess.e.c) cursheet["!ref"] = encode_range(refguess);
  				if(mergecells.length) cursheet["!merges"] = mergecells;
  				if(cstys.length > 0) cursheet["!cols"] = cstys;
  				if(rowinfo.length > 0) cursheet["!rows"] = rowinfo;
  				sheets[sheetname] = cursheet;
  			} else {
  				refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
  				r = c = 0;
  				state.push([Rn[3], false]);
  				tmp = xlml_parsexmltag(Rn[0]);
  				sheetname = unescapexml(tmp.Name);
  				cursheet = (opts.dense ? [] : {});
  				mergecells = [];
  				arrayf = [];
  				rowinfo = [];
  				wsprops = {name:sheetname, Hidden:0};
  				Workbook.Sheets.push(wsprops);
  			}
  			break;
  		case 'Table':
  			if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
  			else if(Rn[0].slice(-2) == "/>") break;
  			else {
  				table = xlml_parsexmltag(Rn[0]);
  				state.push([Rn[3], false]);
  				cstys = []; seencol = false;
  			}
  			break;
  
  		case 'Style':
  			if(Rn[1]==='/') process_style_xlml(styles, stag, opts);
  			else stag = xlml_parsexmltag(Rn[0]);
  			break;
  
  		case 'NumberFormat':
  			stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General");
  			if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf];
  			for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break;
  			if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; }
  			break;
  
  		case 'Column':
  			if(state[state.length-1][0] !== 'Table') break;
  			csty = xlml_parsexmltag(Rn[0]);
  			if(csty.Hidden) { csty.hidden = true; delete csty.Hidden; }
  			if(csty.Width) csty.wpx = parseInt(csty.Width, 10);
  			if(!seencol && csty.wpx > 10) {
  				seencol = true; MDW = DEF_MDW; //find_mdw_wpx(csty.wpx);
  				for(var _col = 0; _col < cstys.length; ++_col) if(cstys[_col]) process_col(cstys[_col]);
  			}
  			if(seencol) process_col(csty);
  			cstys[(csty.Index-1||cstys.length)] = csty;
  			for(var i = 0; i < +csty.Span; ++i) cstys[cstys.length] = dup(csty);
  			break;
  
  		case 'NamedRange':
  			if(!Workbook.Names) Workbook.Names = [];
  			var _NamedRange = parsexmltag(Rn[0]);
  			var _DefinedName = ({
  				Name: _NamedRange.Name,
  				Ref: rc_to_a1(_NamedRange.RefersTo.substr(1))
  			});
  			if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
  Workbook.Names.push(_DefinedName);
  			break;
  
  		case 'NamedCell': break;
  		case 'B': break;
  		case 'I': break;
  		case 'U': break;
  		case 'S': break;
  		case 'Sub': break;
  		case 'Sup': break;
  		case 'Span': break;
  		case 'Border': break;
  		case 'Alignment': break;
  		case 'Borders': break;
  		case 'Font':
  			if(Rn[0].slice(-2) === "/>") break;
  			else if(Rn[1]==="/") ss += str.slice(fidx, Rn.index);
  			else fidx = Rn.index + Rn[0].length;
  			break;
  		case 'Interior':
  			if(!opts.cellStyles) break;
  			stag.Interior = xlml_parsexmltag(Rn[0]);
  			break;
  		case 'Protection': break;
  
  		case 'Author':
  		case 'Title':
  		case 'Description':
  		case 'Created':
  		case 'Keywords':
  		case 'Subject':
  		case 'Category':
  		case 'Company':
  		case 'LastAuthor':
  		case 'LastSaved':
  		case 'LastPrinted':
  		case 'Version':
  		case 'Revision':
  		case 'TotalTime':
  		case 'HyperlinkBase':
  		case 'Manager':
  		case 'ContentStatus':
  		case 'Identifier':
  		case 'Language':
  			if(Rn[0].slice(-2) === "/>") break;
  			else if(Rn[1]==="/") xlml_set_prop(Props, Rn[3], str.slice(pidx, Rn.index));
  			else pidx = Rn.index + Rn[0].length;
  			break;
  		case 'Paragraphs': break;
  
  		case 'Styles':
  		case 'Workbook':
  			if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
  			else state.push([Rn[3], false]);
  			break;
  
  		case 'Comment':
  			if(Rn[1]==='/'){
  				if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
  				xlml_clean_comment(comment);
  				comments.push(comment);
  			} else {
  				state.push([Rn[3], false]);
  				tmp = xlml_parsexmltag(Rn[0]);
  				comment = {a:tmp.Author};
  			}
  			break;
  
  		case 'AutoFilter':
  			if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
  			else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
  				var AutoFilter = xlml_parsexmltag(Rn[0]);
  				cursheet['!autofilter'] = { ref:rc_to_a1(AutoFilter.Range).replace(/\$/g,"") };
  				state.push([Rn[3], true]);
  			}
  			break;
  
  		case 'Name': break;
  
  		case 'ComponentOptions':
  		case 'DocumentProperties':
  		case 'CustomDocumentProperties':
  		case 'OfficeDocumentSettings':
  		case 'PivotTable':
  		case 'PivotCache':
  		case 'Names':
  		case 'MapInfo':
  		case 'PageBreaks':
  		case 'QueryTable':
  		case 'DataValidation':
  		case 'Sorting':
  		case 'Schema':
  		case 'data':
  		case 'ConditionalFormatting':
  		case 'SmartTagType':
  		case 'SmartTags':
  		case 'ExcelWorkbook':
  		case 'WorkbookOptions':
  		case 'WorksheetOptions':
  			if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
  			else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
  			break;
  
  		default:
  			/* FODS file root is <office:document> */
  			if(state.length == 0 && Rn[3] == "document") return parse_fods(str, opts);
  			/* UOS file root is <uof:UOF> */
  			if(state.length == 0 && Rn[3] == "UOF") return parse_fods(str, opts);
  
  			var seen = true;
  			switch(state[state.length-1][0]) {
  				/* OfficeDocumentSettings */
  				case 'OfficeDocumentSettings': switch(Rn[3]) {
  					case 'AllowPNG': break;
  					case 'RemovePersonalInformation': break;
  					case 'DownloadComponents': break;
  					case 'LocationOfComponents': break;
  					case 'Colors': break;
  					case 'Color': break;
  					case 'Index': break;
  					case 'RGB': break;
  					case 'PixelsPerInch': break; // TODO: set PPI
  					case 'TargetScreenSize': break;
  					case 'ReadOnlyRecommended': break;
  					default: seen = false;
  				} break;
  
  				/* ComponentOptions */
  				case 'ComponentOptions': switch(Rn[3]) {
  					case 'Toolbar': break;
  					case 'HideOfficeLogo': break;
  					case 'SpreadsheetAutoFit': break;
  					case 'Label': break;
  					case 'Caption': break;
  					case 'MaxHeight': break;
  					case 'MaxWidth': break;
  					case 'NextSheetNumber': break;
  					default: seen = false;
  				} break;
  
  				/* ExcelWorkbook */
  				case 'ExcelWorkbook': switch(Rn[3]) {
  					case 'Date1904':
  Workbook.WBProps.date1904 = true;
  						break;
  					case 'WindowHeight': break;
  					case 'WindowWidth': break;
  					case 'WindowTopX': break;
  					case 'WindowTopY': break;
  					case 'TabRatio': break;
  					case 'ProtectStructure': break;
  					case 'ProtectWindows': break;
  					case 'ActiveSheet': break;
  					case 'DisplayInkNotes': break;
  					case 'FirstVisibleSheet': break;
  					case 'SupBook': break;
  					case 'SheetName': break;
  					case 'SheetIndex': break;
  					case 'SheetIndexFirst': break;
  					case 'SheetIndexLast': break;
  					case 'Dll': break;
  					case 'AcceptLabelsInFormulas': break;
  					case 'DoNotSaveLinkValues': break;
  					case 'Iteration': break;
  					case 'MaxIterations': break;
  					case 'MaxChange': break;
  					case 'Path': break;
  					case 'Xct': break;
  					case 'Count': break;
  					case 'SelectedSheets': break;
  					case 'Calculation': break;
  					case 'Uncalced': break;
  					case 'StartupPrompt': break;
  					case 'Crn': break;
  					case 'ExternName': break;
  					case 'Formula': break;
  					case 'ColFirst': break;
  					case 'ColLast': break;
  					case 'WantAdvise': break;
  					case 'Boolean': break;
  					case 'Error': break;
  					case 'Text': break;
  					case 'OLE': break;
  					case 'NoAutoRecover': break;
  					case 'PublishObjects': break;
  					case 'DoNotCalculateBeforeSave': break;
  					case 'Number': break;
  					case 'RefModeR1C1': break;
  					case 'EmbedSaveSmartTags': break;
  					default: seen = false;
  				} break;
  
  				/* WorkbookOptions */
  				case 'WorkbookOptions': switch(Rn[3]) {
  					case 'OWCVersion': break;
  					case 'Height': break;
  					case 'Width': break;
  					default: seen = false;
  				} break;
  
  				/* WorksheetOptions */
  				case 'WorksheetOptions': switch(Rn[3]) {
  					case 'Visible':
  						if(Rn[0].slice(-2) === "/>"){/* empty */}
  						else if(Rn[1]==="/") switch(str.slice(pidx, Rn.index)) {
  							case "SheetHidden": wsprops.Hidden = 1; break;
  							case "SheetVeryHidden": wsprops.Hidden = 2; break;
  						}
  						else pidx = Rn.index + Rn[0].length;
  						break;
  					case 'Header':
  						if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
  						cursheet['!margins'].header = parsexmltag(Rn[0]).Margin;
  						break;
  					case 'Footer':
  						if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
  						cursheet['!margins'].footer = parsexmltag(Rn[0]).Margin;
  						break;
  					case 'PageMargins':
  						var pagemargins = parsexmltag(Rn[0]);
  						if(!cursheet['!margins']) default_margins(cursheet['!margins']={},'xlml');
  						if(pagemargins.Top) cursheet['!margins'].top = pagemargins.Top;
  						if(pagemargins.Left) cursheet['!margins'].left = pagemargins.Left;
  						if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right;
  						if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom;
  						break;
  					case 'Unsynced': break;
  					case 'Print': break;
  					case 'Panes': break;
  					case 'Scale': break;
  					case 'Pane': break;
  					case 'Number': break;
  					case 'Layout': break;
  					case 'PageSetup': break;
  					case 'Selected': break;
  					case 'ProtectObjects': break;
  					case 'EnableSelection': break;
  					case 'ProtectScenarios': break;
  					case 'ValidPrinterInfo': break;
  					case 'HorizontalResolution': break;
  					case 'VerticalResolution': break;
  					case 'NumberofCopies': break;
  					case 'ActiveRow': break;
  					case 'ActiveCol': break;
  					case 'ActivePane': break;
  					case 'TopRowVisible': break;
  					case 'TopRowBottomPane': break;
  					case 'LeftColumnVisible': break;
  					case 'LeftColumnRightPane': break;
  					case 'FitToPage': break;
  					case 'RangeSelection': break;
  					case 'PaperSizeIndex': break;
  					case 'PageLayoutZoom': break;
  					case 'PageBreakZoom': break;
  					case 'FilterOn': break;
  					case 'DoNotDisplayGridlines': break;
  					case 'SplitHorizontal': break;
  					case 'SplitVertical': break;
  					case 'FreezePanes': break;
  					case 'FrozenNoSplit': break;
  					case 'FitWidth': break;
  					case 'FitHeight': break;
  					case 'CommentsLayout': break;
  					case 'Zoom': break;
  					case 'LeftToRight': break;
  					case 'Gridlines': break;
  					case 'AllowSort': break;
  					case 'AllowFilter': break;
  					case 'AllowInsertRows': break;
  					case 'AllowDeleteRows': break;
  					case 'AllowInsertCols': break;
  					case 'AllowDeleteCols': break;
  					case 'AllowInsertHyperlinks': break;
  					case 'AllowFormatCells': break;
  					case 'AllowSizeCols': break;
  					case 'AllowSizeRows': break;
  					case 'NoSummaryRowsBelowDetail': break;
  					case 'TabColorIndex': break;
  					case 'DoNotDisplayHeadings': break;
  					case 'ShowPageLayoutZoom': break;
  					case 'NoSummaryColumnsRightDetail': break;
  					case 'BlackAndWhite': break;
  					case 'DoNotDisplayZeros': break;
  					case 'DisplayPageBreak': break;
  					case 'RowColHeadings': break;
  					case 'DoNotDisplayOutline': break;
  					case 'NoOrientation': break;
  					case 'AllowUsePivotTables': break;
  					case 'ZeroHeight': break;
  					case 'ViewableRange': break;
  					case 'Selection': break;
  					case 'ProtectContents': break;
  					default: seen = false;
  				} break;
  
  				/* PivotTable */
  				case 'PivotTable': case 'PivotCache': switch(Rn[3]) {
  					case 'ImmediateItemsOnDrop': break;
  					case 'ShowPageMultipleItemLabel': break;
  					case 'CompactRowIndent': break;
  					case 'Location': break;
  					case 'PivotField': break;
  					case 'Orientation': break;
  					case 'LayoutForm': break;
  					case 'LayoutSubtotalLocation': break;
  					case 'LayoutCompactRow': break;
  					case 'Position': break;
  					case 'PivotItem': break;
  					case 'DataType': break;
  					case 'DataField': break;
  					case 'SourceName': break;
  					case 'ParentField': break;
  					case 'PTLineItems': break;
  					case 'PTLineItem': break;
  					case 'CountOfSameItems': break;
  					case 'Item': break;
  					case 'ItemType': break;
  					case 'PTSource': break;
  					case 'CacheIndex': break;
  					case 'ConsolidationReference': break;
  					case 'FileName': break;
  					case 'Reference': break;
  					case 'NoColumnGrand': break;
  					case 'NoRowGrand': break;
  					case 'BlankLineAfterItems': break;
  					case 'Hidden': break;
  					case 'Subtotal': break;
  					case 'BaseField': break;
  					case 'MapChildItems': break;
  					case 'Function': break;
  					case 'RefreshOnFileOpen': break;
  					case 'PrintSetTitles': break;
  					case 'MergeLabels': break;
  					case 'DefaultVersion': break;
  					case 'RefreshName': break;
  					case 'RefreshDate': break;
  					case 'RefreshDateCopy': break;
  					case 'VersionLastRefresh': break;
  					case 'VersionLastUpdate': break;
  					case 'VersionUpdateableMin': break;
  					case 'VersionRefreshableMin': break;
  					case 'Calculation': break;
  					default: seen = false;
  				} break;
  
  				/* PageBreaks */
  				case 'PageBreaks': switch(Rn[3]) {
  					case 'ColBreaks': break;
  					case 'ColBreak': break;
  					case 'RowBreaks': break;
  					case 'RowBreak': break;
  					case 'ColStart': break;
  					case 'ColEnd': break;
  					case 'RowEnd': break;
  					default: seen = false;
  				} break;
  
  				/* AutoFilter */
  				case 'AutoFilter': switch(Rn[3]) {
  					case 'AutoFilterColumn': break;
  					case 'AutoFilterCondition': break;
  					case 'AutoFilterAnd': break;
  					case 'AutoFilterOr': break;
  					default: seen = false;
  				} break;
  
  				/* QueryTable */
  				case 'QueryTable': switch(Rn[3]) {
  					case 'Id': break;
  					case 'AutoFormatFont': break;
  					case 'AutoFormatPattern': break;
  					case 'QuerySource': break;
  					case 'QueryType': break;
  					case 'EnableRedirections': break;
  					case 'RefreshedInXl9': break;
  					case 'URLString': break;
  					case 'HTMLTables': break;
  					case 'Connection': break;
  					case 'CommandText': break;
  					case 'RefreshInfo': break;
  					case 'NoTitles': break;
  					case 'NextId': break;
  					case 'ColumnInfo': break;
  					case 'OverwriteCells': break;
  					case 'DoNotPromptForFile': break;
  					case 'TextWizardSettings': break;
  					case 'Source': break;
  					case 'Number': break;
  					case 'Decimal': break;
  					case 'ThousandSeparator': break;
  					case 'TrailingMinusNumbers': break;
  					case 'FormatSettings': break;
  					case 'FieldType': break;
  					case 'Delimiters': break;
  					case 'Tab': break;
  					case 'Comma': break;
  					case 'AutoFormatName': break;
  					case 'VersionLastEdit': break;
  					case 'VersionLastRefresh': break;
  					default: seen = false;
  				} break;
  
  				case 'Sorting':
  				case 'ConditionalFormatting':
  				case 'DataValidation':
  				switch(Rn[3]) {
  					case 'Range': break;
  					case 'Type': break;
  					case 'Min': break;
  					case 'Max': break;
  					case 'Sort': break;
  					case 'Descending': break;
  					case 'Order': break;
  					case 'CaseSensitive': break;
  					case 'Value': break;
  					case 'ErrorStyle': break;
  					case 'ErrorMessage': break;
  					case 'ErrorTitle': break;
  					case 'CellRangeList': break;
  					case 'InputMessage': break;
  					case 'InputTitle': break;
  					case 'ComboHide': break;
  					case 'InputHide': break;
  					case 'Condition': break;
  					case 'Qualifier': break;
  					case 'UseBlank': break;
  					case 'Value1': break;
  					case 'Value2': break;
  					case 'Format': break;
  					default: seen = false;
  				} break;
  
  				/* MapInfo (schema) */
  				case 'MapInfo': case 'Schema': case 'data': switch(Rn[3]) {
  					case 'Map': break;
  					case 'Entry': break;
  					case 'Range': break;
  					case 'XPath': break;
  					case 'Field': break;
  					case 'XSDType': break;
  					case 'FilterOn': break;
  					case 'Aggregate': break;
  					case 'ElementType': break;
  					case 'AttributeType': break;
  				/* These are from xsd (XML Schema Definition) */
  					case 'schema':
  					case 'element':
  					case 'complexType':
  					case 'datatype':
  					case 'all':
  					case 'attribute':
  					case 'extends': break;
  
  					case 'row': break;
  					default: seen = false;
  				} break;
  
  				/* SmartTags (can be anything) */
  				case 'SmartTags': break;
  
  				default: seen = false; break;
  			}
  			if(seen) break;
  			/* CustomDocumentProperties */
  			if(!state[state.length-1][1]) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
  			if(state[state.length-1][0]==='CustomDocumentProperties') {
  				if(Rn[0].slice(-2) === "/>") break;
  				else if(Rn[1]==="/") xlml_set_custprop(Custprops, Rn, cp, str.slice(pidx, Rn.index));
  				else { cp = Rn; pidx = Rn.index + Rn[0].length; }
  				break;
  			}
  			if(opts.WTF) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
  	}
  	var out = ({});
  	if(!opts.bookSheets && !opts.bookProps) out.Sheets = sheets;
  	out.SheetNames = sheetnames;
  	out.Workbook = Workbook;
  	out.SSF = SSF.get_table();
  	out.Props = Props;
  	out.Custprops = Custprops;
  	return out;
  }