Skip to content

Commit 0c0b367

Browse files
committed
feat: read DOCTYPE ELEMENT exp
- added code for attribute list too but not tested. hence not using.
1 parent 38d0234 commit 0c0b367

File tree

1 file changed

+173
-6
lines changed

1 file changed

+173
-6
lines changed

src/xmlparser/DocTypeReader.js

Lines changed: 173 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,20 @@ export default function readDocType(xmlData, i){
2727
val: val
2828
};
2929
}
30-
else if( hasBody && isElement(xmlData, i)) i += 8;//Not supported
31-
else if( hasBody && isAttlist(xmlData, i)) i += 8;//Not supported
32-
else if( hasBody && isNotation(xmlData, i)) {
30+
else if( hasBody && isElement(xmlData, i)) {
31+
i += 8;//Not supported
32+
const {index} = readElementExp(xmlData,i+1);
33+
i = index;
34+
}else if( hasBody && isAttlist(xmlData, i)){
35+
i += 8;//Not supported
36+
// const {index} = readAttlistExp(xmlData,i+1);
37+
// i = index;
38+
}else if( hasBody && isNotation(xmlData, i)) {
3339
i += 9;//Not supported
34-
const {name, publicIdentifier, systemIdentifier,index} = readNotationExp(xmlData,i+1);
40+
const {index} = readNotationExp(xmlData,i+1);
3541
i = index;
36-
}else if( isComment) comment = true;
37-
else throw new Error("Invalid DOCTYPE");
42+
}else if( isComment) comment = true;
43+
else throw new Error("Invalid DOCTYPE");
3844

3945
angleBracketsCount++;
4046
exp = "";
@@ -181,6 +187,167 @@ function readIdentifierVal(xmlData, i, type) {
181187
return [i, identifierVal];
182188
}
183189

190+
function readElementExp(xmlData, i) {
191+
// <!ELEMENT name (content-model)>
192+
193+
// Skip leading whitespace after <!ELEMENT
194+
i = skipWhitespace(xmlData, i);
195+
196+
// Read element name
197+
let elementName = "";
198+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
199+
elementName += xmlData[i];
200+
i++;
201+
}
202+
203+
// Validate element name
204+
if (!validateEntityName(elementName)) {
205+
throw new Error(`Invalid element name: "${elementName}"`);
206+
}
207+
208+
// Skip whitespace after element name
209+
i = skipWhitespace(xmlData, i);
210+
211+
// Expect '(' to start content model
212+
if (xmlData[i] !== "(") {
213+
throw new Error(`Expected '(', found "${xmlData[i]}"`);
214+
}
215+
i++; // Move past '('
216+
217+
// Read content model
218+
let contentModel = "";
219+
while (i < xmlData.length && xmlData[i] !== ")") {
220+
contentModel += xmlData[i];
221+
i++;
222+
}
223+
224+
if (xmlData[i] !== ")") {
225+
throw new Error("Unterminated content model");
226+
}
227+
228+
return {
229+
elementName,
230+
contentModel: contentModel.trim(),
231+
index: i
232+
};
233+
}
234+
235+
function readAttlistExp(xmlData, i) {
236+
// Skip leading whitespace after <!ATTLIST
237+
i = skipWhitespace(xmlData, i);
238+
239+
// Read element name
240+
let elementName = "";
241+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
242+
elementName += xmlData[i];
243+
i++;
244+
}
245+
246+
// Validate element name
247+
validateEntityName(elementName)
248+
249+
// Skip whitespace after element name
250+
i = skipWhitespace(xmlData, i);
251+
252+
// Read attribute name
253+
let attributeName = "";
254+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
255+
attributeName += xmlData[i];
256+
i++;
257+
}
258+
259+
// Validate attribute name
260+
if (!validateEntityName(attributeName)) {
261+
throw new Error(`Invalid attribute name: "${attributeName}"`);
262+
}
263+
264+
// Skip whitespace after attribute name
265+
i = skipWhitespace(xmlData, i);
266+
267+
// Read attribute type
268+
let attributeType = "";
269+
if (xmlData.substring(i, i + 8).toUpperCase() === "NOTATION") {
270+
attributeType = "NOTATION";
271+
i += 8; // Move past "NOTATION"
272+
273+
// Skip whitespace after "NOTATION"
274+
i = skipWhitespace(xmlData, i);
275+
276+
// Expect '(' to start the list of notations
277+
if (xmlData[i] !== "(") {
278+
throw new Error(`Expected '(', found "${xmlData[i]}"`);
279+
}
280+
i++; // Move past '('
281+
282+
// Read the list of allowed notations
283+
let allowedNotations = [];
284+
while (i < xmlData.length && xmlData[i] !== ")") {
285+
let notation = "";
286+
while (i < xmlData.length && xmlData[i] !== "|" && xmlData[i] !== ")") {
287+
notation += xmlData[i];
288+
i++;
289+
}
290+
291+
// Validate notation name
292+
notation = notation.trim();
293+
if (!validateEntityName(notation)) {
294+
throw new Error(`Invalid notation name: "${notation}"`);
295+
}
296+
297+
allowedNotations.push(notation);
298+
299+
// Skip '|' separator or exit loop
300+
if (xmlData[i] === "|") {
301+
i++; // Move past '|'
302+
i = skipWhitespace(xmlData, i); // Skip optional whitespace after '|'
303+
}
304+
}
305+
306+
if (xmlData[i] !== ")") {
307+
throw new Error("Unterminated list of notations");
308+
}
309+
i++; // Move past ')'
310+
311+
// Store the allowed notations as part of the attribute type
312+
attributeType += " (" + allowedNotations.join("|") + ")";
313+
} else {
314+
// Handle simple types (e.g., CDATA, ID, IDREF, etc.)
315+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
316+
attributeType += xmlData[i];
317+
i++;
318+
}
319+
320+
// Validate simple attribute type
321+
const validTypes = ["CDATA", "ID", "IDREF", "IDREFS", "ENTITY", "ENTITIES", "NMTOKEN", "NMTOKENS"];
322+
if (!validTypes.includes(attributeType.toUpperCase())) {
323+
throw new Error(`Invalid attribute type: "${attributeType}"`);
324+
}
325+
}
326+
327+
// Skip whitespace after attribute type
328+
i = skipWhitespace(xmlData, i);
329+
330+
// Read default value
331+
let defaultValue = "";
332+
if (xmlData.substring(i, i + 8).toUpperCase() === "#REQUIRED") {
333+
defaultValue = "#REQUIRED";
334+
i += 8;
335+
} else if (xmlData.substring(i, i + 7).toUpperCase() === "#IMPLIED") {
336+
defaultValue = "#IMPLIED";
337+
i += 7;
338+
} else {
339+
[i, defaultValue] = readIdentifierVal(xmlData, i, "ATTLIST");
340+
}
341+
342+
return {
343+
elementName,
344+
attributeName,
345+
attributeType,
346+
defaultValue,
347+
index: i
348+
}
349+
}
350+
184351
function isComment(xmlData, i){
185352
if(xmlData[i+1] === '!' &&
186353
xmlData[i+2] === '-' &&

0 commit comments

Comments
 (0)