diff --git a/spec/arrayMode_test.js b/spec/arrayMode_test.js new file mode 100644 index 00000000..70bcf086 --- /dev/null +++ b/spec/arrayMode_test.js @@ -0,0 +1,193 @@ +"use strict"; + +const parser = require("../src/parser"); + +describe("XMLParser with array_mode enabled ", function () { + it("should parse all the tags as an array no matter how many occurences excluding premitive values when arrayMode is set to true", function () { + const xmlData = ` + + US + + + Banana + 200 + + + Apple + 100 + + + + + EU + + + Banana + 100 + + + + `; + + const expected = { + "report": [ + { + "store": [ + { + "region": "US", + "inventory": [ + { + "item": [ + { + "name": "Banana", + "count": 200 + }, + { + "name": "Apple", + "count": 100 + } + ] + } + ] + }, + { + "region": "EU", + "inventory": [ + { + "item": [ + { + "name": "Banana", + "count": 100 + } + ] + } + ] + } + ] + } + ] + }; + + const result = parser.parse(xmlData, { + arrayMode: true, + ignoreAttributes: false, + }); + //console.log(JSON.stringify(result, null, 4)); + expect(result).toEqual(expected); + }); + + it("should parse all the tags as an array no matter how many occurences when arrayMode is set to strict", function () { + const xmlData = ` + + US + + + Banana + 200 + + + Apple + 100 + + + + + EU + + + Banana + 100 + + + + `; + + const expected = { + "report": [ + { + "store": [ + { + "region": ["US"], + "inventory": [ + { + "item": [ + { + "@_grade" : "A", + "name": ["Banana"], + "count": [200] + }, + { + "@_grade" : "B", + "name": ["Apple"], + "count": [100] + } + ] + } + ] + }, + { + "region": ["EU"], + "inventory": [ + { + "item": [ + { + "name": [ "Banana" ], + "count": [100] + } + ] + } + ] + } + ] + } + ] + }; + + const result = parser.parse(xmlData, { + arrayMode: "strict", + ignoreAttributes: false, + }); + //console.log(JSON.stringify(result, null, 4)); + expect(result).toEqual(expected); + }); + + it("try", function () { + const xmlData = ` + + US + + some item detail + Banana + 200 + + + + Apple + 100 + + + + `; + + let result = parser.parse(xmlData, { + arrayMode: true, + ignoreAttributes: false, + cdataTagName: "__cdata", + attrNodeName: "@@" + }); + console.log(JSON.stringify(result, null, 4)); + //expect(result).toEqual(expected); + + result = parser.parse(xmlData, { + arrayMode: 'strict', + ignoreAttributes: false, + cdataTagName: "__cdata", + attrNodeName: "@@" + }); + console.log(JSON.stringify(result, null, 4)); + //expect(result).toEqual(expected); + }); +}); + + + diff --git a/src/node2json.js b/src/node2json.js index 98366bc7..1180bdb1 100644 --- a/src/node2json.js +++ b/src/node2json.js @@ -12,12 +12,16 @@ const convertToJson = function(node, options) { //otherwise create a textnode if node has some text if (util.isExist(node.val)) { if (!(typeof node.val === 'string' && (node.val === '' || node.val === options.cdataPositionChar))) { - jObj[options.textNodeName] = node.val; + if(options.arrayMode === "strict"){ + jObj[options.textNodeName] = [ node.val ]; + }else{ + jObj[options.textNodeName] = node.val; + } } } } - util.merge(jObj, node.attrsMap); + util.merge(jObj, node.attrsMap, options.arrayMode); const keys = Object.keys(node.child); for (let index = 0; index < keys.length; index++) { @@ -28,7 +32,17 @@ const convertToJson = function(node, options) { jObj[tagname].push(convertToJson(node.child[tagname][tag], options)); } } else { - jObj[tagname] = convertToJson(node.child[tagname][0], options); + if(options.arrayMode === true){ + const result = convertToJson(node.child[tagname][0], options) + if(typeof result === 'object') + jObj[tagname] = [ result ]; + else + jObj[tagname] = result; + }else if(options.arrayMode === "strict"){ + jObj[tagname] = [convertToJson(node.child[tagname][0], options) ]; + }else{ + jObj[tagname] = convertToJson(node.child[tagname][0], options); + } } } diff --git a/src/util.js b/src/util.js index a772b212..97766e4d 100644 --- a/src/util.js +++ b/src/util.js @@ -37,12 +37,16 @@ exports.isEmptyObject = function(obj) { * @param {*} target * @param {*} a */ -exports.merge = function(target, a) { +exports.merge = function(target, a, arrayMode) { if (a) { const keys = Object.keys(a); // will return an array of own properties const len = keys.length; //don't make it inline for (let i = 0; i < len; i++) { - target[keys[i]] = a[keys[i]]; + if(arrayMode === 'strict'){ + target[keys[i]] = [ a[keys[i]] ]; + }else{ + target[keys[i]] = a[keys[i]]; + } } } };