2177 lines
72 KiB
JavaScript
2177 lines
72 KiB
JavaScript
'use strict';
|
||
|
||
/*
|
||
new function() {
|
||
var parser = new EasySAXParser();
|
||
|
||
parser.ns('rss', { // or false
|
||
'http://search.yahoo.com/mrss/': 'media',
|
||
'http://www.w3.org/1999/xhtml': 'xhtml',
|
||
'http://www.w3.org/2005/Atom': 'atom',
|
||
'http://purl.org/rss/1.0/': 'rss',
|
||
});
|
||
|
||
parser.on('error', function(msgError) {
|
||
});
|
||
|
||
parser.on('startNode', function(nodeName, getAttr, isTagEnd, getStrNode) {
|
||
var attr = getAttr();
|
||
});
|
||
|
||
parser.on('endNode', function(nodeName, isTagStart, getStrNode) {
|
||
});
|
||
|
||
parser.on('textNode', function(text) {
|
||
});
|
||
|
||
parser.on('cdata', function(data) {
|
||
});
|
||
|
||
|
||
parser.on('comment', function(text) {
|
||
//console.log('--'+text+'--')
|
||
});
|
||
|
||
//parser.on('unknownNS', function(key) {console.log('unknownNS: ' + key)});
|
||
//parser.on('question', function() {}); // <? ... ?>
|
||
//parser.on('attention', function() {}); // <!XXXXX zzzz="eeee">
|
||
|
||
|
||
parser.write(stringChunk);
|
||
parser.write(stringChunk);
|
||
...
|
||
parser.end(stringChunk);
|
||
};
|
||
|
||
*/
|
||
|
||
// << ------------------------------------------------------------------------ >> //
|
||
|
||
EasySAXParser.entityDecode = xmlEntityDecode;
|
||
if (typeof module === 'object') {
|
||
module.exports = EasySAXParser;
|
||
};
|
||
|
||
|
||
var stringFromCharCode = String.fromCharCode;
|
||
var objectCreate = Object.create;
|
||
function NULL_FUNC() {};
|
||
|
||
|
||
function entity2char(x) {
|
||
if (x === 'amp') {
|
||
return '&';
|
||
};
|
||
|
||
switch(x.toLocaleLowerCase()) {
|
||
case 'quot': return '"';
|
||
case 'amp': return '&'
|
||
case 'lt': return '<'
|
||
case 'gt': return '>'
|
||
|
||
case 'plusmn': return '\u00B1';
|
||
case 'laquo': return '\u00AB';
|
||
case 'raquo': return '\u00BB';
|
||
case 'micro': return '\u00B5';
|
||
case 'nbsp': return '\u00A0';
|
||
case 'copy': return '\u00A9';
|
||
case 'sup2': return '\u00B2';
|
||
case 'sup3': return '\u00B3';
|
||
case 'para': return '\u00B6';
|
||
case 'reg': return '\u00AE';
|
||
case 'deg': return '\u00B0';
|
||
case 'apos': return '\'';
|
||
};
|
||
|
||
return '&' + x + ';';
|
||
};
|
||
|
||
function replaceEntities(s, d, x, z) {
|
||
if (z) {
|
||
return entity2char(z);
|
||
};
|
||
|
||
if (d) {
|
||
return stringFromCharCode(d);
|
||
};
|
||
|
||
return stringFromCharCode(parseInt(x, 16));
|
||
};
|
||
|
||
function xmlEntityDecode(s) {
|
||
return StaxParser.prototype.DecodeXml(s);
|
||
};
|
||
|
||
function cloneMatrixNS(nsmatrix) {
|
||
var nn = objectCreate(null);
|
||
for (var n in nsmatrix) {
|
||
nn[n] = nsmatrix[n];
|
||
};
|
||
return nn;
|
||
};
|
||
|
||
var EasySAXEvent = {
|
||
Unknown: 0,
|
||
START_ELEMENT: 1,
|
||
CHARACTERS: 2,
|
||
END_ELEMENT: 3,
|
||
CDATA: 4,
|
||
Comment: 5,
|
||
Attention: 6,
|
||
Question: 7
|
||
}
|
||
|
||
function EasySAXParser(config) {
|
||
if (!this) {
|
||
return null;
|
||
};
|
||
|
||
var onTextNode = NULL_FUNC, onStartNode = NULL_FUNC, onEndNode = NULL_FUNC, onCDATA = NULL_FUNC, onError = NULL_FUNC, onComment, onQuestion, onAttention, onUnknownNS;
|
||
var is_onComment = false, is_onQuestion = false, is_onAttention = false, is_onUnknownNS = false;
|
||
|
||
var isAutoEntity = true; // делать "EntityDecode" всегда
|
||
var indexStartXML; // позиция на которой закончен разбор xml
|
||
var entityDecode = xmlEntityDecode;
|
||
var isNamespace = false;
|
||
var returnError;
|
||
var isParseStop; // прервать парсер
|
||
var defaultNS;
|
||
var nsmatrix = null;
|
||
var useNS;
|
||
var init = false;
|
||
var xml; // string
|
||
|
||
var stringNodePosStart; // number. для получения исходной строки узла
|
||
var stringNodePosEnd; // number. для получения исходной строки узла
|
||
var attrStartPos; // number начало позиции атрибутов в строке attrString <(div^ class="xxxx" title="sssss")/>
|
||
var attrString; // строка атрибутов <(div class="xxxx" title="sssss")/>
|
||
var attrRes; // закешированный результат разбора атрибутов , null - разбор не проводился, object - хеш атрибутов, true - нет атрибутов, false - невалидный xml
|
||
|
||
function reset() {
|
||
if (isNamespace) {
|
||
nsmatrix = objectCreate(null);
|
||
nsmatrix.xmlns = defaultNS;
|
||
};
|
||
|
||
indexStartXML = 0;
|
||
returnError = '';
|
||
isParseStop = false;
|
||
xml = '';
|
||
};
|
||
|
||
this.setup = function (op) {
|
||
for (var name in op) {
|
||
switch(name) {
|
||
case 'entityDecode': entityDecode = op.entityDecode || entityDecode; break;
|
||
case 'autoEntity': isAutoEntity = !!op.autoEntity; break;
|
||
case 'defaultNS': defaultNS = op.defaultNS || null; break;
|
||
case 'ns': useNS = op.ns || null; break;
|
||
case 'on':
|
||
var listeners = op.on;
|
||
for (var ev in listeners) {
|
||
this.on(ev, listeners[ev]);
|
||
};
|
||
break;
|
||
};
|
||
};
|
||
|
||
isNamespace = !!defaultNS && !!useNS;
|
||
};
|
||
|
||
this.on = function(name, cb) {
|
||
// if (typeof cb !== 'function') {
|
||
// if (cb !== null) {
|
||
// throw error('required args on(string, function||null)');
|
||
// };
|
||
// };
|
||
|
||
switch(name) {
|
||
case 'startNode': onStartNode = cb || NULL_FUNC; break;
|
||
case 'endNode': onEndNode = cb || NULL_FUNC; break;
|
||
case 'text': case 'textNode': onTextNode = cb || NULL_FUNC; break;
|
||
case 'error': onError = cb || NULL_FUNC; break;
|
||
case 'cdata': onCDATA = cb || NULL_FUNC; break;
|
||
|
||
case 'unknownNS': onUnknownNS = cb; is_onUnknownNS = !!cb; break;
|
||
case 'attention': onAttention = cb; is_onAttention = !!cb; break; // <!XXXXX zzzz="eeee">
|
||
case 'question': onQuestion = cb; is_onQuestion = !!cb; break; // <? .... ?>
|
||
case 'comment': onComment = cb; is_onComment = !!cb; break;
|
||
};
|
||
};
|
||
|
||
this.ns = function(root, ns) {
|
||
if (!root) {
|
||
isNamespace = false;
|
||
defaultNS = null;
|
||
useNS = null;
|
||
return this;
|
||
};
|
||
|
||
if (!ns || typeof root !== 'string') {
|
||
throw Error('required args ns(string, object)');
|
||
};
|
||
|
||
isNamespace = !!(useNS = ns || null);
|
||
defaultNS = root || null;
|
||
|
||
return this;
|
||
};
|
||
|
||
this.write = function(chunk) {
|
||
if (typeof chunk !== 'string' || isParseStop) {
|
||
return;
|
||
};
|
||
|
||
if (!init) {
|
||
init = true;
|
||
reset();
|
||
};
|
||
|
||
xml = xml ? xml + chunk : chunk;
|
||
parse();
|
||
|
||
if (isParseStop && returnError) {
|
||
if (returnError) {
|
||
onError(returnError);
|
||
returnError = '';
|
||
};
|
||
};
|
||
|
||
if (indexStartXML > 0) {
|
||
xml = xml.substring(indexStartXML);
|
||
indexStartXML = 0;
|
||
};
|
||
|
||
return this;
|
||
};
|
||
|
||
this.end = function() {
|
||
if (returnError) {
|
||
onError(returnError);
|
||
returnError = '';
|
||
};
|
||
|
||
attrString = '';
|
||
init = false;
|
||
xml = '';
|
||
};
|
||
|
||
this.parse = function(xml) {
|
||
this.write(xml);
|
||
this.end();
|
||
};
|
||
this.staxParseXml = function(xml) {
|
||
staxParseWithEvents.call(this, xml);
|
||
};
|
||
|
||
this.stop = function() {
|
||
isParseStop = true;
|
||
};
|
||
|
||
if (config) {
|
||
this.setup(config);
|
||
};
|
||
|
||
// -----------------------------------------------------
|
||
|
||
var nodeParseAttrResult; // null - кеш пустой, true - атрибутов нет, {...} - карта атрибутов
|
||
var nodeParseAttrSize = 0; // число элементов nodeParseAttrMap
|
||
var nodeParseAttrMap = ['','','','','','','','','','']; // карта атрибутов. четные индексы "имя", не четные "значение"
|
||
var nodeParseHasNS = false;
|
||
var nodeParseName; // имя ноды
|
||
|
||
// разбор ноды <nodeName ...> или <nodeName .../>
|
||
// на вход indexStart = xml.indexOf('<');
|
||
// return xml.indexOf('>', ixNameStart);
|
||
function parseNode(indexStart) {
|
||
var ixNameStart = +indexStart + 1; // позиция первого сивола имени
|
||
var ixNameEnd; // позиция последнего + 1 сивола имени
|
||
var attrName;
|
||
|
||
var i = ixNameStart;
|
||
var l = xml.length;
|
||
var w;
|
||
|
||
var iE = xml.indexOf('>', ixNameStart);
|
||
var iR;
|
||
|
||
if (iE === -1) { // не полный xml. дальнейший парсинг бессмыслен
|
||
returnError = '#1901 invalid node'; // не полный xml
|
||
return -1;
|
||
};
|
||
|
||
nodeParseAttrResult = null;
|
||
nodeParseAttrSize = 0;
|
||
nodeParseHasNS = false;
|
||
nodeParseName = '';
|
||
|
||
if (i >= l) {
|
||
returnError = '#4952 invalid node'; // не полный xml
|
||
return -1;
|
||
};
|
||
|
||
w = xml.charCodeAt(i);
|
||
if (!(w > 96 && w < 123 || w > 64 && w < 91 || w === 95 || w === 58)) { // char 95"_" 58":"
|
||
returnError = '#4940 first char <nodeName .../>';
|
||
isParseStop = true; // дальнейший разбор невозможен
|
||
return -1;
|
||
};
|
||
|
||
while(true) {
|
||
if (++i >= l) {
|
||
returnError = '#4950 invalid node'; // не полный xml
|
||
return -1; // errorParse
|
||
};
|
||
|
||
w = xml.charCodeAt(i);
|
||
|
||
if (w > 96 && w < 123 || w > 64 && w < 91 || w > 47 && w < 59 || w === 45 || w === 46 || w === 95) {
|
||
continue; // символы имени тега только латиница
|
||
};
|
||
|
||
if (w === 32 || w === 9 || w === 10 || w === 11 || w === 12 || w === 13) { // \f\n\r\t\v пробел
|
||
nodeParseName = xml.substring(ixNameStart, ixNameEnd = i);
|
||
break;
|
||
};
|
||
|
||
if (w === 62 /* ">" */) { // тег закрылся, атрибутов нет
|
||
nodeParseName = xml.substring(ixNameStart, ixNameEnd = i);
|
||
return i;
|
||
};
|
||
|
||
if (w === 47 /* "/" */) {
|
||
ixNameEnd = i;
|
||
w = xml.charCodeAt(++i);
|
||
|
||
if (w === 62) {
|
||
nodeParseName = xml.substring(ixNameStart, ixNameEnd);
|
||
return i;
|
||
};
|
||
returnError = '#0320 invalid node .../>?';
|
||
isParseStop = true; // дальнейший разбор невозможен
|
||
return -1;
|
||
};
|
||
|
||
returnError = '#5347 invalid nodeName';
|
||
isParseStop = true; // дальнейший разбор невозможен
|
||
return -1;
|
||
};
|
||
|
||
i += 1; // первый сивол пробел его пропускаем
|
||
|
||
while(true) {
|
||
iR = xml.indexOf('=', i);
|
||
|
||
if (iR > iE || iR === -1) {
|
||
break;
|
||
};
|
||
|
||
attrName = xml.substring(i, iR);
|
||
|
||
if (isNamespace) {
|
||
attrName = attrName.trim();
|
||
if (attrName.charCodeAt(0) === 120 && attrName.substr(0, 6) === 'xmlns') {
|
||
nodeParseHasNS = true;
|
||
};
|
||
};
|
||
|
||
nodeParseAttrMap[nodeParseAttrSize++] = attrName; // имя атрибута
|
||
|
||
w = xml.charCodeAt(++iR);
|
||
|
||
while(w === 32 || w === 9 || w === 10 || w === 11 || w === 12 || w === 13) { // \f\n\r\t\v
|
||
w = xml.charCodeAt(++iR);
|
||
};
|
||
|
||
if (w === 34) {
|
||
i = xml.indexOf('"', iR + 1);
|
||
} else {
|
||
i = xml.indexOf('\'', iR + 1);
|
||
};
|
||
|
||
if (i === -1) {
|
||
returnError = '#5858 invalid node'; // не полный xml
|
||
return -1;
|
||
};
|
||
|
||
nodeParseAttrMap[nodeParseAttrSize++] = xml.substring(iR + 1, i); // значение атрибута
|
||
i += 1;
|
||
|
||
if (i === iE) {
|
||
break;
|
||
};
|
||
|
||
if (i > iE) {
|
||
iE = xml.indexOf('>', i);
|
||
if (iE === -1) {
|
||
returnError = '#0901 invalid node'; // не полный xml
|
||
return -1;
|
||
};
|
||
};
|
||
|
||
if (iE - i < 4) {
|
||
break;
|
||
};
|
||
};
|
||
|
||
return iE;
|
||
};
|
||
|
||
function upNSMATRIX() {
|
||
var hasNewMatrix;
|
||
var newalias;
|
||
var alias;
|
||
var value;
|
||
var name;
|
||
var j;
|
||
|
||
if (!nodeParseAttrSize) {
|
||
return;
|
||
};
|
||
|
||
for (j = 0; j < nodeParseAttrSize; j += 2) {
|
||
name = nodeParseAttrMap[j];
|
||
|
||
if (name !== 'xmlns') {
|
||
if (name.charCodeAt(0) !== 120 || name.substr(0, 6) !== 'xmlns:') {
|
||
continue;
|
||
};
|
||
newalias = name.substr(6);
|
||
} else {
|
||
newalias = 'xmlns';
|
||
};
|
||
|
||
|
||
value = nodeParseAttrMap[j + 1];
|
||
//alias = useNS[isAutoEntity ? value : entityDecode(value)];
|
||
alias = useNS[entityDecode(value)];
|
||
|
||
if (is_onUnknownNS && !alias) {
|
||
alias = onUnknownNS(value);
|
||
};
|
||
|
||
if (alias) {
|
||
if (nsmatrix[newalias] !== alias) {
|
||
if (!hasNewMatrix) {
|
||
nsmatrix = cloneMatrixNS(nsmatrix);
|
||
hasNewMatrix = true;
|
||
};
|
||
nsmatrix[newalias] = alias;
|
||
};
|
||
|
||
continue;
|
||
};
|
||
|
||
if (nsmatrix[newalias]) {
|
||
if (!hasNewMatrix) {
|
||
nsmatrix = cloneMatrixNS(nsmatrix);
|
||
hasNewMatrix = true;
|
||
};
|
||
nsmatrix[newalias] = false;
|
||
};
|
||
};
|
||
};
|
||
|
||
function getAttrs() {
|
||
if (nodeParseAttrResult !== null) {
|
||
return nodeParseAttrResult;
|
||
};
|
||
|
||
if (nodeParseAttrSize === 0) {
|
||
return nodeParseAttrResult = true;
|
||
};
|
||
|
||
var xmlnsAlias;
|
||
var nsName;
|
||
var iQ;
|
||
|
||
var attrs = {};
|
||
var value;
|
||
var name;
|
||
var j;
|
||
|
||
|
||
if (isNamespace) {
|
||
xmlnsAlias = nsmatrix.xmlns;
|
||
};
|
||
|
||
for (j = 0; j < nodeParseAttrSize; j++) {
|
||
name = isNamespace ? nodeParseAttrMap[j] : nodeParseAttrMap[j].trim();
|
||
|
||
if (isNamespace) {
|
||
iQ = name.indexOf(':');
|
||
if (iQ !== -1) {
|
||
nsName = nsmatrix[name.substring(0, iQ)];
|
||
if (!nsName || nsName === 'xmlns') {
|
||
continue;
|
||
};
|
||
name = xmlnsAlias !== nsName ? nsName + name.substr(iQ) : name.substr(iQ + 1);
|
||
};
|
||
};
|
||
|
||
value = nodeParseAttrMap[++j];
|
||
if (isAutoEntity) {
|
||
value = entityDecode(value);
|
||
};
|
||
|
||
attrs[name] = value;
|
||
};
|
||
|
||
return nodeParseAttrResult = attrs;
|
||
};
|
||
|
||
function getStringNode() { // вернет исходную строку узла
|
||
return xml.substring(stringNodePosStart, stringNodePosEnd);
|
||
};
|
||
|
||
|
||
var parseStackMatrixNS = [];
|
||
var parseStackNodes = [];
|
||
var stopIndexNS = 0;
|
||
|
||
|
||
function parse() {
|
||
// разбор идет по элементам (тег, текст cdata, ...).
|
||
// элемент должен быть целиком в памяти
|
||
|
||
var _nsmatrix;
|
||
var isTagStart = false;
|
||
var isTagEnd = false;
|
||
//var nodeBody;
|
||
var stopEmit; // используется при разборе "namespace" . если встретился неизвестное пространство то события не генерируются
|
||
var nodeName;
|
||
var xmlns;
|
||
var iD;
|
||
var iQ;
|
||
var w;
|
||
var i; // number
|
||
|
||
returnError = null; // сброс ошибки неудачного разбора
|
||
|
||
while(indexStartXML !== -1) {
|
||
stopEmit = stopIndexNS > 0;
|
||
|
||
// поиск начала тега
|
||
if (xml.charCodeAt(indexStartXML) === 60) { // "<"
|
||
i = indexStartXML;
|
||
} else {
|
||
i = xml.indexOf('<', indexStartXML);
|
||
};
|
||
|
||
if (i === -1) { // узел не найден. повторим попытку на след. write
|
||
if (parseStackNodes.length) {
|
||
returnError = 'unexpected end parse';
|
||
return;
|
||
};
|
||
|
||
// --- нужно подумать как обрабатывать начало файла ---
|
||
// if (indexStartXML === 0) { // разбор еше не начат. возможно это начало файла. мусор до первого тега игнор
|
||
// returnError = 'missing first tag';
|
||
// return;
|
||
// };
|
||
|
||
return;
|
||
};
|
||
|
||
if (indexStartXML !== i && !stopEmit) { // все что до тега это текст
|
||
var text = xml.substring(indexStartXML, i);
|
||
indexStartXML = i; // до этой позиции разбор завершен
|
||
|
||
onTextNode(isAutoEntity ? entityDecode(text) : text);
|
||
if (isParseStop) {
|
||
return;
|
||
};
|
||
};
|
||
|
||
// ELEMENT
|
||
// ---------------------------------------------
|
||
|
||
w = xml.charCodeAt(i + 1);
|
||
|
||
if (w === 33) { // 33 == "!"
|
||
var wNext = xml.charCodeAt(i + 2);
|
||
|
||
// CDATA
|
||
// ---------------------------------------------
|
||
if (wNext === 91 && xml.substr(i + 3, 6) === 'CDATA[') { // 91 == "["
|
||
var indexStartCDATA = i + 9;
|
||
var indexEndCDATA = xml.indexOf(']]>', indexStartCDATA);
|
||
if (indexEndCDATA === -1) {
|
||
returnError = 'cdata, not found ...]]>'; // не закрыт CDATA. повторим попытку на след. write
|
||
return;
|
||
};
|
||
|
||
indexStartXML = indexEndCDATA + 3;
|
||
|
||
if (!stopEmit) {
|
||
onCDATA(xml.substring(indexStartCDATA, indexEndCDATA));
|
||
if (isParseStop) {
|
||
return;
|
||
};
|
||
};
|
||
continue;
|
||
};
|
||
|
||
|
||
// COMMENT
|
||
// ---------------------------------------------
|
||
if (wNext === 45 && xml.charCodeAt(i + 3) === 45) { // 45 == "-"
|
||
var indexStartComment = i + 4;
|
||
var indexEndComment = xml.indexOf('-->', indexStartComment);
|
||
if (indexEndComment === -1) {
|
||
returnError = 'expected -->'; // не закрыт комментарий. повторим попытку на след. write
|
||
return;
|
||
};
|
||
|
||
indexStartXML = indexEndComment + 3;
|
||
|
||
if (is_onComment && !stopEmit) {
|
||
var commentText = xml.substring(indexStartComment, indexEndComment);
|
||
onComment(isAutoEntity ? entityDecode(commentText) : commentText);
|
||
if (isParseStop) {
|
||
return;
|
||
};
|
||
};
|
||
continue;
|
||
};
|
||
|
||
// ATTENTION
|
||
// ---------------------------------------------
|
||
{
|
||
var indexStartAttention = i + 1;
|
||
var indexEndAttention = xml.indexOf('>', indexStartAttention);
|
||
if (indexEndAttention === -1) {
|
||
returnError = 'expected attention ...>'; // повторим попытку на след. write
|
||
return;
|
||
};
|
||
|
||
indexStartXML = indexEndAttention + 1;
|
||
|
||
if (is_onAttention && !stopEmit) {
|
||
onAttention(xml.substring(i, indexStartXML)); // весь тег, так как не придумал api
|
||
if (isParseStop) {
|
||
return;
|
||
};
|
||
};
|
||
};
|
||
|
||
continue;
|
||
};
|
||
|
||
// QUESTION
|
||
// ---------------------------------------------
|
||
if (w === 63) { // "?"
|
||
var indexEndQuestion = xml.indexOf('?>', i);
|
||
if (indexEndQuestion === -1) { // error
|
||
returnError = 'expected question ...?>'; // повторим попытку на след. write
|
||
return;
|
||
};
|
||
|
||
indexStartXML = indexEndQuestion + 2;
|
||
|
||
if (is_onQuestion) {
|
||
onQuestion(xml.substring(i, indexStartXML)); // весь тег, так как не придумал api
|
||
if (isParseStop) {
|
||
return;
|
||
};
|
||
};
|
||
continue;
|
||
};
|
||
|
||
|
||
// NODE ELEMENT
|
||
// ---------------------------------------------
|
||
|
||
if (w === 47) { // </...
|
||
var indexEndNode = xml.indexOf('>', i + 1);
|
||
if (indexEndNode === -1) { // error ...> // не нашел знак закрытия тега
|
||
returnError = 'unclosed tag'; // повторим попытку на след. write
|
||
return;
|
||
};
|
||
|
||
isTagStart = false;
|
||
isTagEnd = true;
|
||
|
||
// проверяем что тег должен быть закрыт тот-же что и открывался
|
||
if (!parseStackNodes.length) {
|
||
returnError = 'close tag, requires open tag';
|
||
isParseStop = true; // дальнейший разбор невозможен
|
||
return;
|
||
};
|
||
|
||
nodeName = parseStackNodes.pop();
|
||
iQ = i + 2 + nodeName.length;
|
||
|
||
if (nodeName !== xml.substring(i + 2, iQ)) {
|
||
returnError = 'close tag, not equal to the open tag';
|
||
isParseStop = true; // дальнейший разбор невозможен
|
||
return;
|
||
};
|
||
|
||
// проверим что в закрываюшем теге нет лишнего
|
||
for(; iQ < indexEndNode; iQ++) {
|
||
var wNext = xml.charCodeAt(iQ);
|
||
if (wNext === 32 || wNext === 9 || wNext === 10 || wNext === 11 || wNext === 12 || wNext === 13) { // \f\n\r\t\v
|
||
continue;
|
||
};
|
||
|
||
returnError = 'close tag, unallowable char';
|
||
isParseStop = true; // дальнейший разбор невозможен
|
||
return;
|
||
};
|
||
|
||
indexStartXML = indexEndNode + 1;
|
||
|
||
} else {
|
||
var indexEndNode = parseNode(i);
|
||
if (indexEndNode === -1) { // error ...> // не нашел знак закрытия тега
|
||
returnError = returnError || 'unclosed tag'; // повторим попытку на след. write
|
||
return;
|
||
};
|
||
|
||
isTagStart = true;
|
||
isTagEnd = xml.charCodeAt(indexEndNode - 1) === 47;
|
||
nodeName = nodeParseName;
|
||
|
||
if (!isTagEnd) {
|
||
parseStackNodes.push(nodeName);
|
||
};
|
||
|
||
indexStartXML = indexEndNode + 1;
|
||
};
|
||
|
||
|
||
if (isNamespace) {
|
||
if (stopEmit) { // потомки неизвестного пространства имен
|
||
if (isTagEnd) {
|
||
if (!isTagStart) {
|
||
if (--stopIndexNS === 0) {
|
||
nsmatrix = parseStackMatrixNS.pop();
|
||
};
|
||
};
|
||
|
||
} else {
|
||
stopIndexNS += 1;
|
||
};
|
||
continue;
|
||
};
|
||
|
||
// добавляем в parseStackMatrixNS только если !isTagEnd, иначе сохраняем контекст пространств в переменной
|
||
_nsmatrix = nsmatrix;
|
||
if (!isTagEnd) {
|
||
parseStackMatrixNS.push(nsmatrix);
|
||
};
|
||
|
||
if (isTagStart && nodeParseHasNS) { // есть подозрение на xmlns // && (nodeParseAttrResult === null)
|
||
upNSMATRIX();
|
||
};
|
||
|
||
iD = nodeName.indexOf(':');
|
||
if (iD !== -1) {
|
||
xmlns = nsmatrix[nodeName.substring(0, iD)];
|
||
nodeName = nodeName.substr(iD + 1);
|
||
|
||
} else {
|
||
xmlns = nsmatrix.xmlns;
|
||
};
|
||
|
||
if (!xmlns) {
|
||
// элемент неизвестного пространства имен
|
||
if (isTagEnd) {
|
||
nsmatrix = _nsmatrix; // так как тут всегда isTagStart
|
||
} else {
|
||
stopIndexNS = 1; // первый элемент для которого не определено пространство имен
|
||
};
|
||
continue;
|
||
};
|
||
|
||
nodeName = xmlns + ':' + nodeName;
|
||
};
|
||
|
||
stringNodePosStart = i; // stringNodePosStart, stringNodePosEnd - для ручного разбора getStringNode()
|
||
stringNodePosEnd = indexStartXML;
|
||
|
||
if (isTagStart) {
|
||
onStartNode(nodeName, getAttrs, isTagEnd, getStringNode);
|
||
if (isParseStop) {
|
||
return;
|
||
};
|
||
};
|
||
|
||
if (isTagEnd) {
|
||
onEndNode(nodeName, isTagStart, getStringNode);
|
||
if (isParseStop) {
|
||
return;
|
||
};
|
||
|
||
if (isNamespace) {
|
||
if (isTagStart) {
|
||
nsmatrix = _nsmatrix;
|
||
} else {
|
||
nsmatrix = parseStackMatrixNS.pop();
|
||
};
|
||
};
|
||
};
|
||
};
|
||
};
|
||
|
||
var staxStream, staxStateisTagStart, staxStateisTagEnd, staxStatenodeName, staxStateeventType, staxStatetext, staxStatedepth;
|
||
function staxInit(_xml) {
|
||
init = true;
|
||
reset();
|
||
staxCleanState();
|
||
|
||
var xmls = [_xml];
|
||
staxStream = {read: function(){return xmls.pop();}};
|
||
xml = staxStream.read();
|
||
}
|
||
function staxCleanState() {
|
||
staxStateisTagStart = false;
|
||
staxStateisTagEnd = false;
|
||
staxStatenodeName = null;
|
||
|
||
staxStateeventType = null;
|
||
staxStatetext = null;
|
||
staxStatedepth = 0;
|
||
|
||
returnError = null; // сброс ошибки неудачного разбора
|
||
}
|
||
function staxHasNext() {
|
||
return !isParseStop;
|
||
}
|
||
function staxGetEventType() {
|
||
return staxStateeventType;
|
||
}
|
||
function staxGetName() {
|
||
return staxStatenodeName;
|
||
}
|
||
function staxGetText() {
|
||
return staxStatetext;
|
||
}
|
||
function staxGetDepth() {
|
||
return staxStatedepth;
|
||
}
|
||
function staxIsEmptyNode() {
|
||
return staxStateisTagStart && staxStateisTagEnd;
|
||
}
|
||
function staxGetError() {
|
||
return returnError;
|
||
}
|
||
|
||
function staxParseWithEvents(xml) {
|
||
this.staxInit(xml);
|
||
|
||
while (staxHasNext()) {
|
||
var eventType = staxNext();
|
||
switch (eventType) {
|
||
case EasySAXEvent.START_ELEMENT:
|
||
onStartNode(staxGetName(), getAttrs, staxStateisTagEnd, getStringNode);
|
||
break;
|
||
case EasySAXEvent.CHARACTERS:
|
||
onTextNode(staxGetText());
|
||
break;
|
||
case EasySAXEvent.END_ELEMENT:
|
||
onEndNode(staxGetName(), staxStateisTagStart, getStringNode);
|
||
break;
|
||
case EasySAXEvent.CDATA:
|
||
onCDATA(staxGetText());
|
||
break;
|
||
case EasySAXEvent.Comment:
|
||
if (is_onComment) {
|
||
onComment(staxGetText());
|
||
}
|
||
break;
|
||
case EasySAXEvent.Attention:
|
||
if (is_onAttention) {
|
||
onAttention(staxGetText());
|
||
}
|
||
break;
|
||
case EasySAXEvent.Question:
|
||
if (is_onQuestion) {
|
||
onQuestion(staxGetText());
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
this.staxEnd();
|
||
}
|
||
|
||
function staxNext() {
|
||
// разбор идет по элементам (тег, текст cdata, ...).
|
||
// элемент должен быть целиком в памяти
|
||
|
||
// var _nsmatrix;
|
||
// var isTagStart = false;
|
||
// var isTagEnd = false;
|
||
// //var nodeBody;
|
||
// var stopEmit; // используется при разборе "namespace" . если встретился неизвестное пространство то события не генерируются
|
||
// var nodeName;
|
||
// var iD;
|
||
var iQ;
|
||
var w;
|
||
var i; // number
|
||
|
||
if (staxStateisTagEnd) {
|
||
if (staxStateeventType === EasySAXEvent.START_ELEMENT) {
|
||
staxStateeventType = EasySAXEvent.END_ELEMENT;
|
||
return staxStateeventType;
|
||
}
|
||
staxStatedepth--;
|
||
};
|
||
|
||
staxStateeventType = EasySAXEvent.Unknown;
|
||
|
||
// поиск начала тега
|
||
if (xml.charCodeAt(indexStartXML) === 60) { // "<"
|
||
i = indexStartXML;
|
||
} else {
|
||
i = xml.indexOf('<', indexStartXML);
|
||
};
|
||
|
||
if (i === -1) { // узел не найден. повторим попытку на след. write
|
||
// --- нужно подумать как обрабатывать начало файла ---
|
||
// if (indexStartXML === 0) { // разбор еше не начат. возможно это начало файла. мусор до первого тега игнор
|
||
// returnError = 'missing first tag';
|
||
// return;
|
||
// };
|
||
|
||
if (indexStartXML > 0) {
|
||
xml = xml.substring(indexStartXML);
|
||
indexStartXML = 0;
|
||
};
|
||
var chunk = staxStream.read();
|
||
if(chunk) {
|
||
xml = xml + chunk;
|
||
|
||
// поиск начала тега
|
||
if (xml.charCodeAt(indexStartXML) === 60) { // "<"
|
||
i = indexStartXML;
|
||
} else {
|
||
i = xml.indexOf('<', indexStartXML);
|
||
};
|
||
}
|
||
|
||
if (i === -1) {
|
||
if (parseStackNodes.length) {
|
||
returnError = 'unexpected end parse';
|
||
};
|
||
if (returnError) {
|
||
onError(returnError);
|
||
returnError = '';
|
||
};
|
||
isParseStop = true;
|
||
return staxStateeventType;
|
||
}
|
||
};
|
||
|
||
if (indexStartXML !== i) { // все что до тега это текст
|
||
var text = xml.substring(indexStartXML, i);
|
||
indexStartXML = i; // до этой позиции разбор завершен
|
||
|
||
staxStateeventType = EasySAXEvent.CHARACTERS;
|
||
staxStatetext = isAutoEntity ? entityDecode(text) : text;
|
||
return staxStateeventType;
|
||
};
|
||
|
||
// ELEMENT
|
||
// ---------------------------------------------
|
||
|
||
w = xml.charCodeAt(i + 1);
|
||
|
||
if (w === 33) { // 33 == "!"
|
||
var wNext = xml.charCodeAt(i + 2);
|
||
|
||
// CDATA
|
||
// ---------------------------------------------
|
||
if (wNext === 91 && xml.substr(i + 3, 6) === 'CDATA[') { // 91 == "["
|
||
var indexStartCDATA = i + 9;
|
||
var indexEndCDATA = xml.indexOf(']]>', indexStartCDATA);
|
||
if (indexEndCDATA === -1) {
|
||
returnError = 'cdata, not found ...]]>'; // не закрыт CDATA. повторим попытку на след. write
|
||
isParseStop = true;
|
||
return staxStateeventType;
|
||
};
|
||
|
||
indexStartXML = indexEndCDATA + 3;
|
||
staxStateeventType = EasySAXEvent.CDATA;
|
||
staxStatetext = xml.substring(indexStartCDATA, indexEndCDATA);
|
||
return staxStateeventType;
|
||
};
|
||
|
||
|
||
// COMMENT
|
||
// ---------------------------------------------
|
||
if (wNext === 45 && xml.charCodeAt(i + 3) === 45) { // 45 == "-"
|
||
var indexStartComment = i + 4;
|
||
var indexEndComment = xml.indexOf('-->', indexStartComment);
|
||
if (indexEndComment === -1) {
|
||
returnError = 'expected -->'; // не закрыт комментарий. повторим попытку на след. write
|
||
isParseStop = true;
|
||
return staxStateeventType;
|
||
};
|
||
|
||
indexStartXML = indexEndComment + 3;
|
||
staxStateeventType = EasySAXEvent.Comment;
|
||
staxStatetext = xml.substring(indexStartComment, indexEndComment);
|
||
return staxStateeventType;
|
||
};
|
||
|
||
// ATTENTION
|
||
// ---------------------------------------------
|
||
{
|
||
var indexStartAttention = i + 1;
|
||
var indexEndAttention = xml.indexOf('>', indexStartAttention);
|
||
if (indexEndAttention === -1) {
|
||
returnError = 'expected attention ...>'; // повторим попытку на след. write
|
||
isParseStop = true;
|
||
return staxStateeventType;
|
||
};
|
||
|
||
indexStartXML = indexEndAttention + 1;
|
||
staxStateeventType = EasySAXEvent.Attention;
|
||
staxStatetext = xml.substring(i, indexStartXML);
|
||
return staxStateeventType;
|
||
};
|
||
|
||
return staxStateeventType;
|
||
};
|
||
|
||
// QUESTION
|
||
// ---------------------------------------------
|
||
if (w === 63) { // "?"
|
||
var indexEndQuestion = xml.indexOf('?>', i);
|
||
if (indexEndQuestion === -1) { // error
|
||
returnError = 'expected question ...?>'; // повторим попытку на след. write
|
||
isParseStop = true;
|
||
return staxStateeventType;
|
||
};
|
||
|
||
indexStartXML = indexEndQuestion + 2;
|
||
staxStateeventType = EasySAXEvent.Question;
|
||
staxStatetext = xml.substring(i, indexStartXML);
|
||
return staxStateeventType;
|
||
};
|
||
|
||
|
||
// NODE ELEMENT
|
||
// ---------------------------------------------
|
||
|
||
if (w === 47) { // </...
|
||
var indexEndNode = xml.indexOf('>', i + 1);
|
||
if (indexEndNode === -1) { // error ...> // не нашел знак закрытия тега
|
||
returnError = 'unclosed tag'; // повторим попытку на след. write
|
||
isParseStop = true;
|
||
return staxStateeventType;
|
||
};
|
||
|
||
staxStateisTagStart = false;
|
||
staxStateisTagEnd = true;
|
||
|
||
// проверяем что тег должен быть закрыт тот-же что и открывался
|
||
if (!parseStackNodes.length) {
|
||
returnError = 'close tag, requires open tag';
|
||
isParseStop = true; // дальнейший разбор невозможен
|
||
return staxStateeventType;
|
||
};
|
||
|
||
staxStatenodeName = parseStackNodes.pop();
|
||
iQ = i + 2 + staxStatenodeName.length;
|
||
|
||
if (staxStatenodeName !== xml.substring(i + 2, iQ)) {
|
||
returnError = 'close tag, not equal to the open tag';
|
||
isParseStop = true; // дальнейший разбор невозможен
|
||
return staxStateeventType;
|
||
};
|
||
|
||
// проверим что в закрываюшем теге нет лишнего
|
||
for(; iQ < indexEndNode; iQ++) {
|
||
var wNext = xml.charCodeAt(iQ);
|
||
if (wNext === 32 || wNext === 9 || wNext === 10 || wNext === 11 || wNext === 12 || wNext === 13) { // \f\n\r\t\v
|
||
continue;
|
||
};
|
||
|
||
returnError = 'close tag, unallowable char';
|
||
isParseStop = true; // дальнейший разбор невозможен
|
||
return staxStateeventType;
|
||
};
|
||
|
||
indexStartXML = indexEndNode + 1;
|
||
|
||
} else {
|
||
var indexEndNode = parseNode(i);
|
||
if (indexEndNode === -1) { // error ...> // не нашел знак закрытия тега
|
||
returnError = returnError || 'unclosed tag'; // повторим попытку на след. write
|
||
isParseStop = true;
|
||
return staxStateeventType;
|
||
};
|
||
|
||
staxStateisTagStart = true;
|
||
staxStateisTagEnd = xml.charCodeAt(indexEndNode - 1) === 47;
|
||
staxStatenodeName = nodeParseName;
|
||
|
||
if (!staxStateisTagEnd) {
|
||
parseStackNodes.push(staxStatenodeName);
|
||
};
|
||
|
||
indexStartXML = indexEndNode + 1;
|
||
};
|
||
|
||
if (staxStateisTagStart) {
|
||
staxStatedepth++;
|
||
staxStateeventType = EasySAXEvent.START_ELEMENT;
|
||
return staxStateeventType;
|
||
};
|
||
if (staxStateisTagEnd) {
|
||
staxStateeventType = EasySAXEvent.END_ELEMENT;
|
||
return staxStateeventType;
|
||
};
|
||
}
|
||
|
||
this.staxInit = staxInit;
|
||
this.staxHasNext = staxHasNext;
|
||
this.staxNext = staxNext;
|
||
this.staxGetEventType = staxGetEventType;
|
||
this.staxGetName = staxGetName;
|
||
this.staxGetAttrs = getAttrs;
|
||
this.staxGetText = staxGetText;
|
||
this.staxGetDepth = staxGetDepth;
|
||
this.staxIsEmptyNode = staxIsEmptyNode;
|
||
this.staxGetError = staxGetError;
|
||
this.staxEnd = this.end;
|
||
};
|
||
|
||
function StaxParser(xml, rels, context) {
|
||
this.xml = xml;
|
||
this.index = 0;
|
||
this.length = xml.length;
|
||
this.rels = rels;
|
||
this.context = context;
|
||
|
||
this.isTagStart = null;
|
||
this.isInAttr = false;
|
||
this.isTagEnd = null;
|
||
this.eventType = null;
|
||
this.name = null;
|
||
this.text = null;
|
||
this.value = null;
|
||
this.stop = false;
|
||
this.depth = 0;
|
||
}
|
||
StaxParser.prototype.hasNext = function() {
|
||
return !this.stop;
|
||
};
|
||
StaxParser.prototype.next = function() {
|
||
if (this.isInAttr) {
|
||
this.SkipAttributes();
|
||
}
|
||
if (this.isTagEnd) {
|
||
if (this.eventType === EasySAXEvent.START_ELEMENT) {
|
||
this.eventType = EasySAXEvent.END_ELEMENT;
|
||
return this.eventType;
|
||
}
|
||
this.depth--;
|
||
}
|
||
|
||
this.isInAttr = false;
|
||
this.eventType = EasySAXEvent.Unknown;
|
||
this.isTagStart = this.isTagEnd = this.name = this.text = this.value = null;
|
||
|
||
var xml = this.xml;
|
||
var i = this.index;
|
||
|
||
if (xml.charCodeAt(i) !== 60) { // '<'
|
||
i = xml.indexOf('<', i);
|
||
if (i === -1) {
|
||
this.stop = true;
|
||
return;
|
||
}
|
||
this.eventType = EasySAXEvent.CHARACTERS;
|
||
this.text = xml.substring(this.index, i);
|
||
this.index = i;
|
||
return this.eventType;
|
||
}
|
||
|
||
// ELEMENT
|
||
// ---------------------------------------------
|
||
var w = xml.charCodeAt(i + 1);
|
||
if (w === 33) { // 33 == "!"
|
||
if (i + 3 < this.length && xml.charCodeAt(i + 2) === 45 && xml.charCodeAt(i + 3) === 45) { // COMMENT
|
||
this.index = xml.indexOf('-->', i) + 3;
|
||
} else { // CDATA
|
||
this.index = xml.indexOf(']]>', i) + 3;
|
||
}
|
||
if (this.index === 2) { // -1 + 3 = 2
|
||
this.stop = true;
|
||
}
|
||
this.eventType = EasySAXEvent.Unknown;
|
||
return this.eventType;
|
||
}
|
||
// QUESTION
|
||
// ---------------------------------------------
|
||
if (w === 63) { // "?"
|
||
this.index = xml.indexOf('>', i);
|
||
return this.eventType;
|
||
}
|
||
// NODE ELEMENT
|
||
// ---------------------------------------------
|
||
var indexEndNode;
|
||
if (w !== 47) { // </...
|
||
indexEndNode = this.parseNode(i);
|
||
if (indexEndNode === -1) { // error ...> // не нашел знак закрытия тега
|
||
this.stop = true;
|
||
return this.eventType;
|
||
}
|
||
this.isTagStart = true;
|
||
this.isInAttr = true;
|
||
this.isTagEnd = false;
|
||
// this.isTagEnd = this.xml.charCodeAt(indexEndNode - 1) === 47;
|
||
this.eventType = EasySAXEvent.START_ELEMENT;
|
||
this.depth++;
|
||
this.index = indexEndNode;
|
||
} else {
|
||
//todo close tag name not used. don't parse for performance reason
|
||
indexEndNode = this.xml.indexOf('>', i + 1);
|
||
if (indexEndNode === -1) { // error ...> // не нашел знак закрытия тега
|
||
this.stop = true;
|
||
return this.eventType;
|
||
}
|
||
this.isTagStart = false;
|
||
this.isTagEnd = true;
|
||
this.eventType = EasySAXEvent.END_ELEMENT;
|
||
this.index = indexEndNode + 1;
|
||
}
|
||
return this.eventType;
|
||
};
|
||
StaxParser.prototype.parseNode = function(indexStart) {
|
||
var xml = this.xml;
|
||
var len = this.length;
|
||
var ixNameStart = indexStart + 1;
|
||
|
||
var i = ixNameStart;
|
||
var w;
|
||
while (i < len) {
|
||
w = xml.charCodeAt(i);
|
||
if ((w | 32) > 96 && (w | 32) < 123 || // letters
|
||
(w > 47 && w < 58) || // digits
|
||
w === 45 || w === 46 || w === 58 || w === 95) { // - . :_
|
||
++i;
|
||
continue;
|
||
}
|
||
// whitespace (space, tab, LF, VT, FF, CR)
|
||
if (w === 32 || (w >= 9 && w <= 13)) {
|
||
this.name = xml.substring(ixNameStart, i);
|
||
return i;
|
||
}
|
||
// tag end or self-closing slash
|
||
if (w === 62 /* > */ || w === 47 /* / */) {
|
||
this.name = xml.substring(ixNameStart, i);
|
||
return i;
|
||
}
|
||
// invalid char
|
||
return -1;
|
||
}
|
||
return -1;
|
||
};
|
||
StaxParser.prototype.MoveToNextAttribute = function() {
|
||
var xml = this.xml;
|
||
var len = this.length;
|
||
var i = this.index;
|
||
|
||
while (i < len) {
|
||
var w = xml.charCodeAt(i);
|
||
if (w === 61 /* '=' */ && i + 1 < len) {
|
||
// Extract attribute name (likely clean, trim only if needed)
|
||
var nameStart = this.index;
|
||
var nameEnd = i;
|
||
var rawName = xml.substring(nameStart, nameEnd);
|
||
|
||
// Fast quote detection
|
||
var quoteChar = xml.charCodeAt(i + 1);
|
||
var textStart = i + 2;
|
||
|
||
if (quoteChar === 34) { // '"'
|
||
i = xml.indexOf('"', textStart);
|
||
} else if (quoteChar === 39) { // "'"
|
||
i = xml.indexOf("'", textStart);
|
||
} else {
|
||
// Fallback for other quotes
|
||
i = xml.indexOf(xml.charAt(i + 1), textStart);
|
||
}
|
||
|
||
if (i !== -1) {
|
||
// Only trim if name has leading/trailing spaces
|
||
if (rawName.charCodeAt(0) === 32 || rawName.charCodeAt(nameEnd - nameStart - 1) === 32) {
|
||
this.name = rawName.trim();
|
||
} else {
|
||
this.name = rawName;
|
||
}
|
||
this.text = xml.substring(textStart, i);
|
||
this.index = i + 1;
|
||
return true;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
// whitespace (space, tab, LF, VT, FF, CR)
|
||
if (w === 32 || (w >= 9 && w <= 13)) {
|
||
++i;
|
||
continue;
|
||
}
|
||
if (w === 62 /* ">" */) {
|
||
this.index = i + 1;
|
||
this.isInAttr = false;
|
||
return false;
|
||
}
|
||
if (w === 47 /* "/" */ && i + 1 < len && xml.charCodeAt(i + 1) === 62) {
|
||
this.index = i + 2;
|
||
this.isInAttr = false;
|
||
this.isTagEnd = true;
|
||
return false;
|
||
}
|
||
++i;
|
||
}
|
||
this.stop = true;
|
||
this.index = i;
|
||
this.isInAttr = false;
|
||
return false;
|
||
};
|
||
StaxParser.prototype.GetAttributes = function() {
|
||
let attributes = {};
|
||
while (this.MoveToNextAttribute()) {
|
||
attributes[this.GetName()] = this.GetValue();
|
||
}
|
||
|
||
return attributes;
|
||
};
|
||
StaxParser.prototype.SkipAttributes = function() {
|
||
var xml = this.xml;
|
||
var i = xml.indexOf('>', this.index);
|
||
|
||
if (i === -1) {
|
||
this.stop = true;
|
||
return;
|
||
}
|
||
|
||
this.isTagEnd = xml.charCodeAt(i - 1) === 47; // '/'
|
||
this.isInAttr = false;
|
||
this.index = i + 1;
|
||
};
|
||
StaxParser.prototype.Read = function() {
|
||
var hasNext = this.hasNext();
|
||
this.next();
|
||
return hasNext;
|
||
};
|
||
StaxParser.prototype.ReadNextNode = function() {
|
||
var type = EasySAXEvent.Unknown;
|
||
while (EasySAXEvent.START_ELEMENT !== type && this.hasNext()) {
|
||
type = this.next();
|
||
}
|
||
return EasySAXEvent.START_ELEMENT === type;
|
||
};
|
||
StaxParser.prototype.ReadNextSiblingNode = function(depth) {
|
||
var targetDepth = depth + 1;
|
||
var type;
|
||
|
||
while (this.hasNext()) {
|
||
type = this.next();
|
||
var curDepth = this.depth;
|
||
|
||
if (curDepth < depth) {
|
||
break;
|
||
}
|
||
|
||
if (type === EasySAXEvent.START_ELEMENT && curDepth === targetDepth) {
|
||
return true;
|
||
}
|
||
|
||
if (type === EasySAXEvent.END_ELEMENT && curDepth === depth) {
|
||
return false;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
StaxParser.prototype.ReadTillEnd = function (opt_depth) {
|
||
var depth = opt_depth;
|
||
if (!depth) {
|
||
depth = this.depth;
|
||
}
|
||
var type = EasySAXEvent.Unknown;
|
||
while (this.hasNext()) {
|
||
type = this.next();
|
||
var curDepth = this.GetDepth();
|
||
if (curDepth < depth) {
|
||
break;
|
||
}
|
||
if (EasySAXEvent.END_ELEMENT === type && curDepth === depth)
|
||
break;
|
||
}
|
||
return true;
|
||
};
|
||
StaxParser.prototype.IsEmptyNode = function () {
|
||
return this.isTagStart && this.isTagEnd;
|
||
};
|
||
StaxParser.prototype.GetDepth = function() {
|
||
return this.depth;
|
||
};
|
||
StaxParser.prototype.GetName = function () {
|
||
return this.name;
|
||
// return this.ConvertToString(this.xml, this.nameStart, this.nameEnd);
|
||
};
|
||
StaxParser.prototype.GetNameNoNS = function () {
|
||
return this.GetNameFromNodeName(this.GetName());
|
||
};
|
||
StaxParser.prototype.GetValue = function () {
|
||
return this.text;
|
||
// return this.ConvertToString(this.xml, this.textStart, this.textEnd);
|
||
};
|
||
StaxParser.prototype.GetBool = function (val) {
|
||
return "1" === val || "true" === val || "t" === val || "on" === val;
|
||
};
|
||
StaxParser.prototype.GetInt = function (val, def, radix) {
|
||
var num = parseInt(val, radix);
|
||
return !isNaN(num) ? num : def;
|
||
};
|
||
StaxParser.prototype.GetUInt = function (val, def, radix) {
|
||
var num = parseInt(val, radix);
|
||
return !isNaN(num) && num >= 0 ? num : def;
|
||
};
|
||
StaxParser.prototype.GetDouble = function (val, def) {
|
||
var num = parseFloat(val);
|
||
return !isNaN(num) ? num : def;
|
||
};
|
||
StaxParser.prototype.GetDoubleOrNaN = function (val, def) {
|
||
if(val === "NaN") {
|
||
return NaN;
|
||
}
|
||
if (val === "INF") {
|
||
return Infinity;
|
||
}
|
||
return this.GetDouble(val, def);
|
||
};
|
||
StaxParser.prototype.GetValueBool = function () {
|
||
return this.GetBool(this.GetValue());
|
||
};
|
||
StaxParser.prototype.GetValueByte = function (def, radix) {
|
||
return this.GetValueUInt(def, radix);
|
||
};
|
||
StaxParser.prototype.GetValueSByte = function (def, radix) {
|
||
return this.GetValueInt(def, radix);
|
||
};
|
||
StaxParser.prototype.GetValueInt = function (def, radix) {
|
||
return this.GetInt(this.GetValue(), def, radix);
|
||
};
|
||
StaxParser.prototype.GetValueUInt = function (def, radix) {
|
||
return this.GetUInt(this.GetValue(), def, radix);
|
||
};
|
||
StaxParser.prototype.GetValueInt64 = function (def, radix) {
|
||
return this.GetValueInt(def, radix);
|
||
};
|
||
StaxParser.prototype.GetValueUInt64 = function (def, radix) {
|
||
return this.GetValueUInt(def, radix);
|
||
};
|
||
StaxParser.prototype.GetValueDouble = function (def) {
|
||
return this.GetDouble(this.GetValue(), def);
|
||
};
|
||
StaxParser.prototype.GetValueDoubleOrNaN = function (def) {
|
||
return this.GetDoubleOrNaN(this.GetValue(), def);
|
||
};
|
||
StaxParser.prototype.GetValueDecodeXml = function () {
|
||
return this.DecodeXml(this.text);
|
||
};
|
||
StaxParser.prototype.GetValueDecodeXmlExt = function () {
|
||
return this.GetValueDecodeXml();
|
||
};
|
||
StaxParser.prototype.DecodeXml = function (text) {
|
||
// Detect & and _xHHHH_ patterns
|
||
const len = text.length;
|
||
let firstSpecial = -1;
|
||
let i = 0;
|
||
|
||
for (i = 0; i < len; ++i) {
|
||
const c = text.charCodeAt(i);
|
||
if (c === 38 /* & */ || (c === 95 /* _ */ && i + 1 < len && text.charCodeAt(i + 1) === 120 /* x */)) {
|
||
firstSpecial = i;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (firstSpecial === -1) {
|
||
return text;
|
||
}
|
||
|
||
const result = [];
|
||
let lastCopied = 0;
|
||
for (i = firstSpecial; i < len; ++i) {
|
||
const ch = text.charCodeAt(i);
|
||
let entityLen = 0;
|
||
let decoded = null;
|
||
|
||
if (ch === 38) { // '&'
|
||
const nextChar = i + 1 < len ? text.charCodeAt(i + 1) : 0;
|
||
|
||
// < (4 chars)
|
||
if (nextChar === 108 && i + 3 < len && // 'l'
|
||
text.charCodeAt(i + 2) === 116 && // 't'
|
||
text.charCodeAt(i + 3) === 59) { // ';'
|
||
decoded = '<';
|
||
entityLen = 4;
|
||
}
|
||
// > (4 chars)
|
||
else if (nextChar === 103 && i + 3 < len && // 'g'
|
||
text.charCodeAt(i + 2) === 116 && // 't'
|
||
text.charCodeAt(i + 3) === 59) { // ';'
|
||
decoded = '>';
|
||
entityLen = 4;
|
||
}
|
||
// & (5 chars)
|
||
else if (nextChar === 97 && i + 4 < len && // 'a'
|
||
text.charCodeAt(i + 2) === 109 && // 'm'
|
||
text.charCodeAt(i + 3) === 112 && // 'p'
|
||
text.charCodeAt(i + 4) === 59) { // ';'
|
||
decoded = '&';
|
||
entityLen = 5;
|
||
}
|
||
// " or ' (6 chars)
|
||
else if (i + 5 < len) {
|
||
if (nextChar === 113 && // 'q'
|
||
text.charCodeAt(i + 2) === 117 && // 'u'
|
||
text.charCodeAt(i + 3) === 111 && // 'o'
|
||
text.charCodeAt(i + 4) === 116 && // 't'
|
||
text.charCodeAt(i + 5) === 59) { // ';'
|
||
decoded = '"';
|
||
entityLen = 6;
|
||
} else if (nextChar === 97 && // 'a'
|
||
text.charCodeAt(i + 2) === 112 && // 'p'
|
||
text.charCodeAt(i + 3) === 111 && // 'o'
|
||
text.charCodeAt(i + 4) === 115 && // 's'
|
||
text.charCodeAt(i + 5) === 59) { // ';'
|
||
decoded = "'";
|
||
entityLen = 6;
|
||
}
|
||
}
|
||
} else if (ch === 95 && i + 6 < len && // '_'
|
||
text.charCodeAt(i + 1) === 120 && // 'x'
|
||
text.charCodeAt(i + 6) === 95) { // '_'
|
||
|
||
// Inline hex parsing for _xHHHH_ pattern
|
||
let code = 0;
|
||
let isValidHex = true;
|
||
|
||
for (let j = i + 2; j < i + 6; ++j) {
|
||
const hexChar = text.charCodeAt(j);
|
||
code *= 16;
|
||
|
||
if (hexChar >= 48 && hexChar <= 57) { // '0'-'9'
|
||
code += hexChar - 48;
|
||
} else if (hexChar >= 65 && hexChar <= 70) { // 'A'-'F'
|
||
code += hexChar - 55;
|
||
} else if (hexChar >= 97 && hexChar <= 102) { // 'a'-'f'
|
||
code += hexChar - 87;
|
||
} else {
|
||
isValidHex = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (isValidHex) {
|
||
decoded = code === 0x005F ? '_' : stringFromCharCode(code);
|
||
entityLen = 7;
|
||
}
|
||
}
|
||
|
||
if (decoded !== null) {
|
||
// Copy text before entity
|
||
if (i > lastCopied) {
|
||
result.push(text.substring(lastCopied, i));
|
||
}
|
||
result.push(decoded);
|
||
const after = i + entityLen;
|
||
i = after - 1; // loop will ++i next iteration
|
||
lastCopied = after;
|
||
}
|
||
}
|
||
|
||
// Copy remaining text
|
||
if (lastCopied < len) {
|
||
result.push(text.substring(lastCopied, len));
|
||
}
|
||
|
||
return result.join('');
|
||
};
|
||
StaxParser.prototype.GetText = function () {
|
||
var text = "";
|
||
var depth = this.depth;
|
||
var type = EasySAXEvent.Unknown;
|
||
while (this.hasNext()) {
|
||
type = this.next();
|
||
var curDepth = this.GetDepth();
|
||
if (curDepth < depth) {
|
||
break;
|
||
}
|
||
if (EasySAXEvent.END_ELEMENT === type && curDepth === depth)
|
||
break;
|
||
if (EasySAXEvent.CHARACTERS === type) {
|
||
text += this.GetValue();
|
||
}
|
||
}
|
||
return text;
|
||
};
|
||
StaxParser.prototype.GetTextDecodeXml = function () {
|
||
return this.DecodeXml(this.GetText());
|
||
};
|
||
StaxParser.prototype.GetTextBool = function () {
|
||
return this.GetBool(this.GetText());
|
||
};
|
||
StaxParser.prototype.GetTextByte = function (def, radix) {
|
||
return this.GetTextInt(def, radix);
|
||
};
|
||
StaxParser.prototype.GetTextSByte = function (def, radix) {
|
||
return this.GetTextUInt(def, radix);
|
||
};
|
||
StaxParser.prototype.GetTextInt = function (def, radix) {
|
||
return this.GetInt(this.GetText(), def, radix);
|
||
};
|
||
StaxParser.prototype.GetTextUInt = function (def, radix) {
|
||
return this.GetUInt(this.GetText(), def, radix);
|
||
};
|
||
StaxParser.prototype.GetTextInt64 = function (def, radix) {
|
||
return this.GetTextInt(def, radix);
|
||
};
|
||
StaxParser.prototype.GetTextUInt64 = function (def, radix) {
|
||
return this.GetTextUInt(def, radix);
|
||
};
|
||
StaxParser.prototype.GetTextDouble = function (def) {
|
||
return this.GetDouble(this.GetText(), def);
|
||
};
|
||
StaxParser.prototype.ConvertToString = function(xml, start, end) {
|
||
return xml.substring(start, end);
|
||
// return "";
|
||
// return name ? String.prototype.fromUtf8(buffer, start, end - start + 1) : "";
|
||
// return String.prototype.fromUtf8(buffer, start, end - start + 1);
|
||
// return name ? decoder.decode(name) : "";
|
||
// return name ? new TextDecoder("utf-8").decode(name) : "";
|
||
// return String.fromCharCode.apply(null, name);
|
||
};
|
||
StaxParser.prototype.GetNSFromNodeName = function(name) {
|
||
var index = name.indexOf(':');
|
||
if (-1 !== index) {
|
||
return name.substring(0, index + 1);
|
||
}
|
||
return "";
|
||
};
|
||
StaxParser.prototype.GetNameFromNodeName = function(name) {
|
||
var index = name.indexOf(':');
|
||
if (-1 !== index) {
|
||
return name.substring(index + 1);
|
||
}
|
||
return name;
|
||
};
|
||
StaxParser.prototype.GetEventType = function() {
|
||
return this.eventType;
|
||
};
|
||
StaxParser.prototype.GetContext = function() {
|
||
return this.context;
|
||
};
|
||
StaxParser.prototype.GetOformContext = function() {
|
||
if (!this.context)
|
||
return null;
|
||
|
||
return this.context.getOformContext();
|
||
};
|
||
StaxParser.prototype.getState = function() {
|
||
return {
|
||
depth: this.depth,
|
||
eventType: this.eventType,
|
||
index: this.index,
|
||
isInAttr: this.isInAttr,
|
||
isTagEnd: this.isTagEnd,
|
||
isTagStart: this.isTagStart,
|
||
length: this.length,
|
||
name: this.name,
|
||
stop: this.stop,
|
||
text: this.text,
|
||
value: this.value
|
||
};
|
||
};
|
||
StaxParser.prototype.setState = function(state) {
|
||
this.depth = state.depth;
|
||
this.eventType = state.eventType;
|
||
this.index = state.index;
|
||
this.isInAttr = state.isInAttr;
|
||
this.isTagEnd = state.isTagEnd;
|
||
this.isTagStart = state.isTagStart;
|
||
this.length = state.length;
|
||
this.name = state.name;
|
||
this.stop = state.stop;
|
||
this.text = state.text;
|
||
this.value = state.value;
|
||
};
|
||
StaxParser.prototype.readXmlArray = function(childName, func) {
|
||
if (this.IsEmptyNode()) {
|
||
return;
|
||
}
|
||
|
||
var depth = this.GetDepth();
|
||
var indexChild = 0;
|
||
while (this.ReadNextSiblingNode(depth)) {
|
||
if (childName === this.GetNameNoNS()) {
|
||
func(indexChild);
|
||
indexChild++;
|
||
}
|
||
}
|
||
};
|
||
StaxParser.prototype.AddConnectedObject = function(object) {
|
||
this.context.addConnectorsPr(object);
|
||
};
|
||
|
||
function XmlParserContext(){
|
||
//common
|
||
this.zip = null;
|
||
this.DrawingDocument = null;
|
||
this.imageMap = {};
|
||
this.curChart = null;
|
||
this.smartarts = [];
|
||
//docx
|
||
this.commentDataById = {};
|
||
this.oReadResult = AscCommonWord.DocReadResult && new AscCommonWord.DocReadResult();
|
||
this.maxZIndex = 0;
|
||
|
||
this.oformContext = null;
|
||
this.sdtPrWithFieldPath = [];
|
||
this.fieldMasterMap = {};
|
||
|
||
this.fieldMastersWithUserMasterPath = [];
|
||
this.userMasterMap = {};
|
||
|
||
this.fieldGroupsWithFieldMasterPath = [];
|
||
this.fieldWithFieldMastersPath = [];
|
||
this.userWithUserMastersPath = [];
|
||
|
||
//xlsx
|
||
this.sharedStrings = [];
|
||
this.row = null;
|
||
this.cellValue = null;
|
||
this.cellBase = null;
|
||
this.drawingId = null;
|
||
//pptx
|
||
this.layoutsMap = {};
|
||
this.notesMastersMap = {};
|
||
this.TablesMap = {};
|
||
this.TableStylesMap = {};
|
||
this.ConnectorsPr = [];
|
||
}
|
||
XmlParserContext.prototype.initFromWS = function(ws) {
|
||
this.ws = ws;
|
||
this.row = new AscCommonExcel.Row(ws);
|
||
this.cellValue = new AscCommonExcel.CT_Value();
|
||
this.cellBase = new AscCommon.CellBase(0,0);
|
||
this.drawingId = null;
|
||
};
|
||
XmlParserContext.prototype.clearSlideRelations = function() {
|
||
this.layoutsMap = {};
|
||
this.notesMastersMap = {};
|
||
};
|
||
XmlParserContext.prototype.clearFieldRelations = function() {
|
||
this.sdtPrWithFieldPath = [];
|
||
this.fieldMasterMap = {};
|
||
};
|
||
XmlParserContext.prototype.addSdtPrRelation = function(oSdtPr, sTarget) {
|
||
this.sdtPrWithFieldPath.push({sdtPr: oSdtPr, target: sTarget});
|
||
};
|
||
XmlParserContext.prototype.addFieldGroupRelation = function(oFieldGroup, sTarget) {
|
||
this.fieldGroupsWithFieldMasterPath.push({fieldGroup: oFieldGroup, target: sTarget});
|
||
};
|
||
XmlParserContext.prototype.addFieldMasterPath = function(oFieldMaster, sTarget) {
|
||
this.fieldMasterMap[sTarget] = oFieldMaster;
|
||
};
|
||
XmlParserContext.prototype.addFieldWithFieldMaterPath = function(oField, sTarget) {
|
||
this.fieldWithFieldMastersPath.push({field: oField, target: sTarget});
|
||
};
|
||
XmlParserContext.prototype.addUserWithUserMastersPath = function(oUser, sTarget) {
|
||
this.userWithUserMastersPath.push({user: oUser, target: sTarget});
|
||
};
|
||
XmlParserContext.prototype.assignFieldsToFieldMasters = function() {
|
||
for(let nFld = 0; nFld < this.fieldWithFieldMastersPath.length; ++nFld) {
|
||
let oPair = this.fieldWithFieldMastersPath[nFld];
|
||
let sTarget = oPair.target;
|
||
for(let sKey in this.fieldMasterMap) {
|
||
if(this.fieldMasterMap.hasOwnProperty(sKey)) {
|
||
if(sKey.indexOf(sTarget) > -1) {
|
||
let oFieldMaster = this.fieldMasterMap[sKey];
|
||
if(oFieldMaster) {
|
||
oFieldMaster.setLogicField(oPair.field);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
};
|
||
XmlParserContext.prototype.assignFieldsToSdt = function() {
|
||
for(let nSdt = 0; nSdt < this.sdtPrWithFieldPath.length; ++nSdt) {
|
||
let oPair = this.sdtPrWithFieldPath[nSdt];
|
||
let oFieldMaster = this.fieldMasterMap[oPair.target];
|
||
if(oFieldMaster) {
|
||
oPair.sdtPr.OForm = oFieldMaster;
|
||
}
|
||
}
|
||
};
|
||
|
||
XmlParserContext.prototype.addFieldMasterRelation = function(oFieldMaster, sTarget) {
|
||
this.fieldMastersWithUserMasterPath.push({fieldMaster: oFieldMaster, target: sTarget});
|
||
};
|
||
XmlParserContext.prototype.addUserMasterPath = function(oUserMaster, sTarget) {
|
||
this.userMasterMap[sTarget] = oUserMaster;
|
||
};
|
||
XmlParserContext.prototype.assignFieldsToFieldGroup = function() {
|
||
for(let nFldGrp = 0; nFldGrp < this.fieldGroupsWithFieldMasterPath.length; ++nFldGrp) {
|
||
let oPair = this.fieldGroupsWithFieldMasterPath[nFldGrp];
|
||
let sTarget = oPair.target;
|
||
for(let sKey in this.fieldMasterMap) {
|
||
if(this.fieldMasterMap.hasOwnProperty(sKey)) {
|
||
if(sKey.indexOf(sTarget) > -1) {
|
||
let oFieldMaster = this.fieldMasterMap[sKey];
|
||
if(oFieldMaster) {
|
||
oPair.fieldGroup.addField(oFieldMaster);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
};
|
||
XmlParserContext.prototype.assignUsersToFieldMasters = function() {
|
||
for(let nPair = 0; nPair < this.fieldMastersWithUserMasterPath.length; ++nPair) {
|
||
let oPair = this.fieldMastersWithUserMasterPath[nPair];
|
||
let oUserMasterMaster = this.userMasterMap[oPair.target];
|
||
if(oUserMasterMaster) {
|
||
oPair.fieldMaster.addUser(oUserMasterMaster);
|
||
}
|
||
}
|
||
};
|
||
XmlParserContext.prototype.assignUsersToUserMasters = function() {
|
||
for(let nPair = 0; nPair < this.userWithUserMastersPath.length; ++nPair) {
|
||
let oPair = this.userWithUserMastersPath[nPair];
|
||
let sTarget = oPair.target;
|
||
for(let sKey in this.userMasterMap) {
|
||
if(this.userMasterMap.hasOwnProperty(sKey)) {
|
||
if(sKey.indexOf(sTarget) > -1) {
|
||
let oUserMaster = this.userMasterMap[sKey];
|
||
if(oUserMaster) {
|
||
oUserMaster.setUserId(oPair.user.Id);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
};
|
||
XmlParserContext.prototype.assignFormLinks = function() {
|
||
this.assignFieldsToSdt();
|
||
this.assignUsersToFieldMasters();
|
||
this.assignFieldsToFieldGroup();
|
||
this.assignFieldsToFieldMasters();
|
||
this.assignUsersToUserMasters();
|
||
|
||
this.sdtPrWithFieldPath = [];
|
||
this.fieldMasterMap = {};
|
||
this.fieldMastersWithUserMasterPath = [];
|
||
this.userMasterMap = {};
|
||
this.fieldGroupsWithFieldMasterPath = [];
|
||
this.fieldWithFieldMastersPath = [];
|
||
this.userWithUserMastersPath = [];
|
||
};
|
||
XmlParserContext.prototype.getOformContext = function() {
|
||
return this.oformContext;
|
||
};
|
||
XmlParserContext.prototype.setOformContext = function(context) {
|
||
this.oformContext = context;
|
||
};
|
||
|
||
XmlParserContext.prototype.addTableStyle = function(sGuid, oStyle) {
|
||
this.TableStylesMap[sGuid] = oStyle;
|
||
};
|
||
XmlParserContext.prototype.getTableStyle = function(sGuid) {
|
||
return this.TableStylesMap[sGuid] || null;
|
||
};
|
||
XmlParserContext.prototype.addConnectorsPr = function(oPr) {
|
||
for(let nIdx = 0; nIdx < this.ConnectorsPr.length; ++nIdx) {
|
||
if(oPr === this.ConnectorsPr[nIdx]) {
|
||
return;
|
||
}
|
||
}
|
||
this.ConnectorsPr.push(oPr);
|
||
};
|
||
XmlParserContext.prototype.assignConnectors = function(aSpTree) {
|
||
for(let nIdx = 0; nIdx < this.ConnectorsPr.length; ++nIdx) {
|
||
this.ConnectorsPr[nIdx].assignConnectors(aSpTree);
|
||
}
|
||
this.ConnectorsPr.length = 0;
|
||
};
|
||
XmlParserContext.prototype.checkZIndex = function(nZIndex) {
|
||
if(AscFormat.isRealNumber(nZIndex)) {
|
||
this.maxZIndex = Math.max(this.maxZIndex, nZIndex);
|
||
}
|
||
};
|
||
XmlParserContext.prototype.loadDataLinks = function() {
|
||
let _cur_ind = 0;
|
||
let oImageMap = {};
|
||
for (let path in this.imageMap) {
|
||
if (this.imageMap.hasOwnProperty(path)) {
|
||
oImageMap[_cur_ind++] = path;
|
||
let data = this.zip.getFile(path);
|
||
if (data) {
|
||
let blobUrl = AscCommon.g_oDocumentBlobUrls.getBlobUrl(path, this.zip);
|
||
AscCommon.g_oDocumentUrls.addImageUrl(path, blobUrl);
|
||
|
||
this.imageMap[path].forEach(function(blipFill) {
|
||
AscCommon.pptx_content_loader.Reader.initAfterBlipFill(path, blipFill);
|
||
});
|
||
}
|
||
}
|
||
}
|
||
return oImageMap;
|
||
};
|
||
XmlParserContext.prototype.GenerateSmartArts = function() {
|
||
while (this.smartarts.length) {
|
||
const smartart = this.smartarts.pop();
|
||
smartart.generateDrawingPart();
|
||
}
|
||
};
|
||
XmlParserContext.prototype.ClearSmartArts = function() {
|
||
this.smartarts.length = 0;
|
||
};
|
||
function XmlWriterContext(editorId){
|
||
//common
|
||
this.editorId = editorId;
|
||
this.zip = null;
|
||
this.part = null;
|
||
this.imageMap = {};
|
||
this.currentPartImageMap = {};
|
||
this.dataMap = {};
|
||
this.currentPartDataMap = {};
|
||
this.m_lObjectIdVML = 1025;
|
||
|
||
this.oUriMap = {};
|
||
this.objectId = 1;
|
||
this.groupIndex = 0;
|
||
this.flag = 0;
|
||
switch (editorId) {
|
||
case AscCommon.c_oEditorId.Word: {
|
||
this.docType = AscFormat.XMLWRITER_DOC_TYPE_DOCX;
|
||
break;
|
||
}
|
||
case AscCommon.c_oEditorId.Spreadsheet: {
|
||
this.docType = AscFormat.XMLWRITER_DOC_TYPE_XLSX;
|
||
break;
|
||
}
|
||
case AscCommon.c_oEditorId.Presentation: {
|
||
this.docType = AscFormat.XMLWRITER_DOC_TYPE_PPTX;
|
||
break;
|
||
}
|
||
}
|
||
//docx
|
||
this.document = null;
|
||
this.oNumIdMap = {};
|
||
this.commentIdIndex = 1;
|
||
this.paraIdIndex = 1;
|
||
this.commentDataById = {};
|
||
this.docSaveParams = null;
|
||
|
||
this.fieldMastersPartMap = {};
|
||
this.userMasterPartMap = {};
|
||
|
||
//xlsx
|
||
this.wb = null;
|
||
this.sheetIds = [];
|
||
this.sharedStrings = null;
|
||
this.isCopyPaste = null;
|
||
this.stylesForWrite = AscCommonExcel.StylesForWrite && new AscCommonExcel.StylesForWrite(); //no StylesForWrite in vsdx now
|
||
this.oSharedStrings = {index: 0, strings: {}};
|
||
this.oleDrawings = [];
|
||
this.signatureDrawings = [];
|
||
//pptx
|
||
this.presentation = null;
|
||
this.sldMasterIdLst = [];
|
||
this.sldLayoutIdLst = [];
|
||
this.sldLayoutsCount = 0;
|
||
this.notesMasterIdLst = [];
|
||
this.handoutMasterIdLst = [];
|
||
this.sldIdLst = [];
|
||
this.tableStylesIdToGuid = {};
|
||
}
|
||
XmlWriterContext.prototype.initFromWS = function(ws) {
|
||
this.ws = ws;
|
||
this.row = new AscCommonExcel.Row(ws);
|
||
this.cellValue = new AscCommonExcel.CT_Value();
|
||
this.cellBase = new AscCommon.CellBase(0,0);
|
||
this.drawingId = null;
|
||
};
|
||
|
||
XmlWriterContext.prototype.addSlideRel = function(sRel) {
|
||
this.sldIdLst.push(sRel);
|
||
};
|
||
XmlWriterContext.prototype.addSlideLayoutRel = function(sRel) {
|
||
this.sldLayoutIdLst.push(sRel);
|
||
};
|
||
XmlWriterContext.prototype.addSlideMasterRel = function(sRel) {
|
||
this.sldMasterIdLst.push(sRel);
|
||
};
|
||
XmlWriterContext.prototype.addNotesMasterRel = function(sRel) {
|
||
this.notesMasterIdLst.push(sRel);
|
||
};
|
||
XmlWriterContext.prototype.addFieldMasterPart = function(oFieldMaster, oPart) {
|
||
this.fieldMastersPartMap[oFieldMaster.Id] = oPart;
|
||
};
|
||
XmlWriterContext.prototype.addUserMasterPart = function(oUserMaster, oPart) {
|
||
this.userMasterPartMap[oUserMaster.Id] = oPart;
|
||
};
|
||
XmlWriterContext.prototype.clearSlideLayoutRels = function() {
|
||
this.sldLayoutIdLst.length = 0;
|
||
};
|
||
XmlWriterContext.prototype.getSlideMastersCount = function() {
|
||
return this.sldMasterIdLst.length;
|
||
};
|
||
XmlWriterContext.prototype.getSlidesCount = function() {
|
||
return this.sldIdLst.length;
|
||
};
|
||
XmlWriterContext.prototype.clearCurrentPartDataMaps = function() {
|
||
this.currentPartImageMap = {};
|
||
this.currentPartDataMap = {};
|
||
};
|
||
XmlWriterContext.prototype.getImageRId = function(sRasterImageId) {
|
||
let imagePart = this.imageMap[sRasterImageId];
|
||
let type = this.editorId === AscCommon.c_oEditorId.Word ? AscCommon.openXml.Types.imageWord : AscCommon.openXml.Types.image;
|
||
if (!imagePart) {
|
||
if (this.part) {
|
||
let ext = AscCommon.GetFileExtension(sRasterImageId);
|
||
type = Object.assign({}, type);
|
||
type.filename += ext;
|
||
type.contentType = AscCommon.openXml.GetMimeType(ext);
|
||
imagePart = this.part.addPart(type);
|
||
if (imagePart) {
|
||
this.imageMap[sRasterImageId] = imagePart;
|
||
this.currentPartImageMap[sRasterImageId] = imagePart.rId;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
if(!this.currentPartImageMap[sRasterImageId]) {
|
||
if(this.part) {
|
||
this.currentPartImageMap[sRasterImageId] = this.part.addRelationship(type.relationType, imagePart.part.uri);
|
||
}
|
||
}
|
||
}
|
||
return this.currentPartImageMap[sRasterImageId] ? this.currentPartImageMap[sRasterImageId] : "";
|
||
};
|
||
XmlWriterContext.prototype.getDataRId = function(sDataLink) {
|
||
let dataPart = this.dataMap[sDataLink];
|
||
let type = this.editorId === AscCommon.c_oEditorId.Word ? AscCommon.openXml.Types.wordPackage : AscCommon.openXml.Types.package;
|
||
if (!dataPart) {
|
||
if (this.part) {
|
||
let ext = AscCommon.GetFileExtension(sDataLink);
|
||
type = Object.assign({}, type);
|
||
type.filename = AscCommon.changeFileExtention(type.filename, ext, null);
|
||
type.contentType = AscCommon.openXml.GetMimeType(ext);
|
||
dataPart = this.part.addPart(type);
|
||
if (dataPart) {
|
||
this.dataMap[sDataLink] = dataPart;
|
||
this.currentPartDataMap[sDataLink] = dataPart.rId;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
if(!this.currentPartDataMap[sDataLink]) {
|
||
if(this.part) {
|
||
this.currentPartDataMap[sDataLink] = this.part.addRelationship(type.relationType, dataPart.part.uri);
|
||
}
|
||
}
|
||
}
|
||
return this.currentPartDataMap[sDataLink] ? this.currentPartDataMap[sDataLink] : "";
|
||
};
|
||
XmlWriterContext.prototype.getSpIdxId = function(sEditorId){
|
||
if(typeof sEditorId === "string" && sEditorId.length > 0) {
|
||
var oDrawing = AscCommon.g_oTableId.Get_ById(sEditorId);
|
||
if(oDrawing && oDrawing.getFormatId) {
|
||
return oDrawing.getFormatId();
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
function CT_XmlNode(opt_elemReader) {
|
||
this.attributes = {};
|
||
this.members = {};
|
||
this.text = null;
|
||
|
||
this.elemReader = opt_elemReader || function(){};
|
||
}
|
||
CT_XmlNode.fromReader = function(reader, opt_elemReader) {
|
||
let node = new CT_XmlNode(opt_elemReader);
|
||
node.fromXml(reader);
|
||
return node;
|
||
};
|
||
CT_XmlNode.prototype.readAttr = function(reader) {
|
||
while (reader.MoveToNextAttribute()) {
|
||
this.attributes[reader.GetNameNoNS()] = reader.GetValue();
|
||
}
|
||
};
|
||
CT_XmlNode.prototype.fromXml = function(reader) {
|
||
this.readAttr(reader);
|
||
var elem, depth = reader.GetDepth();
|
||
while (reader.Read()) {
|
||
switch(reader.GetEventType()) {
|
||
case EasySAXEvent.START_ELEMENT:
|
||
var name = reader.GetNameNoNS();
|
||
elem = this.elemReader.call(this, reader, name);
|
||
if (!elem) {
|
||
elem = new CT_XmlNode();
|
||
elem.fromXml(reader);
|
||
}
|
||
this.members[name] = elem;
|
||
break;
|
||
case EasySAXEvent.CHARACTERS:
|
||
if(!this.text) {
|
||
this.text = "";
|
||
}
|
||
this.text += reader.GetValue();
|
||
break;
|
||
case EasySAXEvent.END_ELEMENT:
|
||
if (reader.GetDepth() === depth)
|
||
return;
|
||
break;
|
||
}
|
||
}
|
||
};
|
||
CT_XmlNode.prototype.toXml = function(writer, name) {
|
||
var i;
|
||
writer.WriteXmlNodeStart(name);
|
||
for (i in this.attributes) {
|
||
if (this.attributes.hasOwnProperty(i)) {
|
||
writer.WriteXmlNullableAttributeString(i, this.attributes[i]);
|
||
}
|
||
}
|
||
writer.WriteXmlAttributesEnd();
|
||
for (i in this.members) {
|
||
if (this.members.hasOwnProperty(i)) {
|
||
var member = this.members[i];
|
||
if(Array.isArray(member)) {
|
||
for(var nIdx = 0; nIdx < member.length; ++nIdx) {
|
||
member[nIdx].toXml(writer, i);
|
||
}
|
||
}
|
||
else {
|
||
member.toXml(writer, i);
|
||
}
|
||
}
|
||
}
|
||
if (null !== this.text && undefined !== this.text) {
|
||
writer.WriteXmlStringEncode(this.text.toString());
|
||
}
|
||
writer.WriteXmlNodeEnd(name);
|
||
};
|
||
|
||
window['AscCommon'] = window['AscCommon'] || {};
|
||
window['AscCommon'].XmlParserContext = XmlParserContext;
|
||
window["AscCommon"].XmlWriterContext = XmlWriterContext;
|
||
window['AscCommon'].StaxParser = StaxParser;
|