@@ -15,12 +15,14 @@ var defaultOptions = {
1515 textNodeName : "#text" ,
1616 ignoreAttributes : true ,
1717 ignoreNameSpace : false ,
18- // allowBooleanAttributes : false, //a tag can have attributes without any value
18+ allowBooleanAttributes : false , //a tag can have attributes without any value
1919 //ignoreRootElement : false,
2020 parseNodeValue : true ,
2121 parseAttributeValue : false ,
2222 arrayMode : false ,
2323 trimValues : true , //Trim string values of tag and attributes
24+ decodeHTMLchar : false ,
25+ //decodeStrict: false,
2426} ;
2527
2628var buildOptions = function ( options ) {
@@ -52,12 +54,6 @@ var getTraversalObj =function (xmlData,options){
5254 var xmlObj = new xmlNode ( '!xml' ) ;
5355 var currentNode = xmlObj ;
5456
55- //fake function calls to reduce coparisons
56- var resolveNS = options . ignoreNameSpace ? resolveNameSpace : fakeCall ;
57- var buildAttributesMap = options . ignoreAttributes ? fakeCallNoReturn : buildAttributesArr ;
58- var parseNodeVal = options . parseNodeValue ? parseValue : noParse ;
59- var parseAttrVal = options . parseAttributeValue ? parseValue : noParse ;
60-
6157 var tagsRegx = new RegExp ( "<((!\\[CDATA\\[(.*?)(\\]\\]>))|((\\w*:)?([\\w:\\-\\._]+))([^>]*)>|((\\/)((\\w*:)?([\\w:\\-\\._]+))>))([^<]*)" , "g" ) ;
6258 var tag = tagsRegx . exec ( xmlData ) ;
6359 var nextTag = tagsRegx . exec ( xmlData ) ;
@@ -68,23 +64,25 @@ var getTraversalObj =function (xmlData,options){
6864 if ( tagType === TagType . CLOSING ) {
6965 //add parsed data to parent node
7066 if ( currentNode . parent && tag [ 14 ] ) {
71- currentNode . parent . val = util . getValue ( currentNode . parent . val ) + "" + parseNodeVal ( he . decode ( tag [ 14 ] ) , options ) ;
67+ currentNode . parent . val = util . getValue ( currentNode . parent . val ) + "" + processTagValue ( tag [ 14 ] , options ) ;
7268 }
7369
74- //currentNode.parent.val = (currentNode.parent.val || "") + parseNodeVal(he.decode(tag[14]),options);
7570 currentNode = currentNode . parent ;
7671 } else if ( tagType === TagType . CDATA ) {
7772 //no attribute
7873 //add text to parent node
7974 //add parsed data to parent node
80- currentNode . val = ( currentNode . val || "" ) + ( tag [ 3 ] || "" ) + parseNodeVal ( he . decode ( tag [ 14 ] ) , options ) ;
75+ currentNode . val = ( currentNode . val || "" ) + ( tag [ 3 ] || "" ) + processTagValue ( tag [ 14 ] , options ) ;
8176 } else if ( tagType === TagType . SELF ) {
8277 var childNode = new xmlNode ( options . ignoreNameSpace ? tag [ 7 ] : tag [ 5 ] , currentNode , "" ) ;
83- childNode . attrsMap = buildAttributesMap ( tag [ 8 ] , options , resolveNS , parseAttrVal ) ;
78+ if ( tag [ 8 ] && tag [ 8 ] . length > 1 ) {
79+ tag [ 8 ] = tag [ 8 ] . substr ( 0 , tag [ 8 ] . length - 1 ) ;
80+ }
81+ childNode . attrsMap = buildAttributesMap ( tag [ 8 ] , options ) ;
8482 currentNode . addChild ( childNode ) ;
8583 } else { //TagType.OPENING
86- var childNode = new xmlNode ( options . ignoreNameSpace ? tag [ 7 ] : tag [ 5 ] , currentNode , parseNodeVal ( he . decode ( tag [ 14 ] ) , options ) ) ;
87- childNode . attrsMap = buildAttributesMap ( tag [ 8 ] , options , resolveNS , parseAttrVal ) ;
84+ var childNode = new xmlNode ( options . ignoreNameSpace ? tag [ 7 ] : tag [ 5 ] , currentNode , processTagValue ( tag [ 14 ] , options ) ) ;
85+ childNode . attrsMap = buildAttributesMap ( tag [ 8 ] , options ) ;
8886 currentNode . addChild ( childNode ) ;
8987 currentNode = childNode ;
9088 }
@@ -96,7 +94,19 @@ var getTraversalObj =function (xmlData,options){
9694 return xmlObj ;
9795} ;
9896
97+ function processTagValue ( val , options ) {
98+ if ( val ) {
99+ if ( options . trimValues ) {
100+ val = val . trim ( ) ;
101+ }
102+ if ( options . decodeHTMLchar ) {
103+ val = he . decode ( val ) ;
104+ }
105+ val = parseValue ( val , options . parseNodeValue ) ;
106+ }
99107
108+ return val ;
109+ }
100110
101111function checkForTagType ( match ) {
102112 if ( match [ 4 ] === "]]>" ) {
@@ -119,31 +129,23 @@ var xml2json = function (xmlData,options){
119129} ;
120130
121131
122- function resolveNameSpace ( tagname ) {
123- var tags = tagname . split ( ":" ) ;
124- var prefix = tagname . charAt ( 0 ) === "/" ? "/" : "" ;
125- if ( tags . length === 2 ) {
126- if ( tags [ 0 ] === "xmlns" ) {
127- return "" ;
132+ function resolveNameSpace ( tagname , options ) {
133+ if ( options . ignoreNameSpace ) {
134+ var tags = tagname . split ( ":" ) ;
135+ var prefix = tagname . charAt ( 0 ) === "/" ? "/" : "" ;
136+ if ( tags . length === 2 ) {
137+ if ( tags [ 0 ] === "xmlns" ) {
138+ return "" ;
139+ }
140+ tagname = prefix + tags [ 1 ] ;
128141 }
129- tagname = prefix + tags [ 1 ] ;
130142 }
131143 return tagname ;
132- }
133144
134- function noParse ( val ) {
135- if ( typeof val === "string" ) {
136- return val ;
137- } else {
138- return "" ;
139- }
140145}
141146
142- function parseValue ( val , options ) {
143- if ( typeof val === "string" ) {
144- if ( options . trimValues ) {
145- val = val . trim ( ) ;
146- }
147+ function parseValue ( val , shouldParse ) {
148+ if ( shouldParse && typeof val === "string" ) {
147149 if ( val . trim ( ) === "" || isNaN ( val ) ) {
148150 val = val === "true" ? true : val === "false" ? false : val ;
149151 } else {
@@ -161,32 +163,41 @@ function parseValue(val,options){
161163}
162164
163165//TODO: change regex to capture NS
164- var attrsRegx = new RegExp ( "([\\w\\-\\.\\:]+)\\s*=\\s*(['\"])((.|\n)*?)\\2" , "gm" ) ;
165- function buildAttributesArr ( attrStr , options , resolveNS , parseAttrVal ) {
166- if ( typeof attrStr === "string" ) {
166+ //var attrsRegx = new RegExp("([\\w\\-\\.\\:]+)\\s*=\\s*(['\"])((.|\n)*?)\\2","gm");
167+ var attrsRegx = new RegExp ( "([^\\s=]+)\\s*(=\\s*(['\"])(.*?)\\3)?" , "g" ) ;
168+ function buildAttributesMap ( attrStr , options ) {
169+ if ( ! options . ignoreAttributes && typeof attrStr === "string" ) {
167170 //attrStr = attrStr || attrStr.trim();
168171
169- if ( attrStr . length > 3 ) {
170-
171- var matches = util . getAllMatches ( attrStr , attrsRegx ) ;
172- var len = matches . length ; //don't make it inline
173- var attrs = { } ;
174- for ( var i = 0 ; i < len ; i ++ ) {
175- var attrName = resolveNS ( matches [ i ] [ 1 ] ) ;
176- if ( attrName . length && attrName !== "xmlns" ) {
177- attrs [ options . attributeNamePrefix + attrName ] = parseAttrVal ( matches [ i ] [ 3 ] , options ) ;
172+ var matches = util . getAllMatches ( attrStr , attrsRegx ) ;
173+ var len = matches . length ; //don't make it inline
174+ var attrs = { } ;
175+ for ( var i = 0 ; i < len ; i ++ ) {
176+ var attrName = resolveNameSpace ( matches [ i ] [ 1 ] , options ) ;
177+ if ( attrName . length && attrName !== "xmlns" ) {
178+ if ( matches [ i ] [ 4 ] ) {
179+ if ( options . trimValues ) {
180+ matches [ i ] [ 4 ] = matches [ i ] [ 4 ] . trim ( ) ;
181+ }
182+ if ( options . decodeHTMLchar ) {
183+ matches [ i ] [ 4 ] = he . decode ( matches [ i ] [ 4 ] , { isAttributeValue : true } ) ;
184+ }
185+ attrs [ options . attributeNamePrefix + attrName ] = parseValue ( matches [ i ] [ 4 ] , options . parseAttributeValue ) ;
186+ } else if ( options . allowBooleanAttributes ) {
187+ attrs [ options . attributeNamePrefix + attrName ] = true ;
178188 }
189+
179190 }
180- if ( ! Object . keys ( attrs ) . length ) {
181- return ;
182- }
183- if ( options . attrNodeName ) {
184- var attrCollection = { } ;
185- attrCollection [ options . attrNodeName ] = attrs ;
186- return attrCollection ;
187- }
188- return attrs ;
189191 }
192+ if ( ! Object . keys ( attrs ) . length ) {
193+ return ;
194+ }
195+ if ( options . attrNodeName ) {
196+ var attrCollection = { } ;
197+ attrCollection [ options . attrNodeName ] = attrs ;
198+ return attrCollection ;
199+ }
200+ return attrs ;
190201 }
191202}
192203
0 commit comments