diff --git a/src/builder.coffee b/src/builder.coffee index 5653fde0..c8f7537a 100644 --- a/src/builder.coffee +++ b/src/builder.coffee @@ -71,14 +71,24 @@ class exports.Builder # Case #3 Array data else if Array.isArray child + # Simple-type children (numbers and strings) and complex children (objects and arrays) are converted + # differently. Arrays of simple children will repeat the parent element, e.g. `12`, + # while complex child arrays will be wrapped in their parent, e.g. + # `fuzbaz` for own index, entry of child - if typeof entry is 'string' + if typeof entry isnt 'object' + # single element, just append it as text if @options.cdata && requiresCDATA entry element = element.ele(key).raw(wrapCDATA entry).up() else element = element.ele(key, entry).up() else - element = render(element.ele(key), entry).up() + if (!arrayElement) + arrayElement = element.ele(key) + render(arrayElement, entry) + if (arrayElement) + element = arrayElement.up() + arrayElement = null # Case #4 Objects else if typeof child is "object" diff --git a/test/builder.test.coffee b/test/builder.test.coffee index e9c12be3..d8d02320 100644 --- a/test/builder.test.coffee +++ b/test/builder.test.coffee @@ -250,6 +250,38 @@ module.exports = diffeq expected, actual test.finish() + 'test attribute rendering': (test) -> + expected = """ + + + 10 + + + """ + opts = cdata: true + builder = new xml2js.Builder opts + obj = {"xml":{ + "$": {"foo": "bar"} + "MsgId":10}} + actual = builder.buildObject obj + diffeq expected, actual + test.finish() + + 'test nested attribute rendering': (test) -> + expected = """ + + + 10 + + + """ + opts = cdata: true + builder = new xml2js.Builder opts + obj = {"xml":{"MsgId":{"$": {"foo": "bar"}, "_": 10}}} + actual = builder.buildObject obj + diffeq expected, actual + test.finish() + 'test does not error on array values when checking for cdata': (test) -> expected = """ @@ -281,3 +313,24 @@ module.exports = actual = builder.buildObject obj diffeq expected, actual test.finish() + + 'test building obj with nested array': (test) -> + expected = """ + + + +
+
+ + + + """ + opts = cdata: true + builder = new xml2js.Builder opts + obj = {request: { headers: [ + { header: { '$': { 'method': 'INVITE', name: 'X-Mode', value: 'standard' } } }, + { header: { '$': { 'method': 'INVITE', name: 'X-Prop', value: 'default' } } } + ]}} + actual = builder.buildObject obj + diffeq expected, actual + test.finish()