diff --git a/spec/xmlParser_spec.js b/spec/xmlParser_spec.js index 5c7b85a9..acd63eec 100644 --- a/spec/xmlParser_spec.js +++ b/spec/xmlParser_spec.js @@ -797,7 +797,7 @@ describe("XMLParser", function() { expect(result).toEqual(expected); }); - it("should validate before parsing", function() { + it("should validate before parsing", function() { const xmlData = "" + "" + " subtag text" @@ -825,4 +825,165 @@ describe("XMLParser", function() { //console.log(JSON.stringify(result,null,4)); expect(result).toEqual(expected); }); + + it("should add index and childCount to single node", function() { + const xmlData = `value`; + const expected = { + "childCount": 1, + "rootNode": { + "indexPos": 0, + "childCount": 1, + "tag": { + "indexPos": 0, + "#text": "value", + "@_int": 45, + "@_float": 65.34 + } + } + }; + + const result = parser.parse(xmlData, { + ignoreAttributes: false, + parseAttributeValue: true, + appendIndexInNodes: true + }); + + expect(result).toEqual(expected); + }); + + it("should add index and childCount to array", function() { + const xmlData = ` + value + 45 + 65.34 + `; + + const expected = { + "childCount": 1, + "rootNode": { + "indexPos": 0, + "childCount": 3, + "tag": [ + { + "#text": "value", + "indexPos": 0 + }, + { + "#text": 45, + "indexPos": 1 + }, + { + "#text": 65.34, + "indexPos": 2 + } + ] + } + }; + const result = parser.parse(xmlData,{ appendIndexInNodes: true }); + // console.log(result); + // console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + }); + + it("should add index and childCount to array and keep attributes", function() { + const xmlData = ` + value + 45 + 65.34 + `; + + const expected = { + "childCount": 1, + "rootNode": { + "indexPos": 0, + "childCount": 3, + "tag": [ + { + "#text": "value", + "@_name": "Gabriel", + "indexPos": 0 + }, + { + "#text": 45, + "@_country": "Argentina", + "indexPos": 1 + }, + { + "#text": 65.34, + "@_some": "thing", + "indexPos": 2 + } + ] + } + }; + const result = parser.parse(xmlData,{ ignoreAttributes: false, appendIndexInNodes: true }); + // console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + }); + + it("should add index and childCount to array and ignore attributes", function() { + const xmlData = ` + value + 45 + 65.34 + `; + + const expected = { + "childCount": 1, + "rootNode": { + "indexPos": 0, + "childCount": 3, + "tag": [ + { + "#text": "value", + "indexPos": 0 + }, + { + "#text": 45, + "indexPos": 1 + }, + { + "#text": 65.34, + "indexPos": 2 + } + ] + } + }; + const result = parser.parse(xmlData,{ ignoreAttributes: true, appendIndexInNodes: true }); + // console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + }); + + it("should add index and childCount to array in right order", function() { + const xmlData = ` + value + + 65.34 + `; + + const expected = { + "childCount": 1, + "rootNode": { + "indexPos": 0, + "childCount": 3, + "tag": [ + { + "#text": "value", + "indexPos": 0 + }, + { + "#text": 65.34, + "indexPos": 2 + } + ], + "label": { + "#text": 45, + "indexPos": 1 + }, + } + }; + const result = parser.parse(xmlData,{ ignoreAttributes: false, appendIndexInNodes: true }); + // console.log(JSON.stringify(result,null,4)); + expect(result).toEqual(expected); + }); }); diff --git a/src/xmlstr2xmlnode.js b/src/xmlstr2xmlnode.js index f8dda8a2..874bbae9 100644 --- a/src/xmlstr2xmlnode.js +++ b/src/xmlstr2xmlnode.js @@ -4,10 +4,11 @@ const util = require('./util'); const buildOptions = require('./util').buildOptions; const xmlNode = require('./xmlNode'); const TagType = {OPENING: 1, CLOSING: 2, SELF: 3, CDATA: 4}; +const attrstr_regex = '((\\s*[\\w\\-._:]+(=((\'([^\']*)\')|("([^"]*)")))?)*)\\s*'; const regx = '<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\/)(NAME)\\s*>))([^<]*)' .replace(/NAME/g, util.nameRegexp); - + //const tagsRegx = new RegExp("<(\\/?[\\w:\\-\._]+)([^>]*)>(\\s*"+cdataRegx+")*([^<]+)?","g"); //const tagsRegx = new RegExp("<(\\/?)((\\w*:)?([\\w:\\-\._]+))([^>]*)>([^<]*)("+cdataRegx+"([^<]*))*([^<]+)?","g"); @@ -23,6 +24,8 @@ const defaultOptions = { attributeNamePrefix: '@_', attrNodeName: false, textNodeName: '#text', + appendIndexInNodes: false, + indexInNodesName: 'indexPos', ignoreAttributes: true, ignoreNameSpace: false, allowBooleanAttributes: false, //a tag can have attributes without any value @@ -49,6 +52,8 @@ const props = [ 'attributeNamePrefix', 'attrNodeName', 'textNodeName', + 'appendIndexInNodes', + 'indexInNodesName', 'ignoreAttributes', 'ignoreNameSpace', 'allowBooleanAttributes', @@ -115,6 +120,7 @@ const getTraversalObj = function(xmlData, options) { tag[8] = tag[8].substr(0, tag[8].length - 1); } childNode.attrsMap = buildAttributesMap(tag[8], options); + processAppendIndexInNodes(currentNode, childNode, options); currentNode.addChild(childNode); } else { //TagType.OPENING @@ -127,6 +133,7 @@ const getTraversalObj = function(xmlData, options) { childNode.startIndex=tag.index + tag[1].length } childNode.attrsMap = buildAttributesMap(tag[8], options); + processAppendIndexInNodes(currentNode, childNode, options); currentNode.addChild(childNode); currentNode = childNode; } @@ -138,6 +145,22 @@ const getTraversalObj = function(xmlData, options) { return xmlObj; }; + +function processAppendIndexInNodes(currentNode, childNode, options) { + if (options.appendIndexInNodes) { + if (currentNode.attrsMap === undefined) { currentNode.attrsMap = {}} + if (childNode.attrsMap === undefined) { childNode.attrsMap = {}} + const childCount = currentNode.attrsMap.childCount; + if (childCount !== undefined) { + childNode.attrsMap[options.indexInNodesName] = childCount; + } else { + childNode.attrsMap[options.indexInNodesName] = 0; + currentNode.attrsMap.childCount = 0; + } + currentNode.attrsMap.childCount++; + } +} + function processTagValue(parsedTags, options, parentTagName) { const tagName = parsedTags[7] || parentTagName; let val = parsedTags[12];