typesxml
Version:
Open source XML library written in TypeScript
111 lines • 3.88 kB
JavaScript
;
/*******************************************************************************
* 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
*******************************************************************************/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContentModel = void 0;
const Constants_1 = require("../Constants");
const XMLUtils_1 = require("../XMLUtils");
class ContentModel {
OPTIONAL = '?';
ZERO_OR_MORE = '*';
ONE_OR_MORE = '+';
ONE = '';
grammar;
name;
mixed;
contentTypes = ['EMPTY', 'ANY', 'MIXED', 'CHILDREN'];
contentType;
model;
constructor(grammar, name, contentSpec) {
this.grammar = grammar;
this.name = name;
this.model = this.parseSpec(contentSpec);
this.mixed = false;
}
parseSpec(contentSpec) {
let result = [];
let tokens = [];
let token = '';
let index = 0;
while (index < contentSpec.length) {
let c = contentSpec.charAt(index++);
if (XMLUtils_1.XMLUtils.isXmlSpace(c)) {
continue;
}
if (c === '*' || c === '+' || c === '?') {
if (tokens.length < 1) {
throw new Error('Invalid content model: ' + contentSpec);
}
tokens[tokens.length - 1] = tokens[tokens.length - 1] + c;
}
if (c === '(' || c === ')' || c === '|' || c === ',') {
if (token.length > 0) {
tokens.push(token);
token = '';
}
tokens.push(c);
}
else {
token += c;
}
}
return result;
}
toString() {
return this.name;
}
isMixed() {
return this.mixed;
}
isValid(element) {
let attList = this.grammar.getElementAttributesMap(element.getName());
let attributes = element.getAttributes();
for (let i = 0; i < attributes.length; i++) {
let attribute = attributes[i];
let name = attribute.getName();
let attDecl = attList.get(name);
if (attDecl) {
if (!attDecl.isValid(attribute.getValue())) {
return false;
}
}
else {
throw new Error('Attribute \'' + name + '\' not allowed in element \'' + element.getName() + '\'');
}
}
let content = element.getContent();
if (this.contentType === 'EMPTY' && content.length > 0) {
throw new Error('Empty \'' + element.getName() + '\' element has content');
}
if (this.contentType === 'ANY') {
return true;
}
if (content) {
for (let i = 0; i < content.length; i++) {
let node = content[i];
if (node.getNodeType() === Constants_1.Constants.TEXT_NODE) {
let text = node.toString();
if (text.trim().length > 0 && this.contentType !== 'MIXED') {
throw new Error('Element \'' + element.getName() + '\' cannot have #PCDATA content');
}
}
if (node.getNodeType() === Constants_1.Constants.ELEMENT_NODE) {
let childElement = node;
// TODO check sequence
}
}
}
return true;
}
}
exports.ContentModel = ContentModel;
//# sourceMappingURL=ContentModel.js.map