diff --git a/spec/stopNodes_spec.js b/spec/stopNodes_spec.js new file mode 100644 index 00000000..c36fdf31 --- /dev/null +++ b/spec/stopNodes_spec.js @@ -0,0 +1,187 @@ +"use strict"; + +const parser = require("../src/parser"); +const validator = require("../src/validator"); +const he = require("he"); + +describe("XMLParser", function() { + it("1a. should support single stopNode", function() { + const xmlData = `test 1

p 1

div 1
`; + const expected = { + "issue": { + "title": "test 1", + "fix1": "

p 1

div 1
" + } + }; + + let result = parser.parse(xmlData, { + attributeNamePrefix: "", + ignoreAttributes: false, + parseAttributeValue: true, + stopNodes: ["fix1"] + }); + + //console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + + result = validator.validate(xmlData); + expect(result).toBe(true); + }); + + it("1b. 3. should support more than one stopNodes, with or without attr", function() { + const xmlData = `test 1

p 1

div 1

p 2

div 2
`; + const expected = { + "issue": { + "title": "test 1", + "fix1": { + "#text": "

p 1

div 1
", + "lang": "en" + }, + "fix2": "

p 2

div 2
" + } + }; + + let result = parser.parse(xmlData, { + attributeNamePrefix: "", + ignoreAttributes: false, + parseAttributeValue: true, + stopNodes: ["fix1", "fix2"] + }); + + //console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + + result = validator.validate(xmlData); + expect(result).toBe(true); + }); + + it("1c. have two stopNodes, one within the other", function() { + const xmlData = `test 1

p 1

p 2

div 2
div 1
`; + const expected = { + "issue": { + "title": "test 1", + "fix1": { + "#text": "

p 1

p 2

div 2
div 1
", + "lang": "en" + } + } + }; + + let result = parser.parse(xmlData, { + attributeNamePrefix: "", + ignoreAttributes: false, + parseAttributeValue: true, + stopNodes: ["fix1", "fix2"] + }); + + //console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + + result = validator.validate(xmlData); + expect(result).toBe(true); + }); + + it("2a. stop node has nothing in it", function() { + const xmlData = `test 1`; + const expected = { + "issue": { + "title": "test 1", + "fix1": "" + } + }; + + let result = parser.parse(xmlData, { + attributeNamePrefix: "", + ignoreAttributes: false, + parseAttributeValue: true, + stopNodes: ["fix1", "fix2"] + }); + + //console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + + result = validator.validate(xmlData); + expect(result).toBe(true); + }); + + it("2b. stop node is self-closing", function() { + const xmlData = `test 1`; + const expected = { + "issue": { + "title": "test 1", + "fix1": "" + } + }; + + let result = parser.parse(xmlData, { + attributeNamePrefix: "", + ignoreAttributes: false, + parseAttributeValue: true, + stopNodes: ["fix1", "fix2"] + }); + + //console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + + result = validator.validate(xmlData); + expect(result).toBe(true); + }); + + it("4. cdata", function() { + const xmlData = ` + + + +122233344550 + Jack]]> + Mohan]]> + + + + + Mohan]]> + +`; + const expected = { + "issue": { + "fix1": "\n +122233344550\n Jack]]>\n Mohan]]>\n \n \n ", + "fix2": "\n\t\tMohan]]>\n\t" + } + }; + + let result = parser.parse(xmlData, { + attributeNamePrefix: "", + ignoreAttributes: false, + parseAttributeValue: true, + stopNodes: ["fix1", "fix2"] + }); + + //console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + + result = validator.validate(xmlData, { + allowBooleanAttributes: true + }); + expect(result).toBe(true); + }); + + it("5. stopNode at root level", function() { + const xmlData = `

p 1

div 1
`; + const expected = { + "fix1": "

p 1

div 1
" + }; + + let result = parser.parse(xmlData, { + attributeNamePrefix: "", + ignoreAttributes: false, + stopNodes: ["fix1", "fix2"] + }); + + //console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + + result = validator.validate(xmlData, { + allowBooleanAttributes: true + }); + expect(result).toBe(true); + }); +}); diff --git a/src/xmlstr2xmlnode.js b/src/xmlstr2xmlnode.js index 16122ee6..c8e5b83b 100644 --- a/src/xmlstr2xmlnode.js +++ b/src/xmlstr2xmlnode.js @@ -39,6 +39,7 @@ const defaultOptions = { attrValueProcessor: function(a) { return a; }, + stopNodes: [] //decodeStrict: false, }; @@ -61,6 +62,7 @@ const props = [ 'tagValueProcessor', 'attrValueProcessor', 'parseTrueNumberOnly', + 'stopNodes' ]; exports.props = props; @@ -84,7 +86,11 @@ const getTraversalObj = function(xmlData, options) { if (currentNode.parent && tag[14]) { currentNode.parent.val = util.getValue(currentNode.parent.val) + '' + processTagValue(tag[14], options); } - + if (options.stopNodes.length && options.stopNodes.includes(currentNode.tagname)) { + currentNode.child = [] + if (currentNode.attrsMap == undefined) { currentNode.attrsMap = {}} + currentNode.val = xmlData.substr(currentNode.startIndex + 1, tag.index - currentNode.startIndex - 1) + } currentNode = currentNode.parent; } else if (tagType === TagType.CDATA) { if (options.cdataTagName) { @@ -119,6 +125,9 @@ const getTraversalObj = function(xmlData, options) { currentNode, processTagValue(tag[14], options) ); + if (options.stopNodes.length && options.stopNodes.includes(childNode.tagname)) { + childNode.startIndex=tag.index + tag[1].length + } childNode.attrsMap = buildAttributesMap(tag[8], options); currentNode.addChild(childNode); currentNode = childNode;