@@ -17,7 +17,7 @@ export default function readDocType(xmlData, i){
1717 let exp = "" ;
1818 for ( ; i < xmlData . length ; i ++ ) {
1919 if ( xmlData [ i ] === '<' && ! comment ) { //Determine the tag type
20- if ( hasBody && isEntity ( xmlData , i ) ) {
20+ if ( hasBody && hasSeq ( xmlData , "!ENTITY" , i ) ) {
2121 i += 7 ;
2222 let entityName , val ;
2323 [ entityName , val , i ] = readEntityExp ( xmlData , i + 1 ) ;
@@ -27,19 +27,19 @@ export default function readDocType(xmlData, i){
2727 val : val
2828 } ;
2929 }
30- else if ( hasBody && isElement ( xmlData , i ) ) {
30+ else if ( hasBody && hasSeq ( xmlData , "!ELEMENT" , i ) ) {
3131 i += 8 ; //Not supported
3232 const { index} = readElementExp ( xmlData , i + 1 ) ;
3333 i = index ;
34- } else if ( hasBody && isAttlist ( xmlData , i ) ) {
34+ } else if ( hasBody && hasSeq ( xmlData , "!ATTLIST" , i ) ) {
3535 i += 8 ; //Not supported
3636 // const {index} = readAttlistExp(xmlData,i+1);
3737 // i = index;
38- } else if ( hasBody && isNotation ( xmlData , i ) ) {
38+ } else if ( hasBody && hasSeq ( xmlData , "!NOTATION" , i ) ) {
3939 i += 9 ; //Not supported
4040 const { index} = readNotationExp ( xmlData , i + 1 ) ;
4141 i = index ;
42- } else if ( isComment ) comment = true ;
42+ } else if ( hasSeq ( xmlData , "!--" , i ) ) comment = true ;
4343 else throw new Error ( "Invalid DOCTYPE" ) ;
4444
4545 angleBracketsCount ++ ;
@@ -188,8 +188,12 @@ function readIdentifierVal(xmlData, i, type) {
188188}
189189
190190function readElementExp ( xmlData , i ) {
191+ // <!ELEMENT br EMPTY>
192+ // <!ELEMENT div ANY>
193+ // <!ELEMENT title (#PCDATA)>
194+ // <!ELEMENT book (title, author+)>
191195 // <!ELEMENT name (content-model)>
192-
196+
193197 // Skip leading whitespace after <!ELEMENT
194198 i = skipWhitespace ( xmlData , i ) ;
195199
@@ -207,24 +211,26 @@ function readElementExp(xmlData, i) {
207211
208212 // Skip whitespace after element name
209213 i = skipWhitespace ( xmlData , i ) ;
210-
214+ let contentModel = "" ;
211215 // Expect '(' to start content model
212- if ( xmlData [ i ] !== "(" ) {
213- throw new Error ( `Expected '(', found " ${ xmlData [ i ] } "` ) ;
214- }
215- i ++ ; // Move past '('
216+ if ( xmlData [ i ] === "E" && hasSeq ( xmlData , "MPTY" , i ) ) i += 6 ;
217+ else if ( xmlData [ i ] === "A" && hasSeq ( xmlData , "NY" , i ) ) i += 4 ;
218+ else if ( xmlData [ i ] === "(" ) {
219+ i ++ ; // Move past '('
216220
217- // Read content model
218- let contentModel = "" ;
219- while ( i < xmlData . length && xmlData [ i ] !== ")" ) {
220- contentModel += xmlData [ i ] ;
221- i ++ ;
222- }
221+ // Read content model
222+ while ( i < xmlData . length && xmlData [ i ] !== ")" ) {
223+ contentModel += xmlData [ i ] ;
224+ i ++ ;
225+ }
226+ if ( xmlData [ i ] !== ")" ) {
227+ throw new Error ( "Unterminated content model" ) ;
228+ }
223229
224- if ( xmlData [ i ] !== ")" ) {
225- throw new Error ( "Unterminated content model" ) ;
230+ } else {
231+ throw new Error ( `Invalid Element Expression, found " ${ xmlData [ i ] } "` ) ;
226232 }
227-
233+
228234 return {
229235 elementName,
230236 contentModel : contentModel . trim ( ) ,
@@ -348,56 +354,11 @@ function readAttlistExp(xmlData, i) {
348354 }
349355}
350356
351- function isComment ( xmlData , i ) {
352- if ( xmlData [ i + 1 ] === '!' &&
353- xmlData [ i + 2 ] === '-' &&
354- xmlData [ i + 3 ] === '-' ) return true
355- return false
356- }
357- function isEntity ( xmlData , i ) {
358- if ( xmlData [ i + 1 ] === '!' &&
359- xmlData [ i + 2 ] === 'E' &&
360- xmlData [ i + 3 ] === 'N' &&
361- xmlData [ i + 4 ] === 'T' &&
362- xmlData [ i + 5 ] === 'I' &&
363- xmlData [ i + 6 ] === 'T' &&
364- xmlData [ i + 7 ] === 'Y' ) return true
365- return false
366- }
367- function isElement ( xmlData , i ) {
368- if ( xmlData [ i + 1 ] === '!' &&
369- xmlData [ i + 2 ] === 'E' &&
370- xmlData [ i + 3 ] === 'L' &&
371- xmlData [ i + 4 ] === 'E' &&
372- xmlData [ i + 5 ] === 'M' &&
373- xmlData [ i + 6 ] === 'E' &&
374- xmlData [ i + 7 ] === 'N' &&
375- xmlData [ i + 8 ] === 'T' ) return true
376- return false
377- }
378-
379- function isAttlist ( xmlData , i ) {
380- if ( xmlData [ i + 1 ] === '!' &&
381- xmlData [ i + 2 ] === 'A' &&
382- xmlData [ i + 3 ] === 'T' &&
383- xmlData [ i + 4 ] === 'T' &&
384- xmlData [ i + 5 ] === 'L' &&
385- xmlData [ i + 6 ] === 'I' &&
386- xmlData [ i + 7 ] === 'S' &&
387- xmlData [ i + 8 ] === 'T' ) return true
388- return false
389- }
390- function isNotation ( xmlData , i ) {
391- if ( xmlData [ i + 1 ] === '!' &&
392- xmlData [ i + 2 ] === 'N' &&
393- xmlData [ i + 3 ] === 'O' &&
394- xmlData [ i + 4 ] === 'T' &&
395- xmlData [ i + 5 ] === 'A' &&
396- xmlData [ i + 6 ] === 'T' &&
397- xmlData [ i + 7 ] === 'I' &&
398- xmlData [ i + 8 ] === 'O' &&
399- xmlData [ i + 9 ] === 'N' ) return true
400- return false
357+ function hasSeq ( data , seq , i ) {
358+ for ( let j = 0 ; j < seq . length ; j ++ ) {
359+ if ( seq [ j ] !== data [ i + j + 1 ] ) return false ;
360+ }
361+ return true ;
401362}
402363
403364function validateEntityName ( name ) {
0 commit comments