Skip to content

Commit

Permalink
Removed the skipNullAttributes option.
Browse files Browse the repository at this point in the history
null attributes are now skipped by default. Added the `keepNullAttributes` option in case someone needs the old behavior.

BREAKING CHANGE: `skipNullAttributes` option removed.
  • Loading branch information
oozcitak committed Feb 5, 2019
1 parent 51829cc commit 782540c
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 60 deletions.
2 changes: 0 additions & 2 deletions src/XMLAttribute.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ module.exports = class XMLAttribute

if not name?
throw new Error "Missing attribute name. " + @debugInfo(name)
if not value?
throw new Error "Missing attribute value. " + @debugInfo(name)

@name = @stringify.attName name
@value = @stringify.attValue value
Expand Down
4 changes: 2 additions & 2 deletions src/XMLDocument.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ module.exports = class XMLDocument extends XMLNode
#
# `options.skipNullNodes` whether nodes with null values will be ignored:
# true or false
# `options.skipNullAttributes` whether attributes with null values will be
# ignored: true or false
# `options.keepNullAttributes` whether attributes with null values will be
# kept or ignored: true or false
# `options.ignoreDecorators` whether decorator strings will be ignored when
# converting JS objects: true or false
# `options.separateArrayItems` whether array items are created as separate
Expand Down
11 changes: 5 additions & 6 deletions src/XMLDocumentCB.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ module.exports = class XMLDocumentCB
#
# `options.skipNullNodes` whether nodes with null values will be ignored:
# true or false
# `options.skipNullAttributes` whether attributes with null values will be
# ignored: true or false
# `options.keepNullAttributes` whether attributes with null values will be
# kept or ignored: true or false
# `options.ignoreDecorators` whether decorator strings will be ignored when
# converting JS objects: true or false
# `options.separateArrayItems` whether array items are created as separate
Expand Down Expand Up @@ -91,9 +91,6 @@ module.exports = class XMLDocumentCB

name = getValue name

if attributes == null and not text?
[attributes, text] = [{}, null]

attributes ?= {}
attributes = getValue attributes
# swap argument order: text <-> attributes
Expand Down Expand Up @@ -138,7 +135,9 @@ module.exports = class XMLDocumentCB
@attribute attName, attValue
else
value = value.apply() if isFunction value
if not @options.skipNullAttributes or value?
if @options.keepNullAttributes and not value?
@currentNode.attributes[name] = new XMLAttribute @, name, ""
else if value?
@currentNode.attributes[name] = new XMLAttribute @, name, value

return @
Expand Down
4 changes: 3 additions & 1 deletion src/XMLElement.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ module.exports = class XMLElement extends XMLNode
@attribute attName, attValue
else
value = value.apply() if isFunction value
if not @options.skipNullAttributes or value?
if @options.keepNullAttributes and not value?
@attributes[name] = new XMLAttribute @, name, ""
else if value?
@attributes[name] = new XMLAttribute @, name, value

return @
Expand Down
8 changes: 4 additions & 4 deletions src/index.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ XMLStreamWriter = require './XMLStreamWriter'
# true or false
# `options.skipNullNodes` whether nodes with null values will be ignored:
# true or false
# `options.skipNullAttributes` whether attributes with null values will be
# ignored: true or false
# `options.keepNullAttributes` whether attributes with null values will be
# kept or ignored: true or false
# `options.ignoreDecorators` whether decorator strings will be ignored when
# converting JS objects: true or false
# `options.separateArrayItems` whether array items are created as separate
Expand Down Expand Up @@ -59,8 +59,8 @@ module.exports.create = (name, xmldec, doctype, options) ->
#
# `options.skipNullNodes` whether nodes with null values will be ignored:
# true or false
# `options.skipNullAttributes` whether attributes with null values will be
# ignored: true or false
# `options.keepNullAttributes` whether attributes with null values will be
# kept or ignored: true or false
# `options.ignoreDecorators` whether decorator strings will be ignored when
# converting JS objects: true or false
# `options.separateArrayItems` whether array items are created as separate
Expand Down
32 changes: 28 additions & 4 deletions test/basic/attributes.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,48 @@ suite 'Attributes:', ->

test 'Skip if null attribute (ele)', ->
eq(
xml('test4', { headless: true, skipNullAttributes: true })
.ele('node', 'element', {"first":null, 'second': '2'})
xml('test4', { headless: true })
.ele('node', 'element', {"first": null, "second": '2'})
.end()
'<test4><node second="2">element</node></test4>'
)

test 'Skip if null attribute (att)', ->
eq(
xml('test4', { headless: true, skipNullAttributes: true })
xml('test4', { headless: true })
.ele('node').att("first")
.end()
'<test4><node/></test4>'
)

test 'Skip if null attribute (JSON)', ->
eq(
xml('test4', { headless: true, skipNullAttributes: true })
xml('test4', { headless: true })
.ele({'@first': null, '@second': '2'})
.end()
'<test4 second="2"/>'
)

test 'Keep null attribute (ele)', ->
eq(
xml('test4', { headless: true, keepNullAttributes: true })
.ele('node', 'element', {"first": null, "second": '2'})
.end()
'<test4><node first="" second="2">element</node></test4>'
)

test 'Keep null attribute (att)', ->
eq(
xml('test4', { headless: true, keepNullAttributes: true })
.ele('node').att("first")
.end()
'<test4><node first=""/></test4>'
)

test 'Keep null attribute (JSON)', ->
eq(
xml('test4', { headless: true, keepNullAttributes: true })
.ele({'@first': null, '@second': '2'})
.end()
'<test4 first="" second="2"/>'
)
64 changes: 52 additions & 12 deletions test/callback/attributes.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,62 @@ suite 'Attributes:', ->
data = (chunk, level) ->
result += chunk

doc(data)
.node('test4')
.ele('node', {"first":"1", "second":"2"})
.att("third", "3")
test 'All forms of att() usage', ->
result = ''
doc(data)
.node('test4')
.ele('node', {"first":"1", "second":"2"})
.att("third", "3")
.up()
.ele('node').att({"first":"1", "second":"2"}).up()
.up()
.ele('node').att({"first":"1", "second":"2"}).up()
.up()
.end()
.end()

eq(
result

'<test4>' +
'<node first="1" second="2" third="3"/>' +
'<node first="1" second="2"/>' +
'</test4>'
)

test 'Skip null attributes', ->
result = ''
doc(data)
.node('test')
.ele('node', {"first": null})
.att("third", null)
.up()
.ele('node').att({"first": null}).up()
.up()
.end()

test 'All forms of att() usage', ->
eq(
result

'<test4>' +
'<node first="1" second="2" third="3"/>' +
'<node first="1" second="2"/>' +
'</test4>'
'<test>' +
'<node/>' +
'<node/>' +
'</test>'
)

test 'Keep null attributes', ->
result = ''
doc({ keepNullAttributes: true }, data)
.node('test')
.ele('node', {"first": null})
.att("second", null)
.up()
.ele('node').att({"first": null}).up()
.up()
.end()

eq(
result

'<test>' +
'<node first="" second=""/>' +
'<node first=""/>' +
'</test>'
)
30 changes: 1 addition & 29 deletions test/guards/attributes.coffee
Original file line number Diff line number Diff line change
@@ -1,35 +1,7 @@
suite 'attribute() Guards:', ->
test 'Throw if null attribute (ele)', ->
err(
() -> xml('test4', { headless: true }).ele('node', 'element', {"first": null, "second":"2"})
Error
"Missing attribute value. attribute: {first}, parent: <node>"
)

test 'Throw if null attribute (att)', ->
err(
() -> xml('test4', { headless: true }).ele('node').att("first")
Error
"Missing attribute value. attribute: {first}, parent: <node>"
)

test 'Throw if null attribute name (att)', ->
err(
() -> xml('test4', { headless: true }).ele('node').att(null, "first")
() -> xml('test4', { headless: true }).ele('node').att(null, '')
Error
"Missing attribute name. parent: <node>"
)

test 'Throw if null attribute value (att)', ->
err(
() -> xml('test4', { headless: true }).ele('node').att("first", null)
Error
"Missing attribute value. attribute: {first}, parent: <node>"
)

test 'Throw if null attribute (JSON)', ->
err(
() -> xml('test4', { headless: true }).ele({'@first': null})
Error
"Missing attribute value. attribute: {first}, parent: <test4>"
)

0 comments on commit 782540c

Please sign in to comment.