/*
 * SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software. 
 * This class is generated using the converter UniSharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

const Utils = require("./../../../unisharp/Utils");
const Hashtable = require("./../../../unisharp/Hashtable");
const RefOutArgWrapper = require("./../../../unisharp/RefOutArgWrapper");
const StringBuilder = require("./../../../unisharp/StringBuilder");
const Stream = require("./../../../unisharp/Stream");
const FileStream = require("./../../../unisharp/FileStream");
const MemoryStream = require("./../../../unisharp/MemoryStream");
const XmlDocument = require("./../../../unisharp/XmlDocument");
const XmlNode = require("./../../../unisharp/XmlNode");

const UnitextItem = require("./../../UnitextItem");
const WingdingsHelper = require("./../misc/WingdingsHelper");
const UnitextContainerType = require("./../../UnitextContainerType");
const MyXmlReader = require("./../misc/MyXmlReader");
const ExcelHelper = require("./../misc/ExcelHelper");
const SymbolHelper = require("./../misc/SymbolHelper");
const UnitextMisc = require("./../../UnitextMisc");
const UnitextStyledFragmentType = require("./../../UnitextStyledFragmentType");
const UnitextNewline = require("./../../UnitextNewline");
const UnitextPlaintext = require("./../../UnitextPlaintext");
const UnitextContainer = require("./../../UnitextContainer");
const UnitextStyle = require("./../../UnitextStyle");
const UnitextFootnote = require("./../../UnitextFootnote");
const UnitextPlaintextType = require("./../../UnitextPlaintextType");
const UnitextMiscType = require("./../../UnitextMiscType");
const DocTable = require("./DocTable");
const IUnitextGenNumStyle = require("./../uni/IUnitextGenNumStyle");
const DocTextStyles = require("./DocTextStyles");
const FileFormat = require("./../../FileFormat");
const UnitextComment = require("./../../UnitextComment");
const DocNumStyles = require("./DocNumStyles");
const UnitextGen = require("./../uni/UnitextGen");
const UnitextStyledFragment = require("./../../UnitextStyledFragment");
const MyZipFile = require("./../misc/MyZipFile");
const UnitextPagesectionItemPages = require("./../../UnitextPagesectionItemPages");
const UnitextService = require("./../../UnitextService");
const UnitextPagebreak = require("./../../UnitextPagebreak");
const UnitextDocument = require("./../../UnitextDocument");
const UnitextImage = require("./../../UnitextImage");
const UnitextHelper = require("./../uni/UnitextHelper");
const DocxPart = require("./DocxPart");
const DocSection = require("./DocSection");
const UnitextPagesectionItem = require("./../../UnitextPagesectionItem");
const UnitextHyperlink = require("./../../UnitextHyperlink");
const OdtHelper = require("./../misc/OdtHelper");

class DocxToText {
    
    constructor(fileName, content, isXml, setFormulaAsImage) {
        this.maxTableRows = 0;
        this.setFormulasAsImage = false;
        this.zipFile = null;
        this.xmlFile = null;
        this.parts = new Array();
        this.m_Hyperlinks = new Hashtable();
        this.m_DataControls = new Hashtable();
        this.m_Styles = new DocTextStyles();
        this.m_NumStyles = new DocNumStyles();
        this.m_Sections = new Array();
        this.m_CurSection = null;
        this.m_Collontituls = new Hashtable();
        this.m_Comments = new Hashtable();
        this.m_Embeds = new Hashtable();
        this.m_Footnotes = new Hashtable();
        this.m_lastRSID = "";
        this.m_lastChar = ' ';
        this.setFormulasAsImage = setFormulaAsImage;
        if (isXml) {
            this.xmlFile = new XmlDocument();
            if (content !== null) {
                let mem = new MemoryStream(content); 
                try {
                    this.xmlFile.loadStream(mem);
                }
                finally {
                    mem.close();
                }
            }
            else {
                let fs = new FileStream(fileName, "r", false); 
                try {
                    this.xmlFile.loadStream(fs);
                }
                finally {
                    fs.close();
                }
            }
            this._prepareXml();
        }
        else {
            this.zipFile = new MyZipFile(fileName, content);
            this._prepareZip();
        }
    }
    
    _prepareZip() {
        for (const o of this.zipFile.entries) {
            if (o.isDirectory || o.encrypted || o.uncompressDataSize === 0) 
                continue;
            this.parts.push(DocxPart._new487(o.name, o));
        }
    }
    
    _prepareXml() {
        if (this.xmlFile.document_element.local_name === "wordDocument") {
            this.parts.push(DocxPart._new488("word/document.xml", this.xmlFile.document_element));
            return;
        }
        for (const xml of this.xmlFile.document_element.child_nodes) {
            if (xml.local_name === "part") {
                let p = new DocxPart();
                if (xml.attributes !== null) {
                    for (const a of xml.attributes) {
                        if (a.local_name === "name") {
                            p.name = a.value;
                            if (p.name.startsWith("/")) 
                                p.name = p.name.substring(1);
                            break;
                        }
                    }
                }
                for (const x of xml.child_nodes) {
                    if (x.local_name === "xmlData") {
                        for (const xx of x.child_nodes) {
                            p.xml = xx;
                            break;
                        }
                        break;
                    }
                    else if (x.local_name === "binaryData") {
                        try {
                            p.data = Utils.decodeBase64(x.inner_text);
                        } catch (ex) {
                        }
                        break;
                    }
                }
                if (p.name !== null && ((p.xml !== null || p.data !== null))) 
                    this.parts.push(p);
            }
        }
    }
    
    close() {
        try {
            if (this.zipFile !== null) {
                this.zipFile.close();
                this.zipFile = null;
            }
        } catch (ex) {
        }
    }
    
    createUniDoc(onlyForPureText, frm, pars) {
        let sheets = new Hashtable();
        let idImages = new Hashtable();
        let idEmbeds = new Hashtable();
        let sharedStrings = new Array();
        let pptSlides = new Hashtable();
        let pptImages = new Hashtable();
        let xmlDoc = null;
        let xmlBook = null;
        let xmlComments = null;
        let xmlSettings = null;
        let xmlFootnotes = null;
        let xmlEndnotes = null;
        let xmlOdtContent = null;
        let xmlOdtStyle = null;
        for (const p of this.parts) {
            if (p.name !== null && p.name.startsWith("word/theme/")) 
                this.m_Styles.readTheme(p.getXmlNode(false));
        }
        for (const p of this.parts) {
            if (p.isName("word/numbering.xml")) {
                let xmlNum = p.getXmlNode(false);
                if (xmlNum !== null) 
                    this.m_NumStyles.readAllStyles(xmlNum);
            }
        }
        for (const p of this.parts) {
            if (p.isName("word/styles.xml")) 
                this.m_Styles.readAllStyles(p.getXmlNode(false), this.m_NumStyles);
        }
        for (const p of this.parts) {
            if (p.isName("word/document.xml")) 
                xmlDoc = p.getXmlNode(false);
            else if (p.isName("word/footnotes.xml")) 
                xmlFootnotes = p.getXmlNode(false);
            else if (p.isName("word/endnotes.xml")) 
                xmlEndnotes = p.getXmlNode(false);
            else if (p.isName("word/styles.xml")) {
            }
            else if (p.isName("word/settings.xml")) 
                xmlSettings = p.getXmlNode(false);
            else if (p.isName("word/comments.xml")) {
                xmlComments = p.getXmlNode(false);
                if (xmlComments !== null) {
                    for (const x of xmlComments.child_nodes) {
                        if (x.local_name === "comment") {
                            let cmt = new UnitextComment();
                            let id = null;
                            if (x.attributes !== null) {
                                for (const a of x.attributes) {
                                    if (a.local_name === "id") 
                                        id = a.value;
                                    else if (a.local_name === "author") 
                                        cmt.author = a.value;
                                }
                            }
                            if (id === null || this.m_Comments.containsKey(id)) 
                                continue;
                            let gen = new UnitextGen();
                            let xxx = new Array();
                            xxx.push(x);
                            this.m_Styles.ignore = true;
                            this.readNode(xxx, gen, null, -1);
                            this.m_Styles.ignore = false;
                            let it = gen.finish(true, null);
                            if (it !== null) {
                                let tmp = new StringBuilder();
                                it.getPlaintext(tmp, null);
                                if (tmp.length > 0) {
                                    cmt.text = tmp.toString();
                                    this.m_Comments.put(id, cmt);
                                }
                            }
                        }
                    }
                }
            }
            else if (p.isName("content.xml")) 
                xmlOdtContent = p.getXmlNode(true);
            else if (p.isName("styles.xml")) 
                xmlOdtStyle = p.getXmlNode(true);
            else if (p.isName("xl/workbook.xml")) 
                xmlBook = p.getXmlNode(false);
            else if (p.isName("xl/sharedStrings.xml")) {
                let xml = p.getXmlNode(false);
                if (xml !== null) {
                    for (const xx of xml.child_nodes) {
                        if (xx.local_name === "si") {
                            let gg = new UnitextGen();
                            let xxx = new Array();
                            xxx.push(xx);
                            this.m_Styles.ignore = true;
                            this.readNode(xxx, gg, null, -1);
                            this.m_Styles.ignore = false;
                            let ff = gg.finish(true, null);
                            if (ff !== null) 
                                ff = ff.optimize(true, pars);
                            sharedStrings.push(ff);
                        }
                    }
                }
            }
            else if (p.isName("xl/styles.xml")) {
                let xml = p.getXmlNode(false);
                if (xml !== null) 
                    this.m_Styles.readAllExcelStyles(xml);
            }
            else if (((p.isNameStarts("word/_rels/") || p.isNameStarts("xl/_rels/") || p.isNameStarts("ppt/slides/_rels/"))) && ((p.zipEntry !== null && !p.zipEntry.isDirectory))) {
                let xmlRels = p.getXmlNode(false);
                if (xmlRels !== null) {
                    let pptImgs = null;
                    if (p.name.startsWith("ppt")) {
                        let ii = p.name.indexOf("rels/slide");
                        if (ii < 0) 
                            continue;
                        let nam = p.name.substring(ii + 10);
                        ii = nam.indexOf('.');
                        if (ii < 0) 
                            continue;
                        let wrapii489 = new RefOutArgWrapper();
                        let inoutres490 = Utils.tryParseInt(nam.substring(0, 0 + ii), wrapii489);
                        ii = wrapii489.value;
                        if (!inoutres490) 
                            continue;
                        if (pptImages.containsKey(ii)) 
                            continue;
                        pptImgs = new Hashtable();
                        pptImages.put(ii, pptImgs);
                    }
                    for (const xx of xmlRels.child_nodes) {
                        if (xx.attributes !== null) {
                            if (Utils.getXmlAttrByName(xx.attributes, "Id") !== null && Utils.getXmlAttrByName(xx.attributes, "Target") !== null && Utils.getXmlAttrByName(xx.attributes, "Type") !== null) {
                                let id = Utils.getXmlAttrByName(xx.attributes, "Id").value;
                                let val = Utils.getXmlAttrByName(xx.attributes, "Target").value;
                                let typ = Utils.getXmlAttrByName(xx.attributes, "Type").value;
                                if (typ.endsWith("/header")) 
                                    this.m_Collontituls.put(id, val);
                                else if (typ.endsWith("/footer")) 
                                    this.m_Collontituls.put(id, val);
                                else if (typ.endsWith("/worksheet")) 
                                    sheets.put(id, val);
                                else if (typ.endsWith("/image")) {
                                    if (pptImgs !== null) {
                                        if (!pptImgs.containsKey(id)) 
                                            pptImgs.put(id, val);
                                    }
                                    else if (!idImages.containsKey(id)) 
                                        idImages.put(id, val);
                                }
                                else if (typ.endsWith("/package")) {
                                    if (!idEmbeds.containsKey(id)) 
                                        idEmbeds.put(id, val);
                                }
                                else if (typ.endsWith("/hyperlink")) {
                                    if (!Utils.isNullOrEmpty(val) && !this.m_Hyperlinks.containsKey(id)) 
                                        this.m_Hyperlinks.put(id, val);
                                }
                            }
                        }
                    }
                }
            }
            else if (p.isNameStarts("ppt/slides/slide") && p.name.endsWith(".xml")) {
                xmlDoc = p.getXmlNode(false);
                if (xmlDoc === null) 
                    continue;
                let gen = new UnitextGen();
                let xxx = new Array();
                xxx.push(xmlDoc);
                this.readNode(xxx, gen, null, -1);
                let slide = gen.finish(true, null);
                if (slide === null) 
                    continue;
                let nam = p.name.substring("ppt/slides/slide".length);
                let ii = nam.indexOf('.');
                if (ii < 0) 
                    continue;
                let wrapii491 = new RefOutArgWrapper();
                let inoutres492 = Utils.tryParseInt(nam.substring(0, 0 + ii), wrapii491);
                ii = wrapii491.value;
                if (inoutres492) {
                }
                else 
                    ii = pptSlides.length + 1;
                for (; ; ii++) {
                    if (!pptSlides.containsKey(ii)) {
                        pptSlides.put(ii, slide);
                        break;
                    }
                }
            }
        }
        if (xmlOdtContent !== null) {
            let dh = new OdtHelper();
            let res = dh.createUni(xmlOdtContent, (xmlOdtStyle === null ? null : xmlOdtStyle));
            if (res === null) 
                return null;
            let its = new Array();
            let keys = new Array();
            res.getAllItems(its, 0);
            for (const it of its) {
                if ((it instanceof UnitextImage) && it.id !== null && !keys.includes(it.id.toLowerCase())) 
                    keys.push(it.id.toLowerCase());
            }
            if (its.length > 0 && !onlyForPureText) {
                for (const o of this.zipFile.entries) {
                    let kkk = o.name.toLowerCase();
                    if (!keys.includes(kkk)) 
                        continue;
                    let dat = o.getData();
                    if (dat !== null && dat.length > 0) {
                        for (const it of its) {
                            if ((it instanceof UnitextImage) && it.id !== null && it.id.toLowerCase() === kkk) 
                                it.content = dat;
                        }
                    }
                }
            }
            return res;
        }
        if (pptSlides.length > 0) {
            let res = UnitextDocument._new493(FileFormat.PPTX, this.m_DataControls);
            let cnt = new UnitextContainer();
            res.content = cnt;
            for (const kp of pptSlides.entries) {
                if (cnt.children.length > 0) 
                    cnt.children.push(new UnitextPagebreak());
                cnt.children.push(kp.value);
                if (pptImages.containsKey(kp.key)) {
                    let imgs = new Array();
                    kp.value.getAllItems(imgs, 0);
                    for (const it of imgs) {
                        let im = Utils.as(it, UnitextImage);
                        if (im !== null && pptImages.get(kp.key).containsKey((im.id != null ? im.id : ""))) {
                            im.id = pptImages.get(kp.key).get(im.id);
                            if (im.id.startsWith("../")) 
                                im.id = im.id.substring(3);
                        }
                    }
                }
            }
            if (!onlyForPureText) {
                let ims = new Array();
                res.getAllItems(ims, 0);
                for (const p of this.parts) {
                    let kkk = p.name.toLowerCase();
                    let dat = null;
                    for (const im of ims) {
                        if ((im instanceof UnitextImage) && im.id !== null) {
                            if (kkk.endsWith(im.id)) {
                                if (dat === null) 
                                    dat = p.getBytes();
                                im.content = dat;
                            }
                        }
                    }
                }
            }
            return res;
        }
        if (idEmbeds.length > 0) {
            for (const p of this.parts) {
                for (const kp of idEmbeds.entries) {
                    if (!this.m_Embeds.containsKey(kp.key)) {
                        if (p.name.toLowerCase().endsWith(kp.value.toLowerCase())) {
                            let dat = p.getBytes();
                            if (dat !== null && dat.length > 0) {
                                let doc1 = UnitextService.createDocument(p.name, dat, null);
                                if (doc1 !== null && doc1.content !== null) 
                                    this.m_Embeds.put(kp.key, doc1.content);
                            }
                            break;
                        }
                    }
                }
            }
        }
        if (xmlDoc !== null) {
            let res = UnitextDocument._new493(FileFormat.DOCX, this.m_DataControls);
            let rootStyle = new UnitextStyledFragment();
            rootStyle.doc = res;
            if (this.m_Styles.defStyle !== null) {
                this.m_Styles.defStyle = this.m_Styles.registerStyle(this.m_Styles.defStyle);
                rootStyle.style = this.m_Styles.defStyle;
            }
            this.m_Sections.push(new DocSection());
            this.m_CurSection = this.m_Sections[0].uSect;
            this.m_CurSection.id = "ps1";
            let evenAndOddHeaders = false;
            if (xmlSettings !== null) {
                for (const x of xmlSettings.child_nodes) {
                    if (x.local_name === "evenAndOddHeaders") 
                        evenAndOddHeaders = true;
                }
            }
            if (xmlFootnotes !== null) {
                let li = new Array();
                li.push(xmlFootnotes);
                this.readFootnotes(li, false, rootStyle);
            }
            if (xmlEndnotes !== null) {
                let li = new Array();
                li.push(xmlEndnotes);
                this.readFootnotes(li, true, rootStyle);
            }
            let gen = new UnitextGen();
            gen.setStyle(rootStyle);
            let xxx = new Array();
            xxx.push(xmlDoc);
            this.readNode(xxx, gen, rootStyle, -1);
            let body = gen.finish(true, null);
            if (body === null) 
                return null;
            res.content = body;
            res.content.m_StyledFrag = rootStyle;
            if (this.m_Sections.length > 0 && !this.m_Sections[this.m_Sections.length - 1].loaded) 
                this.m_Sections.splice(this.m_Sections.length - 1, 1);
            this.m_CurSection = null;
            for (const s of this.m_Sections) {
                res.sections.push(s.uSect);
                for (let k = 0; k < 2; k++) {
                    let ids = (k === 0 ? s.headIds : s.footIds);
                    let pits = new Array();
                    for (const kp of ids.entries) {
                        if (!this.m_Collontituls.containsKey(kp.value)) 
                            continue;
                        if (!evenAndOddHeaders) {
                            if (kp.key === UnitextPagesectionItemPages.EVEN || kp.key === UnitextPagesectionItemPages.ODD) 
                                continue;
                        }
                        if (!s.titlePg) {
                            if (kp.key === UnitextPagesectionItemPages.FIRST) 
                                continue;
                        }
                        let fnam = this.m_Collontituls.get(kp.value);
                        let sectRootStyle = new UnitextStyledFragment();
                        sectRootStyle.doc = res;
                        let g = new UnitextGen();
                        g.setStyle(sectRootStyle);
                        for (const p of this.parts) {
                            let kkk = p.name;
                            let ii = kkk.indexOf('/');
                            if (ii < 0) 
                                continue;
                            kkk = kkk.substring(ii + 1);
                            if (kkk !== fnam) 
                                continue;
                            let xml = p.getXmlNode(false);
                            if (xml !== null) {
                                xxx.splice(0, xxx.length);
                                xxx.push(xml);
                                this.readNode(xxx, g, sectRootStyle, -1);
                                break;
                            }
                        }
                        let fi = g.finish(true, null);
                        let it = new UnitextPagesectionItem();
                        if (k > 0) 
                            it.isFooter = true;
                        it.pages = kp.key;
                        it.content = fi;
                        let its = new Array();
                        fi.getAllItems(its, 0);
                        for (const ii of its) {
                            if (ii instanceof UnitextContainer) {
                                let ccc = Utils.as(ii, UnitextContainer);
                                for (let i = 0; i < ccc.children.length; i++) {
                                    if (ccc.children[i] instanceof UnitextPagebreak) 
                                        ccc.children[i] = new UnitextNewline();
                                }
                            }
                        }
                        if (it.pages === UnitextPagesectionItemPages.FIRST) 
                            pits.splice(0, 0, it);
                        else 
                            pits.push(it);
                    }
                    s.uSect.items.splice(s.uSect.items.length, 0, ...pits);
                    if (s.titlePg) {
                        let hasTitle = false;
                        for (const pi of pits) {
                            if (pi.pages === UnitextPagesectionItemPages.FIRST) 
                                hasTitle = true;
                        }
                        if (!hasTitle && res.sections.length > 1) {
                            let sprev = res.sections[res.sections.length - 2];
                            for (const it of sprev.items) {
                                if (it.pages === UnitextPagesectionItemPages.FIRST && it.isFooter === (k > 0)) {
                                    let it2 = Utils.as(it.clone(), UnitextPagesectionItem);
                                    s.uSect.items.push(it2);
                                    break;
                                }
                            }
                        }
                    }
                    if (!evenAndOddHeaders) {
                        let has = false;
                        for (const pi of pits) {
                            if (pi.pages === UnitextPagesectionItemPages.DEFAULT) 
                                has = true;
                        }
                        if (!has && res.sections.length > 1) {
                            let sprev = res.sections[res.sections.length - 2];
                            for (const it of sprev.items) {
                                if (it.pages === UnitextPagesectionItemPages.DEFAULT && it.isFooter === (k > 0)) {
                                    let it2 = Utils.as(it.clone(), UnitextPagesectionItem);
                                    s.uSect.items.push(it2);
                                    break;
                                }
                            }
                        }
                    }
                    else {
                        let has = false;
                        for (const pi of pits) {
                            if (pi.pages === UnitextPagesectionItemPages.EVEN) 
                                has = true;
                        }
                        if (!has && res.sections.length > 1) {
                            let sprev = res.sections[res.sections.length - 2];
                            for (const it of sprev.items) {
                                if (it.pages === UnitextPagesectionItemPages.EVEN && it.isFooter === (k > 0)) {
                                    let it2 = Utils.as(it.clone(), UnitextPagesectionItem);
                                    s.uSect.items.push(it2);
                                    break;
                                }
                            }
                        }
                        has = false;
                        for (const pi of pits) {
                            if (pi.pages === UnitextPagesectionItemPages.DEFAULT || pi.pages === UnitextPagesectionItemPages.ODD) 
                                has = true;
                        }
                        if (!has && res.sections.length > 1) {
                            let sprev = res.sections[res.sections.length - 2];
                            for (const it of sprev.items) {
                                if (((it.pages === UnitextPagesectionItemPages.DEFAULT || it.pages === UnitextPagesectionItemPages.ODD)) && it.isFooter === (k > 0)) {
                                    let it2 = Utils.as(it.clone(), UnitextPagesectionItem);
                                    s.uSect.items.push(it2);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            res.styles = this.m_Styles.uStyles;
            if (!onlyForPureText) {
                let its = new Array();
                res.getAllItems(its, 0);
                let iii = new Array();
                let iiids = new Array();
                for (const i of its) {
                    if ((i instanceof UnitextImage) && i.id !== null && idImages.containsKey(i.id)) {
                        iii.push(Utils.as(i, UnitextImage));
                        i.tag = idImages.get(i.id);
                        iiids.push(Utils.asString(i.tag));
                        i.id = null;
                    }
                }
                if (iii.length > 0) {
                    for (const p of this.parts) {
                        let kkk = p.name;
                        if (!iiids.includes(kkk)) {
                            let ii = kkk.indexOf('/');
                            if (ii < 0) 
                                continue;
                            kkk = kkk.substring(ii + 1);
                            if (!iiids.includes(kkk)) 
                                continue;
                        }
                        let dat = p.getBytes();
                        if (dat !== null) {
                            for (const kp of iii) {
                                if ((Utils.asString(kp.tag)) === kkk) 
                                    kp.content = dat;
                            }
                        }
                    }
                }
            }
            return res;
        }
        if (xmlBook !== null && this.zipFile !== null) {
            let res = UnitextDocument._new493(FileFormat.XLSX, this.m_DataControls);
            let books = new Hashtable();
            for (const xml of xmlBook.child_nodes) {
                if (xml.local_name === "sheets") {
                    for (const xx of xml.child_nodes) {
                        let id = null;
                        let nams = null;
                        if (xx.attributes !== null) {
                            for (const a of xx.attributes) {
                                if (a.local_name === "name") 
                                    nams = a.value;
                                else if (a.local_name === "id") 
                                    id = a.value;
                            }
                        }
                        if (id !== null && nams !== null && !books.containsKey(nams)) 
                            books.put(id, nams);
                    }
                }
            }
            let sss = new Hashtable();
            for (const o of this.zipFile.entries) {
                let kkk = o.name;
                let ii = kkk.indexOf('/');
                if (ii < 0) 
                    continue;
                kkk = kkk.substring(ii + 1);
                let id = null;
                for (const kp of sheets.entries) {
                    if (kp.value === kkk) {
                        id = kp.key;
                        break;
                    }
                }
                if (id === null) 
                    continue;
                let sheetName = null;
                let wrapsheetName496 = new RefOutArgWrapper();
                books.tryGetValue(id, wrapsheetName496);
                sheetName = wrapsheetName496.value;
                let dat = o.getData();
                if (dat === null) 
                    continue;
                let xr = MyXmlReader.create(dat);
                let cnt = ExcelHelper.readSheet(xr, sharedStrings, sheetName, this.m_Styles, this.maxTableRows);
                if (cnt === null) 
                    continue;
                sss.put(id, cnt);
            }
            let ss = new Array();
            for (const kp of books.entries) {
                if (sss.containsKey(kp.key)) {
                    if (sss.get(kp.key) !== null) 
                        ss.push(sss.get(kp.key));
                }
            }
            if (ss.length === 0) 
                return null;
            if (ss.length === 1) 
                res.content = ss[0];
            else {
                let cnt = new UnitextContainer();
                for (let ii = 0; ii < ss.length; ii++) {
                    if (ii > 0) 
                        cnt.children.push(new UnitextPagebreak());
                    cnt.children.push(ss[ii]);
                }
                res.content = cnt;
            }
            res.optimize(false, pars);
            return res;
        }
        return null;
    }
    
    readFootnotes(stackList, end, rootStyle) {
        let node = stackList[stackList.length - 1];
        for (const xml of node.child_nodes) {
            if (xml.local_name === "footnote" || xml.local_name === "endnote") {
                let id = null;
                if (xml.attributes !== null) {
                    for (const a of xml.attributes) {
                        if (a.local_name === "id") {
                            id = a.value;
                            if (end) 
                                id = "end" + id;
                            break;
                        }
                    }
                }
                if (id === null || this.m_Footnotes.containsKey(id)) 
                    continue;
                let gen = new UnitextGen();
                gen.setStyle(rootStyle);
                stackList.push(xml);
                this.readNode(stackList, gen, rootStyle, -1);
                stackList.splice(stackList.length - 1, 1);
                let fi = gen.finish(true, null);
                if (fi !== null) 
                    this.m_Footnotes.put(id, fi);
            }
        }
    }
    
    readNode(stackNodes, gen, sfrag, pictTop) {
        if (stackNodes.length === 0) 
            return;
        let node = stackNodes[stackNodes.length - 1];
        for (const child of node.child_nodes) {
            if (child.local_name === "Fallback") {
                stackNodes.push(child);
                this.readNode(stackNodes, gen, sfrag, pictTop);
                stackNodes.splice(stackNodes.length - 1, 1);
                return;
            }
        }
        let delText = null;
        let proofErr = false;
        for (let i = 0; i < node.child_nodes.length; i++) {
            let child = node.child_nodes[i];
            let locname = child.local_name;
            if (Utils.isNullOrEmpty(locname)) 
                continue;
            if (locname === "#text") 
                continue;
            if (node.local_name === "p") {
            }
            if (child.local_name === "r") {
            }
            if (i === 7) {
            }
            if (proofErr) 
                continue;
            switch (locname) { 
            case "del": {
                break;
            }
            case "delText": {
                break;
            }
            case "moveFrom": {
                break;
            }
            case "AlternateContent": {
                for (const x of child.child_nodes) {
                    if (x.local_name === "Choice") {
                        stackNodes.push(x);
                        this.readNode(stackNodes, gen, sfrag, pictTop);
                        stackNodes.splice(stackNodes.length - 1, 1);
                        break;
                    }
                }
                break;
            }
            case "t": {
                let text = child.inner_text;
                if (text === "НЕ ВЫДЕЛ") {
                }
                if (Utils.isNullOrEmpty(text) || text === delText) 
                    this.m_lastChar = ' ';
                else {
                    if (delText !== null) {
                        if (text.startsWith(delText)) 
                            text = text.substring(delText.length);
                    }
                    if (sfrag !== null && sfrag.style !== null && sfrag.style.getAttr("upper-case") === "true") 
                        text = text.toUpperCase();
                    this.m_lastChar = text[text.length - 1];
                    gen.appendText(text, false);
                    if (text.startsWith("Дого")) {
                    }
                }
                delText = null;
                break;
            }
            case "sym": {
                let ch = null;
                if (child.attributes !== null) {
                    let font = null;
                    for (const a of child.attributes) {
                        if (a.local_name === "font") {
                            font = a.value;
                            break;
                        }
                    }
                    for (const a of child.attributes) {
                        if (a.local_name === "char") {
                            let nn = 0;
                            for (let jj = 0; jj < a.value.length; jj++) {
                                let dig = a.value.charCodeAt(jj);
                                if (dig >= 0x30 && dig <= 0x39) 
                                    nn = ((nn * 16) + dig) - 0x30;
                                else if (dig >= 0x41 && dig <= 0x46) 
                                    nn = (((nn * 16) + dig) - 0x41) + 10;
                                else if (dig >= 0x61 && dig <= 0x66) 
                                    nn = (((nn * 16) + dig) - 0x61) + 10;
                            }
                            if (a.value[0] === 'F') 
                                nn -= 0xF000;
                            let uch = String.fromCharCode(0);
                            if (Utils.compareStrings((font != null ? font : ""), "Symbol", true) === 0) 
                                uch = SymbolHelper.getUnicode(nn);
                            else 
                                uch = WingdingsHelper.getUnicode(nn);
                            if (uch === (String.fromCharCode(0))) 
                                ch = " ";
                            else 
                                ch = (uch);
                        }
                    }
                }
                if (ch !== null) {
                    gen.appendText(ch, false);
                    this.m_lastChar = ch[0];
                }
                break;
            }
            case "cr": {
                gen.appendNewline(false, false);
                break;
            }
            case "commentRangeStart": {
                if (child.attributes !== null) {
                    for (const a of child.attributes) {
                        if (a.local_name === "id") {
                            let cmt = null;
                            let wrapcmt497 = new RefOutArgWrapper();
                            let inoutres498 = this.m_Comments.tryGetValue(Utils.notNull(a.value, ""), wrapcmt497);
                            cmt = wrapcmt497.value;
                            if (inoutres498) {
                                if (cmt.id === null) 
                                    cmt.id = "comment" + a.value;
                                gen.append(cmt, null, -1, false);
                            }
                        }
                    }
                }
                break;
            }
            case "commentRangeEnd": {
                if (child.attributes !== null) {
                    for (const a of child.attributes) {
                        if (a.local_name === "id") {
                            let cmt = null;
                            let wrapcmt500 = new RefOutArgWrapper();
                            let inoutres501 = this.m_Comments.tryGetValue(Utils.notNull(a.value, ""), wrapcmt500);
                            cmt = wrapcmt500.value;
                            if (inoutres501) {
                                let ecmt = UnitextComment._new499(cmt.id + "_end", cmt.id, true);
                                cmt.twinId = ecmt.id;
                                ecmt.text = cmt.text;
                                ecmt.author = cmt.author;
                                gen.append(ecmt, null, -1, false);
                                this.m_Comments.remove(a.value);
                            }
                        }
                    }
                }
                break;
            }
            case "br": {
                let val = null;
                if (child.attributes !== null && child.attributes.length > 0 && child.attributes[0].name.includes("type")) 
                    val = child.attributes[0].value;
                if (val === "page") 
                    gen.appendPagebreak();
                else {
                    let isNewLine = false;
                    if (gen.lastNotSpaceChar === ':' || gen.lastNotSpaceChar === '.') 
                        isNewLine = true;
                    if (isNewLine) 
                        gen.appendNewline(false, true);
                    else 
                        gen.appendNewline(false, true);
                }
                break;
            }
            case "pict": {
                let img1 = null;
                for (const x of child.child_nodes) {
                    if (x.local_name === "binData") {
                        if (img1 === null) 
                            img1 = new UnitextImage();
                        try {
                            img1.content = Utils.decodeBase64(x.inner_text);
                        } catch (ex) {
                        }
                        gen.append(img1, null, -1, false);
                    }
                    else if (x.local_name === "shape" && x.attributes !== null) {
                        for (const a of x.attributes) {
                            if (a.local_name === "style" && a.value !== null) {
                                if (img1 === null) 
                                    img1 = new UnitextImage();
                                DocxToText._setImageSize(img1, a.value);
                            }
                        }
                    }
                }
                if (img1 !== null && img1.content !== null) 
                    return;
                let gg = new UnitextGen();
                gg.appendPagesection(this.m_CurSection);
                stackNodes.push(child);
                this.readNode(stackNodes, gg, sfrag, pictTop);
                stackNodes.splice(stackNodes.length - 1, 1);
                let it = gg.finish(true, null);
                if (it === null) 
                    break;
                if (it instanceof UnitextContainer) 
                    it.typ = UnitextContainerType.SHAPE;
                else {
                    let cnt = UnitextContainer._new94(UnitextContainerType.SHAPE);
                    cnt.children.push(it);
                    it = cnt.optimize(false, null);
                }
                if (it !== null) {
                    gen.append(it, null, -1, false);
                    gen.appendNewline(false, false);
                }
                break;
            }
            case "tab": {
                if (node.local_name === "tabs") {
                }
                else 
                    gen.appendText("\t", false);
                break;
            }
            case "sectPr": {
                this.m_Sections[this.m_Sections.length - 1].load(child);
                let se = new DocSection();
                this.m_Sections.push(se);
                se.uSect.id = ("ps" + this.m_Sections.length);
                this.m_CurSection = se.uSect;
                gen.appendPagesection(this.m_CurSection);
                break;
            }
            case "tbl": {
                let tbl = new DocTable();
                stackNodes.push(child);
                tbl.read(this, sfrag, stackNodes);
                stackNodes.splice(stackNodes.length - 1, 1);
                let tab = tbl.createUni(this.maxTableRows);
                if (tab !== null) 
                    gen.append(tab, null, -1, false);
                break;
            }
            case "bookmarkStart": {
                for (const a of child.attributes) {
                    if (a.local_name === "name") {
                        if (a.value === "_GoBack") 
                            continue;
                        let mi = new UnitextMisc();
                        mi.typ = UnitextMiscType.ANCHOR;
                        mi.id = a.value;
                        if (mi.id.endsWith("54874551")) {
                        }
                        if (mi.id === "_GoBack") {
                        }
                        gen.append(mi, null, -1, false);
                        break;
                    }
                }
                break;
            }
            case "fldSimple": {
                let ggg1 = new UnitextGen();
                ggg1.appendPagesection(this.m_CurSection);
                for (const a of child.attributes) {
                    if (a.local_name === "instr") {
                        let vvv = a.value.trim();
                        if (vvv.startsWith("SEQ")) 
                            ggg1.textGenRegime = true;
                    }
                }
                stackNodes.push(child);
                this.readNode(stackNodes, ggg1, sfrag, pictTop);
                stackNodes.splice(stackNodes.length - 1, 1);
                let ggt = ggg1.finish(true, null);
                if (ggg1.textGenRegime && ggt !== null) 
                    gen.append(ggt, null, -1, false);
                else {
                    let txt = (ggt === null ? null : UnitextHelper.getPlaintext(ggt, null));
                    if (!Utils.isNullOrEmpty(txt) && !gen.lastText.endsWith(txt)) 
                        gen.appendText(txt, false);
                }
                break;
            }
            case "hyperlink": 
            case "hlink": {
                let ok = false;
                if (child.attributes !== null) {
                    for (const a of child.attributes) {
                        if (a.local_name === "id") {
                            if (this.m_Hyperlinks.containsKey(a.value)) {
                                let ggg = new UnitextGen();
                                ggg.appendPagesection(this.m_CurSection);
                                stackNodes.push(child);
                                this.readNode(stackNodes, ggg, sfrag, pictTop);
                                stackNodes.splice(stackNodes.length - 1, 1);
                                let cnt = ggg.finish(true, null);
                                if (cnt !== null) {
                                    if (this.m_Hyperlinks.containsKey(Utils.notNull(a.value, ""))) {
                                        try {
                                            let hr = UnitextHyperlink._new59(this.m_Hyperlinks.get(a.value).toString());
                                            hr.content = cnt;
                                            gen.append(hr, null, -1, false);
                                        } catch (xx) {
                                            gen.append(cnt, null, -1, false);
                                        }
                                    }
                                    else 
                                        gen.append(cnt, null, -1, false);
                                    ok = true;
                                    break;
                                }
                            }
                        }
                        else if (a.local_name === "dest" || a.local_name === "anchor") {
                            let ggg = new UnitextGen();
                            ggg.appendPagesection(this.m_CurSection);
                            stackNodes.push(child);
                            this.readNode(stackNodes, ggg, sfrag, pictTop);
                            stackNodes.splice(stackNodes.length - 1, 1);
                            let cnt = ggg.finish(true, null);
                            if (cnt !== null) {
                                let hr = UnitextHyperlink._new59(a.value);
                                if (a.local_name === "anchor") 
                                    hr.isInternal = true;
                                hr.content = cnt;
                                gen.append(hr, null, -1, false);
                                ok = true;
                                break;
                            }
                        }
                    }
                }
                if (!ok) {
                    stackNodes.push(child);
                    this.readNode(stackNodes, gen, sfrag, pictTop);
                    stackNodes.splice(stackNodes.length - 1, 1);
                }
                break;
            }
            case "p": {
                let numStyle = null;
                let lev = 0;
                let numTxtStyle = null;
                let para = null;
                if (sfrag !== null) {
                    para = UnitextStyledFragment._new505(sfrag, UnitextStyledFragmentType.PARAGRAPH);
                    sfrag.children.push(para);
                }
                let defParaStyle = null;
                if (this.m_Styles.defStyles.containsKey("paragraph")) {
                    defParaStyle = this.m_Styles.registerStyle(this.m_Styles.defStyles.get("paragraph"));
                    if (para !== null) 
                        para.style = defParaStyle;
                }
                let pgen = new UnitextGen();
                pgen.setStyle(para);
                pgen.appendPagesection(this.m_CurSection);
                let hidden = false;
                let numExStyle = null;
                for (const xx of child.child_nodes) {
                    if (xx.local_name === "pPr") {
                        if (para !== null) {
                            let ust0 = new UnitextStyle();
                            if (defParaStyle !== null) 
                                defParaStyle.copyTo(ust0);
                            this.m_Styles.readUnitextStyle(xx, ust0, false);
                            ust0.removeInheritAttrs(para.parent);
                            if (ust0.getAttr("font-size") === "1pt") {
                                hidden = true;
                                if (sfrag !== null) 
                                    Utils.removeItem(sfrag.children, sfrag);
                                break;
                            }
                            para.style = this.m_Styles.registerStyle(ust0);
                        }
                        let id = null;
                        for (const xxx of xx.child_nodes) {
                            if (xxx.local_name === "numPr") {
                                for (const chh of xxx.child_nodes) {
                                    if (chh.local_name === "numId" && chh.attributes !== null && chh.attributes.length === 1) 
                                        id = chh.attributes[0].value;
                                    else if (chh.local_name === "ilvl" && chh.attributes !== null && chh.attributes.length === 1) {
                                        let wraplev506 = new RefOutArgWrapper();
                                        Utils.tryParseInt(Utils.notNull(chh.attributes[0].value, ""), wraplev506);
                                        lev = wraplev506.value;
                                    }
                                }
                            }
                            else if (xxx.local_name === "listPr") {
                                numStyle = DocNumStyles.readNumberStyle(xxx);
                                lev = numStyle.lvl;
                            }
                            else if (xxx.local_name === "pStyle") {
                                numTxtStyle = this.m_Styles.getStyle(xxx, "val");
                                if (numTxtStyle !== null && numTxtStyle.numId !== null) {
                                    if (id !== null || lev > 0) {
                                    }
                                    else {
                                        id = numTxtStyle.numId;
                                        lev = numTxtStyle.numLvl;
                                    }
                                }
                            }
                            else if (xxx.local_name === "pageBreakBefore") 
                                pgen.appendPagebreak();
                            else if (xxx.local_name === "rPr") {
                                numExStyle = new UnitextStyle();
                                this.m_Styles.readUnitextStyle(xxx, numExStyle, false);
                            }
                        }
                        numStyle = this.m_NumStyles.getStyle(id);
                    }
                }
                if (hidden) 
                    break;
                gen.appendPagesection(this.m_CurSection);
                stackNodes.push(child);
                this.readNode(stackNodes, pgen, para, pictTop);
                pgen.textGenRegime = false;
                if (pictTop < 0) 
                    pgen.appendNewline(false, false);
                let fi = pgen.finish(false, null);
                if (fi !== null) {
                    if ((numStyle !== null && numExStyle !== null && para !== null) && para.style !== null) {
                        let npara = UnitextStyledFragment._new505(para, UnitextStyledFragmentType.INLINE);
                        numExStyle.removeInheritAttrs(para);
                        npara.style = this.m_Styles.registerStyle(numExStyle);
                        para.children.push(npara);
                        gen.setNumStyle(npara);
                    }
                    gen.append(fi, numStyle, lev, false);
                    gen.setNumStyle(null);
                }
                stackNodes.splice(stackNodes.length - 1, 1);
                break;
            }
            case "r": {
                if (child.attributes !== null) {
                    for (const a of child.attributes) {
                        if (a.local_name === "rsidRPr") {
                            if (!Utils.isNullOrEmpty(this.m_lastRSID) && Utils.compareStrings(a.value, this.m_lastRSID, true) !== 0) {
                                this.m_lastRSID = a.local_name;
                                if ((gen.lastChar.charCodeAt(0)) !== 0 && !Utils.isWhitespace(gen.lastChar)) 
                                    gen.appendText(" ", false);
                            }
                        }
                    }
                }
                let ust = null;
                let isSup = -1;
                let fldCharBegin = false;
                let hidden2 = false;
                let gtr = gen.textGenRegime;
                for (const rpr of child.child_nodes) {
                    if (rpr.local_name === "rPr") {
                        ust = new UnitextStyle();
                        this.m_Styles.readUnitextStyle(rpr, ust, false);
                        if (sfrag !== null) 
                            ust.removeInheritAttrs(sfrag);
                        if (ust.getAttr("font-size") === "1pt") {
                            hidden2 = true;
                            break;
                        }
                        ust = this.m_Styles.registerStyle(ust);
                        for (const xxx of rpr.child_nodes) {
                            if (xxx.local_name === "vertAlign" && xxx.attributes !== null && xxx.attributes.length > 0) {
                                if (xxx.attributes[0].value === "superscript") 
                                    isSup = 1;
                                else if (xxx.attributes[0].value === "subscript") 
                                    isSup = 0;
                            }
                        }
                    }
                    else if (rpr.local_name === "fldChar") {
                        for (const aa of rpr.attributes) {
                            if (aa.local_name === "fldCharType" && aa.value === "begin") 
                                fldCharBegin = true;
                        }
                    }
                }
                if (hidden2) 
                    break;
                if (fldCharBegin) {
                    let gg1 = new UnitextGen();
                    let anchor = null;
                    gg1.appendPagesection(this.m_CurSection);
                    let ii = -1;
                    let instrText = null;
                    for (let j = i; j < node.child_nodes.length; j++) {
                        let chh = node.child_nodes[j];
                        if (chh.local_name === "bookmarkStart") {
                            for (const a of chh.attributes) {
                                if (a.local_name === "name") {
                                    if (a.value === "_GoBack") 
                                        continue;
                                    let mi = new UnitextMisc();
                                    mi.typ = UnitextMiscType.ANCHOR;
                                    mi.id = a.value;
                                    gen.append(mi, null, -1, false);
                                    break;
                                }
                            }
                            continue;
                        }
                        if (chh.local_name !== "r") 
                            continue;
                        for (const rpr of chh.child_nodes) {
                            if (rpr.local_name === "instrText" || rpr.local_name === "instr") {
                                if (instrText === null) 
                                    instrText = new StringBuilder();
                                instrText.append(Utils.notNull(rpr.inner_text, ""));
                            }
                            else if (rpr.local_name === "fldChar") {
                                for (const aa of rpr.attributes) {
                                    if (aa.local_name === "fldCharType" && aa.value === "end") 
                                        fldCharBegin = false;
                                }
                            }
                        }
                        stackNodes.push(chh);
                        this.readNode(stackNodes, gg1, sfrag, pictTop);
                        stackNodes.splice(stackNodes.length - 1, 1);
                        ii = j;
                        if (!fldCharBegin) 
                            break;
                    }
                    if (instrText !== null) {
                        let vvv = instrText.toString().trim();
                        if (vvv.startsWith("SEQ ")) 
                            gg1.textGenRegime = true;
                        let iii = vvv.indexOf("REF ");
                        if (iii >= 0 && !vvv.includes("STYLEREF")) {
                            vvv = vvv.substring(iii + 4);
                            for (let k = 1; k < vvv.length; k++) {
                                if (Utils.isWhitespace(vvv[k])) {
                                    vvv = vvv.substring(0, 0 + k);
                                    break;
                                }
                            }
                            anchor = vvv;
                        }
                    }
                    if (anchor !== null) {
                        let hy = UnitextHyperlink._new508(true, anchor);
                        hy.content = gg1.finish(false, null);
                        gen.append(hy, null, -1, false);
                        i = ii;
                        break;
                    }
                    if (gg1.textGenRegime) {
                        let tmp = gg1.finish(true, null);
                        if (tmp !== null) {
                            gen.append(tmp, null, -1, false);
                            i = ii;
                            break;
                        }
                        else 
                            gen.textGenRegime = true;
                    }
                }
                if (isSup >= 0) {
                    let gg1 = new UnitextGen();
                    gg1.appendPagesection(this.m_CurSection);
                    stackNodes.push(child);
                    this.readNode(stackNodes, gg1, sfrag, pictTop);
                    stackNodes.splice(stackNodes.length - 1, 1);
                    let tmp = gg1.finish(true, null);
                    if (tmp === null) 
                        break;
                    let tt = UnitextHelper.getPlaintext(tmp, null);
                    if (tt === null) 
                        tt = "";
                    tt = tt.trim();
                    if (tt.startsWith("<") && tt.endsWith(">")) 
                        tt = tt.substring(1, 1 + tt.length - 2);
                    if (tt.length > 0 && (tt.length < 10)) {
                        let tp = UnitextPlaintext._new58(tt, (isSup === 0 ? UnitextPlaintextType.SUB : UnitextPlaintextType.SUP));
                        gen.append(tp, null, -1, false);
                        break;
                    }
                }
                stackNodes.push(child);
                if (ust === null || sfrag === null) 
                    this.readNode(stackNodes, gen, sfrag, pictTop);
                else {
                    let ifr = UnitextStyledFragment._new505(sfrag, UnitextStyledFragmentType.INLINE);
                    ifr.style = ust;
                    let gg1 = new UnitextGen();
                    gg1.setStyle(ifr);
                    gg1.appendPagesection(this.m_CurSection);
                    gg1.textGenRegime = gen.textGenRegime;
                    this.readNode(stackNodes, gg1, ifr, pictTop);
                    let v = gg1.finish(false, null);
                    if (v !== null) {
                        gen.append(v, null, -1, false);
                        sfrag.children.push(ifr);
                        gen.textGenRegime = false;
                    }
                }
                stackNodes.splice(stackNodes.length - 1, 1);
                break;
            }
            case "footnoteReference": {
                delText = null;
                if (child.attributes === null) 
                    break;
                for (const a of child.attributes) {
                    if (a.local_name === "customMarkFollows" && a.value === "1" && ((i + 1) < node.child_nodes.length)) {
                        let ch1 = node.child_nodes[i + 1];
                        if (ch1.local_name === "t") {
                            delText = ch1.inner_text;
                            i++;
                            break;
                        }
                    }
                }
                for (const a of child.attributes) {
                    if (a.local_name === "id" && this.m_Footnotes.containsKey(a.value)) {
                        let cnt = this.m_Footnotes.get(a.value);
                        if (!Utils.isNullOrEmpty(delText)) {
                            let pl = Utils.as(cnt, UnitextPlaintext);
                            if (pl !== null && pl.text.startsWith(delText)) 
                                pl.text = pl.text.substring(delText.length).trim();
                        }
                        if ((cnt.m_StyledFrag !== null && cnt.m_StyledFrag.parent === null && (cnt instanceof UnitextContainer)) && sfrag !== null) {
                            let cc = Utils.as(cnt, UnitextContainer);
                            if (cc.children.length === 1 && (cc.children[0] instanceof UnitextContainer)) {
                                cnt = cc.children[0];
                                if (cnt.m_StyledFrag !== null && cnt.m_StyledFrag.parent !== null) {
                                    cnt.m_StyledFrag.typ = UnitextStyledFragmentType.FOOTNOTE;
                                    Utils.removeItem(cnt.m_StyledFrag.parent.children, cnt.m_StyledFrag);
                                    sfrag.children.push(cnt.m_StyledFrag);
                                    cnt.m_StyledFrag.parent = sfrag;
                                }
                            }
                        }
                        gen.append(UnitextFootnote._new329(cnt, delText), null, -1, false);
                        break;
                    }
                }
                break;
            }
            case "endnoteReference": {
                if (child.attributes !== null) {
                    for (const a of child.attributes) {
                        if (a.local_name === "id" && this.m_Footnotes.containsKey("end" + a.value)) {
                            let cnt = this.m_Footnotes.get("end" + a.value);
                            if ((cnt.m_StyledFrag !== null && cnt.m_StyledFrag.parent === null && (cnt instanceof UnitextContainer)) && sfrag !== null) {
                                let cc = Utils.as(cnt, UnitextContainer);
                                if (cc.children.length === 1 && (cc.children[0] instanceof UnitextContainer)) {
                                    cnt = cc.children[0];
                                    if (cnt.m_StyledFrag !== null && cnt.m_StyledFrag.parent !== null) {
                                        cnt.m_StyledFrag.typ = UnitextStyledFragmentType.FOOTNOTE;
                                        Utils.removeItem(cnt.m_StyledFrag.parent.children, cnt.m_StyledFrag);
                                        sfrag.children.push(cnt.m_StyledFrag);
                                        cnt.m_StyledFrag.parent = sfrag;
                                    }
                                }
                            }
                            gen.append(UnitextFootnote._new284(cnt, true), null, -1, false);
                            break;
                        }
                    }
                }
                break;
            }
            case "footnote": 
            case "endnote": {
                let gg2 = new UnitextGen();
                gg2.appendPagesection(this.m_CurSection);
                stackNodes.push(child);
                this.readNode(stackNodes, gg2, sfrag, pictTop);
                stackNodes.splice(stackNodes.length - 1, 1);
                let tmp2 = gg2.finish(true, null);
                if (tmp2 === null) 
                    break;
                let fn = UnitextFootnote._new513(locname === "endnote", tmp2);
                gen.append(fn, null, -1, false);
                break;
            }
            case "blip": {
                if (child.attributes !== null) {
                    for (const a of child.attributes) {
                        if (a.local_name === "embed") {
                            let img = UnitextImage._new96(a.value);
                            gen.append(img, null, -1, false);
                            for (let ii = stackNodes.length - 1; ii >= 0; ii--) {
                                for (const xxx of stackNodes[ii].child_nodes) {
                                    if (xxx.local_name === "extent" && xxx.attributes !== null) {
                                        let xw = 0;
                                        let yh = 0;
                                        for (const aa of xxx.attributes) {
                                            if (aa.local_name === "cx") {
                                                let wrapxw515 = new RefOutArgWrapper();
                                                Utils.tryParseInt(aa.value, wrapxw515);
                                                xw = wrapxw515.value;
                                            }
                                            else if (aa.local_name === "cy") {
                                                let wrapyh516 = new RefOutArgWrapper();
                                                Utils.tryParseInt(aa.value, wrapyh516);
                                                yh = wrapyh516.value;
                                            }
                                        }
                                        if (xw > 0 && yh > 0) {
                                            img.width = ((String(Utils.intDiv(xw * 72, 914400))) + "pt");
                                            img.height = ((String(Utils.intDiv(yh * 72, 914400))) + "pt");
                                        }
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
                break;
            }
            case "imagedata": {
                if (child.attributes !== null) {
                    for (const a of child.attributes) {
                        if (a.local_name === "id") {
                            let img = UnitextImage._new96(a.value);
                            gen.append(img, null, -1, false);
                            if (node.local_name === "shape" && node.attributes !== null) {
                                for (const aa of node.attributes) {
                                    if (aa.local_name === "style") {
                                        DocxToText._setImageSize(img, aa.value);
                                        break;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
                break;
            }
            case "OLEObject": {
                if (child.attributes !== null) {
                    for (const a of child.attributes) {
                        if (a.local_name === "id") {
                            if (this.m_Embeds.containsKey(a.value)) {
                                gen.append(this.m_Embeds.get(a.value), null, -1, false);
                                break;
                            }
                        }
                    }
                }
                break;
            }
            case "sdt": {
                let tag = null;
                let valu = null;
                let ust1 = null;
                for (const x of child.child_nodes) {
                    if (x.local_name === "sdtPr") {
                        for (const xx of x.child_nodes) {
                            if (xx.local_name === "tag") 
                                tag = DocxToText._getAttrValue(xx, "val");
                            else if (xx.local_name === "date") 
                                valu = DocxToText._getAttrValue(xx, "fullDate");
                        }
                        ust1 = new UnitextStyle();
                        this.m_Styles.readUnitextStyle(x, ust1, false);
                        if (sfrag !== null) 
                            ust1.removeInheritAttrs(sfrag);
                        ust1 = this.m_Styles.registerStyle(ust1);
                    }
                }
                for (const x of child.child_nodes) {
                    if (x.local_name === "sdtContent") {
                        let sfrag1 = sfrag;
                        if (ust1 !== null) {
                            sfrag1 = UnitextStyledFragment._new518(UnitextStyledFragmentType.INLINE, ust1, sfrag1);
                            sfrag.children.push(sfrag1);
                        }
                        let gg3 = new UnitextGen();
                        gg3.setStyle(sfrag1);
                        gg3.appendPagesection(this.m_CurSection);
                        stackNodes.push(x);
                        this.readNode(stackNodes, gg3, sfrag1, pictTop);
                        stackNodes.splice(stackNodes.length - 1, 1);
                        let tmp3 = gg3.finish(true, null);
                        if (tmp3 === null) 
                            break;
                        if (valu === null) 
                            valu = UnitextHelper.getPlaintext(tmp3, null);
                        if (tmp3 instanceof UnitextContainer) 
                            tmp3.typ = UnitextContainerType.CONTENTCONTROL;
                        else {
                            let ccc = UnitextContainer._new451(UnitextContainerType.CONTENTCONTROL, sfrag1);
                            ccc.children.push(tmp3);
                            tmp3.parent = ccc;
                            tmp3 = ccc;
                        }
                        tmp3.htmlTitle = ("Content control: " + ((tag != null ? tag : "?")));
                        tmp3.data = valu;
                        tmp3.id = tag;
                        gen.append(tmp3, null, -1, false);
                    }
                }
                if (tag !== null && valu !== null) {
                    if (!this.m_DataControls.containsKey(tag)) 
                        this.m_DataControls.put(tag, valu);
                }
                break;
            }
            case "ffData": {
                let nam1 = null;
                for (const x of child.child_nodes) {
                    if (x.local_name === "name") 
                        nam1 = DocxToText._getAttrValue(x, "val");
                    else if (x.local_name === "textInput") {
                        for (const xx of x.child_nodes) {
                            if (xx.local_name === "default") {
                                let val1 = DocxToText._getAttrValue(xx, "val");
                                if (val1 !== null && nam1 !== null) {
                                    if (!this.m_DataControls.containsKey(nam1)) 
                                        this.m_DataControls.put(nam1, val1);
                                }
                            }
                        }
                    }
                }
                break;
            }
            case "rect": {
                for (const a of child.attributes) {
                    if (a.local_name === "style") {
                        if (pictTop < 0) 
                            pictTop = 0;
                        for (const s of Utils.splitString(a.value, ';', false)) {
                            let ii = s.indexOf(':');
                            if (ii <= 0) 
                                continue;
                            let key = s.substring(0, 0 + ii).trim().toLowerCase();
                            let va = s.substring(ii + 1).trim();
                            if (key === "position") {
                                if (va !== "absolute") 
                                    break;
                            }
                            if (key !== "top") 
                                continue;
                            for (let j = va.length - 1; j > 0; j--) {
                                if (Utils.isDigit(va[j])) {
                                    let wrapii520 = new RefOutArgWrapper();
                                    let inoutres521 = Utils.tryParseInt(va.substring(0, 0 + j + 1), wrapii520);
                                    ii = wrapii520.value;
                                    if (!inoutres521) 
                                        break;
                                    if (ii > pictTop) {
                                        gen.appendNewline(true, false);
                                        pictTop = ii;
                                    }
                                    break;
                                }
                            }
                            break;
                        }
                    }
                }
                stackNodes.push(child);
                this.readNode(stackNodes, gen, sfrag, pictTop);
                stackNodes.splice(stackNodes.length - 1, 1);
                break;
            }
            case "drawing": {
                let gg4 = new UnitextGen();
                gg4.setStyle(sfrag);
                gg4.appendPagesection(this.m_CurSection);
                stackNodes.push(child);
                this.readNode(stackNodes, gg4, sfrag, pictTop);
                stackNodes.splice(stackNodes.length - 1, 1);
                let drsh = UnitextContainer._new451(UnitextContainerType.SHAPE, sfrag);
                let tgg4 = gg4.finish(false, null);
                if (tgg4 !== null) 
                    drsh.children.push(tgg4);
                gen.append(drsh, null, -1, false);
                break;
            }
            case "oMath": {
                if (this.setFormulasAsImage) {
                    gen.append(new UnitextImage(), null, -1, false);
                    break;
                }
                let gg5 = new UnitextGen();
                gg5.setStyle(sfrag);
                gg5.appendPagesection(this.m_CurSection);
                stackNodes.push(child);
                this.readNode(stackNodes, gg5, sfrag, pictTop);
                stackNodes.splice(stackNodes.length - 1, 1);
                let drsh5 = UnitextContainer._new451(UnitextContainerType.FORMULA, sfrag);
                let nary = DocxToText._calcNary(child);
                if (nary > 0) 
                    drsh5.data = nary.toString();
                let tgg5 = gg5.finish(false, null);
                if (tgg5 !== null) {
                    let its = new Array();
                    tgg5.getAllItems(its, 0);
                    for (const ii of its) {
                        if ((ii instanceof UnitextNewline) || (ii instanceof UnitextPagebreak)) 
                            tgg5.replaceChild(ii, UnitextPlaintext._new57(" "));
                    }
                    drsh5.children.push(tgg5);
                }
                gen.append(drsh5, null, -1, false);
                break;
            }
            default: {
                if ((pictTop < 0) && child.local_name === "txbxContent") 
                    gen.appendText(" ", false);
                stackNodes.push(child);
                this.readNode(stackNodes, gen, sfrag, pictTop);
                stackNodes.splice(stackNodes.length - 1, 1);
                if ((pictTop < 0) && child.local_name === "txbxContent") 
                    gen.appendText(" ", false);
                break;
            }
            }
        }
    }
    
    static _calcNary(xml) {
        let res = 0;
        if (xml.local_name === "nary") 
            res++;
        for (const xx of xml.child_nodes) {
            res += DocxToText._calcNary(xx);
        }
        return res;
    }
    
    static _setImageSize(img, style) {
        let ii = style.indexOf("width:");
        if (ii >= 0) {
            img.width = style.substring(ii + 6).trim();
            if ((((ii = img.width.indexOf(';')))) > 0) 
                img.width = img.width.substring(0, 0 + ii).trim();
        }
        ii = style.indexOf("height:");
        if (ii >= 0) {
            img.height = style.substring(ii + 7).trim();
            if ((((ii = img.height.indexOf(';')))) > 0) 
                img.height = img.height.substring(0, 0 + ii).trim();
        }
    }
    
    static _getAttrValue(n, attrName) {
        if (n.attributes !== null) {
            for (const a of n.attributes) {
                if (a.local_name === attrName) 
                    return a.value;
            }
        }
        return null;
    }
}


module.exports = DocxToText