Skip to content

Commit 45d0d8d

Browse files
committed
Fix validator for invalid attributes
1 parent 69d4347 commit 45d0d8d

3 files changed

Lines changed: 52 additions & 44 deletions

File tree

spec/attr_spec.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,20 @@ describe("XMLParser", function () {
124124
expect(result).toBe(false);
125125
});
126126

127-
it("should not validate xml with invalid attributes when an attribute without value present", function () {
127+
128+
it("should not validate a tag with attribute presents without value ", function () {
129+
var xmlData = "<rootNode ab cd='ef'></rootNode>";
130+
var result = validator.validate(xmlData);
131+
expect(result).toBe(false);
132+
});
133+
134+
it("should not validate xml with invalid attributes presents without value", function () {
128135
var xmlData = "<rootNode 123 abc='123' bc='567' />";
129136

130137
result = validator.validate(xmlData);
131138
expect(result).toBe(false);
132139
});
133140

141+
142+
134143
});

spec/validator_spec.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,18 @@ describe("XMLParser", function () {
3434
});
3535

3636
it("should validate self closing tags", function () {
37-
var xmlData = "<rootNode/>";
38-
result = validator.validate(xmlData);
37+
var xmlData = "<rootNode><validtag1 /><validtag2/><validtag3 with='attrib'/></rootNode>";
38+
var result = validator.validate(xmlData);
3939
expect(result).toBe(true);
4040
});
4141

42+
it("should validate self closing tags", function () {
43+
var xmlData = "<rootNode><validtag1 /><invalid tag/><validtag3 with='attrib'/></rootNode>";
44+
var result = validator.validate(xmlData);
45+
expect(result).toBe(false);
46+
});
47+
48+
4249
it("should not validate xml string when closing tag is different", function () {
4350
var xmlData = "<rootNode></rootnode>";
4451

src/validator.js

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,20 @@ exports.validate = function(xmlData){
6060
attrStr += xmlData[i];
6161
}
6262
if(startChar !== "") return false;//Unclosed quote
63-
attrStr = attrStr.trim();
63+
//attrStr = attrStr.trim();
6464
//console.log(attrStr, attrStr);
6565

6666
if(attrStr[attrStr.length-1] === "/" ){//self closing tag
67-
attrStr = attrStr.substring(0,attrStr.length-2);
68-
67+
attrStr = attrStr.substring(0,attrStr.length-1);
68+
//console.log(attrStr);
6969
if(!validateAttributeString(attrStr)){
7070
return false;
7171
}else{
7272

7373
continue;
7474
}
7575
}else if(closingTag){
76-
if(attrStr.length > 0){
76+
if(attrStr.trim().length > 0){
7777
return false;
7878
//throw new Error("XML validation error: closing tag should not have any attribute");
7979
}else{
@@ -148,60 +148,52 @@ function readCommentAndCDATA(xmlData,i){
148148

149149
return i;
150150
}
151-
//attr, ="sd", a="amit's", a="sd"b="saf",
151+
152+
/**
153+
* Select all the attributes whether valid or invalid.
154+
*/
155+
var validAttrStrRegxp = new RegExp("(\\s*)([^\\s=]+)\\s*(=)?(\\s*(['\"])((.|\\n)*?)\\5)?", "g");
156+
157+
//attr, ="sd", a="amit's", a="sd"b="saf", ab cd=""
158+
152159
function validateAttributeString(attrStr){
153-
var attrNames = [];
154-
for(var i=0; i< attrStr.length; i++){
155-
var startChar = "";
156-
//read attribute name
157-
var attrName = "";
158-
for(;i < attrStr.length && attrStr[i] !== "=" ; i++) {
159-
attrName +=attrStr[i];
160-
}
161-
//validate attrName
162-
attrName = attrName.trim();
160+
//console.log("start:"+attrStr+":end");
163161

162+
//if(attrStr.trim().length === 0) return true; //empty string
164163

164+
var matches = util.getAllMatches(attrStr,validAttrStrRegxp);
165+
var attrNames = [];
165166

166-
if(!attrNames.hasOwnProperty(attrName)){
167-
attrNames[attrName]=1;
168-
}else{
167+
168+
for(var i=0;i<matches.length;i++){
169+
//console.log(matches[i]);
170+
171+
if(matches[i][1].length === 0){//nospace before attribute name: a="sd"b="saf"
172+
return false;
173+
}else if(matches[i][3] === undefined){//independent attribute: ab
174+
return false;
175+
}else if(matches[i][6] === undefined){//attribute without value: ab=
169176
return false;
170177
}
178+
attrName=matches[i][2];
171179
if(!validateAttrName(attrName)){
180+
//console.log("seems invalid");
172181
return false;
173182
}
174-
i++;
175-
176-
//skip whitespaces
177-
for(;i < attrStr.length
178-
&& (attrStr[i] === " "
179-
|| attrStr[i] === "\t") ; i++);
180-
181-
//read attribute value
182-
startChar = attrStr[i++];
183-
184-
var attrVal = "";
185-
for(;i < attrStr.length && attrStr[i] !== startChar; i++) {
186-
attrVal +=attrStr[i];
187-
}
188-
189-
//validate attrVal
190-
191-
if(startChar !== ""){
192-
i++;
193-
if(i<attrStr.length && (attrStr[i] !== " " && attrStr[i] !== "\t") ){//when no spce between 2 attributes : a="sd"b="saf"
194-
return false;
195-
}
196-
startChar = "";
183+
if(!attrNames.hasOwnProperty(attrName)){//check for duplicate attribute.
184+
attrNames[attrName]=1;
185+
}else{
186+
return false;
197187
}
198188
}
199189

200190
return true;
191+
201192
}
202193

203194
var validAttrRegxp = new RegExp("^[_a-zA-Z][\\w\\-\\.\\:]*$");
204195

196+
205197
function validateAttrName(attrName){
206198
return util.doesMatch(attrName,validAttrRegxp);
207199
}

0 commit comments

Comments
 (0)