@@ -94,8 +94,8 @@ exports.validate = function (xmlData, options) {
94
94
95
95
const nsResult = validateNameSpace ( tagName , nameSpaces ) ;
96
96
97
- if ( ! nsResult . isValid ) {
98
- return getErrorObject ( 'InvalidNS ' , nsResult . errorMsg , getLineNumberForPosition ( xmlData , i ) ) ;
97
+ if ( nsResult !== true ) {
98
+ return getErrorObject ( 'InvalidTag ' , nsResult , getLineNumberForPosition ( xmlData , i ) ) ;
99
99
}
100
100
}
101
101
@@ -105,9 +105,16 @@ exports.validate = function (xmlData, options) {
105
105
if ( attrStr [ attrStr . length - 1 ] === '/' ) {
106
106
//self closing tag
107
107
attrStr = attrStr . substring ( 0 , attrStr . length - 1 ) ;
108
- const isValid = validateAttributeString ( attrStr , options ) ;
108
+ const isValid = validateAttributeString ( attrStr , nameSpaces , options ) ;
109
109
if ( isValid === true ) {
110
110
tagFound = true ;
111
+
112
+ if ( ! options . ignoreNameSpace && result . nsArray . length > 0 ) {
113
+ //Popping namespaces defined in tag
114
+ for ( let x = 0 ; x < result . nsArray . length ; x ++ ) {
115
+ nameSpaces . pop ( result . nsArray [ x ] ) ;
116
+ }
117
+ }
111
118
//continue; //text may presents after self closing tag
112
119
} else {
113
120
//the result from the nested function returns the position of the error within the attribute
@@ -127,7 +134,7 @@ exports.validate = function (xmlData, options) {
127
134
}
128
135
129
136
if ( ! options . ignoreNameSpace && otg . nsArray . length > 0 ) {
130
- //Pushing namespaces defined in tag
137
+ //Popping namespaces defined in tag
131
138
for ( let x = 0 ; x < otg . nsArray . length ; x ++ ) {
132
139
nameSpaces . pop ( otg . nsArray [ x ] ) ;
133
140
}
@@ -139,7 +146,7 @@ exports.validate = function (xmlData, options) {
139
146
}
140
147
}
141
148
} else {
142
- const isValid = validateAttributeString ( attrStr , options ) ;
149
+ const isValid = validateAttributeString ( attrStr , nameSpaces , options ) ;
143
150
if ( isValid !== true ) {
144
151
//the result from the nested function returns the position of the error within the attribute
145
152
//in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute
@@ -334,7 +341,7 @@ const validAttrStrRegxp = new RegExp('(\\s*)([^\\s=]+)(\\s*=)?(\\s*([\'"])(([\\s
334
341
335
342
//attr, ="sd", a="amit's", a="sd"b="saf", ab cd=""
336
343
337
- function validateAttributeString ( attrStr , options ) {
344
+ function validateAttributeString ( attrStr , nsArray , options ) {
338
345
//console.log("start:"+attrStr+":end");
339
346
340
347
//if(attrStr.trim().length === 0) return true; //empty string
@@ -357,6 +364,18 @@ function validateAttributeString(attrStr, options) {
357
364
if ( ! validateAttrName ( attrName ) ) {
358
365
return getErrorObject ( 'InvalidAttr' , "Attribute '" + attrName + "' is an invalid name." , getPositionFromMatch ( attrStr , matches [ i ] [ 0 ] ) ) ;
359
366
}
367
+
368
+ if ( ! options . ignoreNameSpace ) {
369
+ const nsDefMatches = util . getAllMatches ( matches [ i ] [ 0 ] , nameSpaceDefinitionRegex ) ;
370
+ //Skipping namespace definition attribute
371
+ if ( ! nsDefMatches || nsDefMatches . length === 0 || attrName !== nsDefMatches [ 0 ] [ 1 ] ) {
372
+ const nsResult = validateNameSpace ( attrName , nsArray ) ;
373
+ if ( nsResult !== true ) {
374
+ return getErrorObject ( 'InvalidAttr' , nsResult , getPositionFromMatch ( attrStr , matches [ i ] [ 0 ] ) ) ;
375
+ }
376
+ }
377
+ }
378
+
360
379
if ( ! attrNames . hasOwnProperty ( attrName ) ) {
361
380
//check for duplicate attribute.
362
381
attrNames [ attrName ] = 1 ;
@@ -423,38 +442,29 @@ function validateTagName(tagname) {
423
442
return util . isName ( tagname ) /* && !tagname.match(startsWithXML) */ ;
424
443
}
425
444
426
- function validateNameSpace ( tagName , nsArray ) {
427
- let tagSplit = tagName . split ( ":" ) ;
428
- let isValid , errorMsg ;
429
- switch ( tagSplit . length ) {
445
+ const nameSpaceDefinitionRegex = new RegExp ( / ( x m l n s : ( [ ^ : = ] + ) ) = / , 'g' ) ;
446
+
447
+ function validateNameSpace ( elemName , nsArray ) {
448
+ let elemSplit = elemName . split ( ":" ) ;
449
+ switch ( elemSplit . length ) {
430
450
case 1 :
431
- isValid = true ;
432
- break ;
451
+ return true ;
433
452
case 2 :
434
- if ( nsArray . indexOf ( tagSplit [ 0 ] ) > - 1 ) {
435
- isValid = true ;
453
+ if ( nsArray . indexOf ( elemSplit [ 0 ] ) > - 1 ) {
454
+ return true ;
436
455
} else {
437
- isValid = false ;
438
- errorMsg = "Namespace prefix '" + tagSplit [ 0 ] + "' is not defined for tag '" + tagName + "'" ;
456
+ return "Namespace prefix '" + elemSplit [ 0 ] + "' is not defined for '" + elemName + "'" ;
439
457
}
440
- break ;
441
458
default :
442
- isValid = false ;
443
- errorMsg = "Tag '" + tagName + "' cannot have multiple namespace prefixes" ;
444
- }
445
- return {
446
- isValid : isValid ,
447
- errorMsg : errorMsg
459
+ return "'" + elemName + "' cannot have multiple namespace prefixes" ;
448
460
}
449
461
}
450
462
451
463
function getNameSpaceDefinitions ( attributeString ) {
452
- const regexNs = / x m l n s : ( [ ^ = ] + ) = / g;
453
464
let nsArray = [ ] ;
454
- let matches = regexNs . exec ( attributeString ) ;
455
- while ( matches ) {
456
- nsArray . push ( matches [ 1 ] ) ;
457
- matches = regexNs . exec ( attributeString ) ;
465
+ let matches = util . getAllMatches ( attributeString , nameSpaceDefinitionRegex ) ;
466
+ for ( let i = 0 ; i < matches . length ; i ++ ) {
467
+ nsArray . push ( matches [ i ] [ 2 ] ) ;
458
468
}
459
469
return nsArray ;
460
470
}
0 commit comments