Skip to content

Commit

Permalink
Added optional comment handling
Browse files Browse the repository at this point in the history
  • Loading branch information
visorgames committed Mar 8, 2019
1 parent 0f0a298 commit 0bdbcce
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 30 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ value})``. Possible options are:
Version 0.1 default was `@`.
* `charkey` (default: `_`): Prefix that is used to access the character
content. Version 0.1 default was `#`.
* `commentskey` (default: `$comments`): Prefix that is used to access the comments.
* `parseComments` (default: `false`): Determines whether comments should be parsed.
* `explicitCharkey` (default: `false`)
* `trim` (default: `false`): Trim the whitespace at the beginning and end of
text nodes.
Expand Down Expand Up @@ -377,6 +379,7 @@ Possible options are:
Version 0.1 default was `@`.
* `charkey` (default: `_`): Prefix that is used to access the character
content. Version 0.1 default was `#`.
* `commentskey` (default: `$comments`): Prefix that is used to access the comments.
* `rootName` (default `root` or the root key name): root element name to be used in case
`explicitRoot` is `false` or to override the root element name.
* `renderOpts` (default `{ 'pretty': true, 'indent': ' ', 'newline': '\n' }`):
Expand Down
10 changes: 8 additions & 2 deletions lib/builder.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions lib/defaults.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 16 additions & 2 deletions lib/parser.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions src/builder.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class exports.Builder
buildObject: (rootObj) ->
attrkey = @options.attrkey
charkey = @options.charkey
commentskey = @options.commentskey

# If there is a sane-looking first element to use as the root,
# and the user hasn't specified a non-default rootName,
Expand Down Expand Up @@ -69,7 +70,12 @@ class exports.Builder
else
element = element.txt child

# Case #3 Array data
# Case #3 Comment
else if key is commentskey
for value in child
element = element.comment value

# Case #4 Array data
else if Array.isArray child
for own index, entry of child
if typeof entry is 'string'
Expand All @@ -80,11 +86,11 @@ class exports.Builder
else
element = render(element.ele(key), entry).up()

# Case #4 Objects
# Case #5 Objects
else if typeof child is "object"
element = render(element.ele(key), child).up()

# Case #5 String and remaining types
# Case #6 String and remaining types
else
if typeof child is 'string' && @options.cdata && requiresCDATA child
element = element.ele(key).raw(wrapCDATA child).up()
Expand Down
2 changes: 2 additions & 0 deletions src/defaults.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ exports.defaults = {
normalizeTags: false
attrkey: "$"
charkey: "_"
commentskey: "$comments"
parseComments: false
explicitArray: true
ignoreAttrs: false
mergeAttrs: false
Expand Down
9 changes: 9 additions & 0 deletions src/parser.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class exports.Parser extends events.EventEmitter
# aliases, so we don't have to type so much
attrkey = @options.attrkey
charkey = @options.charkey
commentskey = @options.commentskey

@saxParser.onopentag = (node) =>
obj = {}
Expand Down Expand Up @@ -225,6 +226,14 @@ class exports.Parser extends events.EventEmitter
if s
s.cdata = true

if @options.parseComments
@saxParser.oncomment = (text) =>
s = stack[stack.length - 1]
if s
s[commentskey] = s[commentskey] or []
s[commentskey].push text.slice(1,-1)
s

parseString: (str, cb) =>
if cb? and typeof cb is "function"
@on "end", (result) ->
Expand Down
2 changes: 1 addition & 1 deletion test/builder.test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ module.exports =
fileName = path.join __dirname, '/fixtures/build_sample.xml'
fs.readFile fileName, (err, xmlData) ->
xmlExpected = xmlData.toString()
xml2js.parseString xmlData, {'trim': true}, (err, obj) ->
xml2js.parseString xmlData, {'trim': true, 'parseComments': true}, (err, obj) ->
equ err, null
builder = new xml2js.Builder({})
xmlActual = builder.buildObject obj
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/build_sample.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
<chartest desc="Test for CHARs">Character data here!</chartest>
<nochartest desc="No data" misc="false"/>
<nochildrentest desc="No data" misc="false"/>
<!-- This is the first sample comment! -->
<listtest>
<!-- This is the second sample comment! -->
<item>
This is
character
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/sample.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
<cdatawhitespacetest desc="Test for CDATA with whitespace" misc="true"><![CDATA[ ]]></cdatawhitespacetest>
<nochartest desc="No data" misc="false" />
<nochildrentest desc="No data" misc="false" />
<!-- This is the first sample comment! -->
<whitespacetest desc="Test for normalizing and trimming">
Line One
Line Two
</whitespacetest>
<listtest attr="Attribute">
<!-- This is the second sample comment! -->
<item>
This <subitem>Foo(1)</subitem> is
<subitem>Foo(2)</subitem>
Expand Down
49 changes: 27 additions & 22 deletions test/parser.test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ module.exports =
# determine number of items in object
equ Object.keys(r.sample.tagcasetest[0]).length, 3)

'test parse with parseComments': skeleton(parseComments: true, (r) ->
console.log 'Result object: ' + util.inspect r, false, 10
equ r.sample.$comments[0], 'This is the first sample comment!'
equ r.sample.listtest[0].$comments[0], 'This is the second sample comment!')

'test parse with explicitCharkey': skeleton(explicitCharkey: true, (r) ->
console.log 'Result object: ' + util.inspect r, false, 10
equ r.sample.chartest[0].$.desc, 'Test for CHARs'
Expand Down Expand Up @@ -190,32 +195,32 @@ module.exports =

'test parse with explicitChildren and charsAsChildren and preserveChildrenOrder and includeWhiteChars': skeleton(explicitChildren: true, preserveChildrenOrder: true, charsAsChildren: true, includeWhiteChars: true, (r) ->
console.log 'Result object: ' + util.inspect r, false, 10
equ r.sample.$$[35]['#name'], 'textordertest'
equ r.sample.$$[35].$$[0]['#name'], '__text__'
equ r.sample.$$[35].$$[0]._, 'this is text with '
equ r.sample.$$[35].$$[1]['#name'], 'b'
equ r.sample.$$[35].$$[1]._, 'markup'
equ r.sample.$$[35].$$[2]['#name'], '__text__'
equ r.sample.$$[35].$$[2]._, ' '
equ r.sample.$$[35].$$[3]['#name'], 'em'
equ r.sample.$$[35].$$[3]._, 'like this'
equ r.sample.$$[35].$$[4]['#name'], '__text__'
equ r.sample.$$[35].$$[4]._, ' in the middle')
equ r.sample.$$[36]['#name'], 'textordertest'
equ r.sample.$$[36].$$[0]['#name'], '__text__'
equ r.sample.$$[36].$$[0]._, 'this is text with '
equ r.sample.$$[36].$$[1]['#name'], 'b'
equ r.sample.$$[36].$$[1]._, 'markup'
equ r.sample.$$[36].$$[2]['#name'], '__text__'
equ r.sample.$$[36].$$[2]._, ' '
equ r.sample.$$[36].$$[3]['#name'], 'em'
equ r.sample.$$[36].$$[3]._, 'like this'
equ r.sample.$$[36].$$[4]['#name'], '__text__'
equ r.sample.$$[36].$$[4]._, ' in the middle')

'test parse with explicitChildren and charsAsChildren and preserveChildrenOrder and includeWhiteChars and normalize': skeleton(explicitChildren: true, preserveChildrenOrder: true, charsAsChildren: true, includeWhiteChars: true, normalize: true, (r) ->
console.log 'Result object: ' + util.inspect r, false, 10
# normalized whitespace-only text node becomes empty string
equ r.sample.$$[35]['#name'], 'textordertest'
equ r.sample.$$[35].$$[0]['#name'], '__text__'
equ r.sample.$$[35].$$[0]._, 'this is text with'
equ r.sample.$$[35].$$[1]['#name'], 'b'
equ r.sample.$$[35].$$[1]._, 'markup'
equ r.sample.$$[35].$$[2]['#name'], '__text__'
equ r.sample.$$[35].$$[2]._, ''
equ r.sample.$$[35].$$[3]['#name'], 'em'
equ r.sample.$$[35].$$[3]._, 'like this'
equ r.sample.$$[35].$$[4]['#name'], '__text__'
equ r.sample.$$[35].$$[4]._, 'in the middle')
equ r.sample.$$[36]['#name'], 'textordertest'
equ r.sample.$$[36].$$[0]['#name'], '__text__'
equ r.sample.$$[36].$$[0]._, 'this is text with'
equ r.sample.$$[36].$$[1]['#name'], 'b'
equ r.sample.$$[36].$$[1]._, 'markup'
equ r.sample.$$[36].$$[2]['#name'], '__text__'
equ r.sample.$$[36].$$[2]._, ''
equ r.sample.$$[36].$$[3]['#name'], 'em'
equ r.sample.$$[36].$$[3]._, 'like this'
equ r.sample.$$[36].$$[4]['#name'], '__text__'
equ r.sample.$$[36].$$[4]._, 'in the middle')

'test element without children': skeleton(explicitChildren: true, (r) ->
console.log 'Result object: ' + util.inspect r, false, 10
Expand Down

0 comments on commit 0bdbcce

Please sign in to comment.