UNPKG

typesxml

Version:

Open source XML library written in TypeScript

289 lines 11.7 kB
"use strict"; /******************************************************************************* * Copyright (c) 2023 - 2024 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 *******************************************************************************/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.Catalog = void 0; const fs_1 = require("fs"); const path = __importStar(require("node:path")); const DOMBuilder_1 = require("./DOMBuilder"); const SAXParser_1 = require("./SAXParser"); const XMLUtils_1 = require("./XMLUtils"); class Catalog { systemCatalog; publicCatalog; uriCatalog; dtdCatalog; uriRewrites; systemRewrites; workDir; base; constructor(catalogFile) { if (!path.isAbsolute(catalogFile)) { throw new Error('Catalog file must be absolute: ' + catalogFile); } if (!(0, fs_1.existsSync)(catalogFile)) { throw new Error('Catalog file ' + catalogFile + ' not found'); } this.systemCatalog = new Map(); this.publicCatalog = new Map(); this.uriCatalog = new Map(); this.dtdCatalog = new Map(); this.uriRewrites = new Array(); this.systemRewrites = new Array(); this.workDir = path.dirname(catalogFile); this.base = ''; let contentHandler = new DOMBuilder_1.DOMBuilder(); let parser = new SAXParser_1.SAXParser(); parser.setContentHandler(contentHandler); parser.parseFile(catalogFile); let catalogDocument = contentHandler.getDocument(); let catalogRoot = catalogDocument.getRoot(); if (catalogRoot.getName() !== 'catalog') { throw new Error('Catalog root element must be <catalog>'); } this.recurse(catalogRoot); } recurse(catalogRoot) { for (let child of catalogRoot.getChildren()) { let currentBase = this.base; if (child.hasAttribute('xml:base') && child.getAttribute("xml:base").getValue() !== '') { this.base = child.getAttribute("xml:base").getValue(); if (!this.base.endsWith('/')) { this.base += '/'; } if (!path.isAbsolute(this.base)) { this.base = path.resolve(this.workDir, this.base); } if (!(0, fs_1.existsSync)(this.base)) { throw new Error('Invalid xml:base: ' + this.base); } } if (child.getName() === 'public') { let publicId = child.getAttribute("publicId").getValue(); if (publicId.startsWith("urn:publicid:")) { publicId = this.unwrapUrn(publicId); } if (!this.publicCatalog.has(publicId)) { let uri = this.makeAbsolute(child.getAttribute("uri").getValue()); if ((0, fs_1.existsSync)(uri)) { this.publicCatalog.set(publicId, uri); if (uri.endsWith(".dtd") || uri.endsWith(".ent") || uri.endsWith(".mod")) { let name = path.basename(uri); if (!this.dtdCatalog.has(name)) { this.dtdCatalog.set(name, uri); } } } } } if (child.getName() === 'system') { let uri = this.makeAbsolute(child.getAttribute("uri").getValue()); if ((0, fs_1.existsSync)(uri)) { this.systemCatalog.set(child.getAttribute("systemId").getValue(), uri); if (uri.endsWith(".dtd")) { let name = path.basename(uri); if (!this.dtdCatalog.has(name)) { this.dtdCatalog.set(name, uri); } } } } if (child.getName() === 'uri') { let uri = this.makeAbsolute(child.getAttribute("uri").getValue()); if ((0, fs_1.existsSync)(uri)) { this.uriCatalog.set(child.getAttribute("name").getValue(), uri); if (uri.endsWith(".dtd") || uri.endsWith(".ent") || uri.endsWith(".mod")) { let name = path.basename(uri); if (!this.dtdCatalog.has(name)) { this.dtdCatalog.set(name, uri); } } } } if (child.getName() === 'rewriteURI') { let uri = this.makeAbsolute(child.getAttribute("rewritePrefix").getValue()); let pair = [child.getAttribute("uriStartString").getValue(), uri]; if (!this.uriRewrites.includes(pair)) { this.uriRewrites.push(pair); } } if (child.getName() === 'rewriteSystem') { let uri = this.makeAbsolute(child.getAttribute("rewritePrefix").getValue()); let pair = [child.getAttribute("systemIdStartString").getValue(), uri]; if (!this.systemRewrites.includes(pair)) { this.systemRewrites.push(pair); } } if (child.getName() === 'nextCatalog') { let nextCatalog = this.makeAbsolute(child.getAttribute("catalog").getValue()); let catalog = new Catalog(nextCatalog); let map = catalog.getSystemCatalog(); map.forEach((value, key) => { if (!this.systemCatalog.has(key)) { this.systemCatalog.set(key, value); } }); map = catalog.getPublicCatalog(); map.forEach((value, key) => { if (!this.publicCatalog.has(key)) { this.publicCatalog.set(key, value); } }); map = catalog.getUriCatalog(); map.forEach((value, key) => { if (!this.uriCatalog.has(key)) { this.uriCatalog.set(key, value); } }); map = catalog.getDtdCatalog(); map.forEach((value, key) => { if (!this.dtdCatalog.has(key)) { this.dtdCatalog.set(key, value); } }); let array = catalog.getUriRewrites(); array.forEach((value) => { if (!this.uriRewrites.includes(value)) { this.uriRewrites.push(value); } }); array = catalog.getSystemRewrites(); array.forEach((value) => { if (!this.systemRewrites.includes(value)) { this.systemRewrites.push(value); } }); } this.recurse(child); this.base = currentBase; } } makeAbsolute(uri) { let file = this.base + uri; if (!path.isAbsolute(file)) { if (this.base !== '') { return path.resolve(this.base, uri); } return path.resolve(this.workDir, uri); } return this.base + uri; } unwrapUrn(urn) { if (!urn.startsWith('urn:publicid:')) { return urn; } let publicId = urn.trim().substring('urn:publicid:'.length); publicId = XMLUtils_1.XMLUtils.replaceAll(publicId, '+', ' '); publicId = XMLUtils_1.XMLUtils.replaceAll(publicId, ':', '//'); publicId = XMLUtils_1.XMLUtils.replaceAll(publicId, ';', '::'); publicId = XMLUtils_1.XMLUtils.replaceAll(publicId, '%2B', '+'); publicId = XMLUtils_1.XMLUtils.replaceAll(publicId, '%3A', ':'); publicId = XMLUtils_1.XMLUtils.replaceAll(publicId, '%2F', '/'); publicId = XMLUtils_1.XMLUtils.replaceAll(publicId, '%3B', ';'); publicId = XMLUtils_1.XMLUtils.replaceAll(publicId, '%27', '\''); publicId = XMLUtils_1.XMLUtils.replaceAll(publicId, '%3F', '?'); publicId = XMLUtils_1.XMLUtils.replaceAll(publicId, '%23', '#'); return XMLUtils_1.XMLUtils.replaceAll(publicId, '%25', '%'); } getSystemCatalog() { return this.systemCatalog; } getPublicCatalog() { return this.publicCatalog; } getUriCatalog() { return this.uriCatalog; } getDtdCatalog() { return this.dtdCatalog; } getUriRewrites() { return this.uriRewrites; } getSystemRewrites() { return this.systemRewrites; } resolveEntity(publicId, systemId) { if (publicId) { let location = this.matchPublic(publicId); if (location) { return location; } } let location = this.matchSystem(systemId); if (location) { return location; } return undefined; } matchSystem(systemId) { if (systemId) { for (let pair of this.systemRewrites) { if (systemId.startsWith(pair[0])) { systemId = pair[1] + systemId.substring(pair[0].length); } } if (this.systemCatalog.has(systemId)) { return this.systemCatalog.get(systemId); } let fileName = path.basename(systemId); if (this.dtdCatalog.has(fileName)) { return this.dtdCatalog.get(fileName); } } return undefined; } matchPublic(publicId) { if (publicId.startsWith("urn:publicid:")) { publicId = this.unwrapUrn(publicId); } if (this.publicCatalog.has(publicId)) { return this.publicCatalog.get(publicId); } return undefined; } } exports.Catalog = Catalog; //# sourceMappingURL=Catalog.js.map