var parse_content_xml = (function() {
var parse_text_p = function(text, tag) {
return unescapexml(text.replace(//g," ").replace(/<[^>]*>/g,""));
};
var number_formats = {
/* ods name: [short ssf fmt, long ssf fmt] */
day: ["d", "dd"],
month: ["m", "mm"],
year: ["y", "yy"],
hours: ["h", "hh"],
minutes: ["m", "mm"],
seconds: ["s", "ss"],
"am-pm": ["A/P", "AM/PM"],
"day-of-week": ["ddd", "dddd"]
};
return function pcx(d/*:string*/, _opts)/*:Workbook*/ {
var opts = _opts || {};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var str = xlml_normalize(d);
var state/*:Array*/ = [], tmp;
var tag/*:: = {}*/;
var NFtag = {name:""}, NF = "", pidx = 0;
var sheetag/*:: = {name:"", '名称':""}*/;
var rowtag/*:: = {'行号':""}*/;
var Sheets = {}, SheetNames/*:Array*/ = [];
var ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var Rn, q/*:: = ({t:"", v:null, z:null, w:"",c:[]}:any)*/;
var ctag = {value:""};
var textp = "", textpidx = 0, textptag/*:: = {}*/;
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
var number_format_map = {};
var merges = [], mrange = {}, mR = 0, mC = 0;
var arrayf = [];
var comments = [], comment = {};
var creator = "", creatoridx = 0;
var rept = 1, isstub = false;
var i = 0;
xlmlregex.lastIndex = 0;
str = str.replace(//mg,"").replace(//gm,"");
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
case 'table': case '工作表': // 9.1.2
if(Rn[1]==='/') {
if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
if(merges.length) ws['!merges'] = merges;
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
SheetNames.push(sheetag.name);
Sheets[sheetag.name] = ws;
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
sheetag = parsexmltag(Rn[0], false);
R = C = -1;
range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/); merges = [];
}
break;
case 'table-row': case '行': // 9.1.3
if(Rn[1] === '/') break;
rowtag = parsexmltag(Rn[0], false);
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
C = -1; break;
case 'covered-table-cell': // 9.1.5
++C;
if(opts.sheetStubs) {
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; }
else ws[encode_cell({r:R,c:C})] = {t:'z'};
}
break; /* stub */
case 'table-cell': case '数据':
if(Rn[0].charAt(Rn[0].length-2) === '/') {
ctag = parsexmltag(Rn[0], false);
if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10);
else ++C;
}
else if(Rn[1]!=='/') {
++C;
rept = 1;
if(C > range.e.c) range.e.c = C;
if(R > range.e.r) range.e.r = R;
if(C < range.s.c) range.s.c = C;
if(R < range.s.r) range.s.r = R;
ctag = parsexmltag(Rn[0], false);
comments = []; comment = {};
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
if(opts.cellFormula) {
if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
q.F = encode_range(mrange);
arrayf.push([mrange, q.F]);
}
if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
else for(i = 0; i < arrayf.length; ++i)
if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
q.F = arrayf[i][1];
}
if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
mR = parseInt(ctag['number-rows-spanned'],10) || 0;
mC = parseInt(ctag['number-columns-spanned'],10) || 0;
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
merges.push(mrange);
}
/* 19.675.2 table:number-columns-repeated */
if(ctag['number-columns-repeated']) rept = parseInt(ctag['number-columns-repeated'], 10);
/* 19.385 office:value-type */
switch(q.t) {
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break;
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); }
q.z = 'm/d/yy'; break;
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break;
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
default:
if(q.t === 'string' || q.t === 'text' || !q.t) {
q.t = 's';
if(ctag['string-value'] != null) textp = unescapexml(ctag['string-value']);
} else throw new Error('Unsupported value type ' + q.t);
}
} else {
isstub = false;
if(q.t === 's') {
q.v = textp || '';
isstub = textpidx == 0;
}
if(comments.length > 0) { q.c = comments; comments = []; }
if(textp && opts.cellText !== false) q.w = textp;
if(!isstub || opts.sheetStubs) {
if(!(opts.sheetRows && opts.sheetRows < R)) {
if(opts.dense) {
if(!ws[R]) ws[R] = [];
ws[R][C] = q;
while(--rept > 0) ws[R][++C] = dup(q);
} else {
ws[encode_cell({r:R,c:C})] = q;
while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
}
if(range.e.c <= C) range.e.c = C;
}
} else { C += rept; rept = 0; }
q = {/*:: t:"", v:null, z:null, w:"",c:[]*/};
textp = "";
}
break; // 9.1.4
/* pure state */
case 'document': // TODO: is the root for FODS
case 'document-content': case '电子表格文档': // 3.1.3.2
case 'spreadsheet': case '主体': // 3.7
case 'scripts': // 3.12
case 'styles': // TODO
case 'font-face-decls': // 3.14
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
break;
case 'annotation': // 14.1
if(Rn[1]==='/'){
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
comment.t = textp;
comment.a = creator;
comments.push(comment);
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
creator = ""; creatoridx = 0;
textp = ""; textpidx = 0;
break;
case 'creator': // 4.3.2.7
if(Rn[1]==='/') { creator = str.slice(creatoridx,Rn.index); }
else creatoridx = Rn.index + Rn[0].length;
break;
/* ignore state */
case 'meta': case '元数据': // TODO: FODS/UOF
case 'settings': // TODO:
case 'config-item-set': // TODO:
case 'config-item-map-indexed': // TODO:
case 'config-item-map-entry': // TODO:
case 'config-item-map-named': // TODO:
case 'shapes': // 9.2.8
case 'frame': // 10.4.2
case 'text-box': // 10.4.3
case 'image': // 10.4.4
case 'data-pilot-tables': // 9.6.2
case 'list-style': // 16.30
case 'form': // 13.13
case 'dde-links': // 9.8
case 'event-listeners': // TODO
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
textp = ""; textpidx = 0;
break;
case 'scientific-number': // TODO:
break;
case 'currency-symbol': // TODO:
break;
case 'currency-style': // TODO:
break;
case 'number-style': // 16.27.2
case 'percentage-style': // 16.27.9
case 'date-style': // 16.27.10
case 'time-style': // 16.27.18
if(Rn[1]==='/'){
number_format_map[NFtag.name] = NF;
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
NF = "";
NFtag = parsexmltag(Rn[0], false);
state.push([Rn[3], true]);
} break;
case 'script': break; // 3.13
case 'libraries': break; // TODO:
case 'automatic-styles': break; // 3.15.3
case 'master-styles': break; // TODO:
case 'default-style': // TODO:
case 'page-layout': break; // TODO:
case 'style': break; // 16.2
case 'map': break; // 16.3
case 'font-face': break; // 16.21
case 'paragraph-properties': break; // 17.6
case 'table-properties': break; // 17.15
case 'table-column-properties': break; // 17.16
case 'table-row-properties': break; // 17.17
case 'table-cell-properties': break; // 17.18
case 'number': // 16.27.3
switch(state[state.length-1][0]) {
case 'time-style':
case 'date-style':
tag = parsexmltag(Rn[0], false);
NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
} break;
case 'fraction': break; // TODO 16.27.6
case 'day': // 16.27.11
case 'month': // 16.27.12
case 'year': // 16.27.13
case 'era': // 16.27.14
case 'day-of-week': // 16.27.15
case 'week-of-year': // 16.27.16
case 'quarter': // 16.27.17
case 'hours': // 16.27.19
case 'minutes': // 16.27.20
case 'seconds': // 16.27.21
case 'am-pm': // 16.27.22
switch(state[state.length-1][0]) {
case 'time-style':
case 'date-style':
tag = parsexmltag(Rn[0], false);
NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
} break;
case 'boolean-style': break; // 16.27.23
case 'boolean': break; // 16.27.24
case 'text-style': break; // 16.27.25
case 'text': // 16.27.26
if(Rn[0].slice(-2) === "/>") break;
else if(Rn[1]==="/") switch(state[state.length-1][0]) {
case 'number-style':
case 'date-style':
case 'time-style':
NF += str.slice(pidx, Rn.index);
break;
}
else pidx = Rn.index + Rn[0].length;
break;
case 'text-content': break; // 16.27.27
case 'text-properties': break; // 16.27.27
case 'body': case '电子表格': break; // 3.3 16.9.6 19.726.3
case 'forms': break; // 12.25.2 13.2
case 'table-column': break; // 9.1.6
case 'null-date': break; // 9.4.2 TODO: date1904
case 'graphic-properties': break; // 17.21
case 'calculation-settings': break; // 9.4.1
case 'named-expressions': break; // 9.4.11
case 'named-range': break; // 9.4.12
case 'named-expression': break; // 9.4.13
case 'sort': break; // 9.4.19
case 'sort-by': break; // 9.4.20
case 'sort-groups': break; // 9.4.22
case 'span': break; //
case 'line-break': break; // 6.1.5
case 'p': case '文本串':
if(Rn[1]==='/') textp = (textp.length > 0 ? textp + "\n" : "") + parse_text_p(str.slice(textpidx,Rn.index), textptag);
else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
break; //
case 'database-range': // 9.4.15
if(Rn[1]==='/') break;
try {
var AutoFilter = ods_to_csf_range_3D(parsexmltag(Rn[0])['target-range-address']);
Sheets[AutoFilter[0]]['!autofilter'] = { ref: AutoFilter[1] };
} catch(e) { }
break;
case 's': break; //
case 'date': break; // <*:date>
case 'object': break; // 10.4.6.2
case 'title': case '标题': break; // <*:title> OR
case 'desc': break; // <*:desc>
case 'table-source': break; // 9.2.6
case 'iteration': break; // 9.4.3
case 'content-validations': break; // 9.4.4
case 'filter': break; // 9.5.2
case 'filter-and': break; // 9.5.3
case 'filter-or': break; // 9.5.4
case 'filter-condition': break; // 9.5.5
case 'list-level-style-bullet': break; // 16.31
case 'page-count': break; // TODO
case 'time': break; // TODO
/* 9.6 Data Pilot Tables
case 'property': break; // 13.8
case 'a': break; // 6.1.8 hyperlink
/* non-standard */
case 'table-protection': break;
case 'data-pilot-grand-total': break; //