UNPKG

typesxml

Version:

Open source XML library written in TypeScript

220 lines 6.65 kB
/******************************************************************************* * Copyright (c) 2023-2026 Maxprograms. * * This program and the accompanying materials * are made available under the terms of the Eclipse License 1.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/epl-v10.html * * Contributors: * Maxprograms - initial API and implementation *******************************************************************************/ import { XMLUtils } from "../XMLUtils.js"; export class XmlEventStreamWriter { output; encoding; autoClose; elementStack; catalog; grammar; xmlVersion; inCDATA; dtdOpen; dtdHasSubset; completed; constructor(output, encoding = "utf8", autoClose = true) { this.output = output; this.encoding = encoding; this.autoClose = autoClose; this.elementStack = new Array(); this.xmlVersion = "1.0"; this.inCDATA = false; this.dtdOpen = false; this.dtdHasSubset = false; this.completed = false; this.output.setDefaultEncoding(this.encoding); } initialize() { this.elementStack = new Array(); this.xmlVersion = "1.0"; this.inCDATA = false; this.dtdOpen = false; this.dtdHasSubset = false; this.completed = false; } setCatalog(catalog) { this.catalog = catalog; } setGrammar(grammar) { this.grammar = grammar; } getGrammar() { return this.grammar; } getCurrentText() { return ''; } startDocument() { return; } endDocument() { this.closePendingStartTag(); this.elementStack = new Array(); if (this.autoClose && !this.completed) { this.completed = true; this.output.end(); } } xmlDeclaration(version, encoding, standalone) { this.xmlVersion = version === "" ? "1.0" : version; let declaration = "<?xml"; if (version !== "") { declaration += " version=\"" + version + "\""; } if (encoding !== "") { declaration += " encoding=\"" + encoding + "\""; } if (standalone !== undefined) { declaration += " standalone=\"" + standalone + "\""; } declaration += "?>"; this.write(declaration); } startElement(name, atts) { this.prepareForChildContent(); let buffer = "<" + name; for (let index = 0; index < atts.length; index++) { const attribute = atts[index]; buffer += " " + attribute.toString(); } this.write(buffer); const frame = { name: name, startTagOpen: true, hasContent: false }; this.elementStack.push(frame); } endElement(name) { if (this.elementStack.length === 0) { throw new Error("Unexpected endElement event for \"" + name + "\""); } const frame = this.elementStack.pop(); if (frame.name !== name) { throw new Error("Mismatched endElement event: expected \"" + frame.name + "\" but received \"" + name + "\""); } if (frame.startTagOpen) { this.write("/>"); } else { this.write("</" + name + ">"); } } internalSubset(declaration) { if (!this.dtdOpen) { throw new Error("Internal subset event received outside of DTD"); } this.write(" [" + declaration + "]"); this.dtdHasSubset = true; } characters(ch) { this.prepareForTextContent(); if (this.inCDATA) { this.write(ch); return; } XMLUtils.ensureValidXmlCharacters(this.xmlVersion, ch, "character data"); const escaped = XMLUtils.cleanString(ch); this.write(escaped); } ignorableWhitespace(ch) { this.characters(ch); } comment(ch) { this.prepareForTextContent(); this.write("<!--" + ch + "-->"); } processingInstruction(target, data) { this.prepareForTextContent(); let instruction = "<?" + target; if (data.length > 0) { instruction += " " + data; } instruction += "?>"; this.write(instruction); } startCDATA() { this.prepareForTextContent(); this.write("<![CDATA["); this.inCDATA = true; } endCDATA() { if (!this.inCDATA) { throw new Error("endCDATA event received without matching startCDATA"); } this.write("]]>"); this.inCDATA = false; } startDTD(name, publicId, systemId) { this.closePendingStartTag(); let declaration = "<!DOCTYPE " + name; if (publicId !== "" && systemId !== "") { declaration += " PUBLIC \"" + publicId + "\" \"" + systemId + "\""; } else if (systemId !== "") { declaration += " SYSTEM \"" + systemId + "\""; } else if (publicId !== "") { declaration += " PUBLIC \"" + publicId + "\""; } this.write(declaration); this.dtdOpen = true; this.dtdHasSubset = false; } endDTD() { if (!this.dtdOpen) { return; } this.write(">"); this.dtdOpen = false; } skippedEntity(name) { this.prepareForTextContent(); this.write("&" + name + ";"); } prepareForChildContent() { if (this.elementStack.length === 0) { return; } const current = this.elementStack[this.elementStack.length - 1]; if (current.startTagOpen) { this.write(">"); current.startTagOpen = false; } current.hasContent = true; } prepareForTextContent() { if (this.elementStack.length > 0) { const current = this.elementStack[this.elementStack.length - 1]; if (current.startTagOpen) { this.write(">"); current.startTagOpen = false; } current.hasContent = true; } } closePendingStartTag() { if (this.elementStack.length === 0) { return; } const current = this.elementStack[this.elementStack.length - 1]; if (current.startTagOpen) { this.write(">"); current.startTagOpen = false; } } write(data) { this.output.write(data, this.encoding); } } //# sourceMappingURL=XmlEventStreamWriter.js.map