Files
DocumentServer-v-9.2.0/sdkjs/vendor/easysax.js
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

2177 lines
72 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'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 &amp; 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;
// &lt; (4 chars)
if (nextChar === 108 && i + 3 < len && // 'l'
text.charCodeAt(i + 2) === 116 && // 't'
text.charCodeAt(i + 3) === 59) { // ';'
decoded = '<';
entityLen = 4;
}
// &gt; (4 chars)
else if (nextChar === 103 && i + 3 < len && // 'g'
text.charCodeAt(i + 2) === 116 && // 't'
text.charCodeAt(i + 3) === 59) { // ';'
decoded = '>';
entityLen = 4;
}
// &amp; (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;
}
// &quot; or &apos; (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;