Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom node post-processing support #642

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,23 @@ value})``. Possible options are:
return name
}
```
Added in 0.4.6

Added in 0.x.y
* `nodeProcessors` (default: `null`): Allows custom processing to be run on a node after xml2js has converted it. Accepts an `Array` of objects with two functions:
```javascript
// Processor to convert the XML node "<Foo type="integer">1234</Foo>" to the number "1234"
{
canProcess: function(node) {
// If node has "integer" attribute, this processor will handle it
return node?.$?.type === "integer";
},
process: function(node) {
// Replace this node with the parsed text contents
return Number.parseInt(node._);
}
}
```
`nodeProcessors` are applied in the order they appear in.

Options for the `Builder` class
-------------------------------
Expand Down
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.

2 changes: 2 additions & 0 deletions src/defaults.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ exports.defaults = {
attrValueProcessors: null
tagNameProcessors: null
valueProcessors: null
nodeProcessors: null
emptyTag: ''

"0.2":
Expand Down Expand Up @@ -61,6 +62,7 @@ exports.defaults = {
attrValueProcessors: null
tagNameProcessors: null
valueProcessors: null
nodeProcessors: null
# xml building options
rootName: 'root'
xmldec: {'version': '1.0', 'encoding': 'UTF-8', 'standalone': true}
Expand Down
5 changes: 5 additions & 0 deletions src/parser.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ class exports.Parser extends events
if Object.keys(obj).length == 1 and charkey of obj and not @EXPLICIT_CHARKEY
obj = obj[charkey]

if @options.nodeProcessors?
for processor in @options.nodeProcessors
if processor.canProcess obj
obj = processor.process obj

# check whether we closed all the open tags
if stack.length > 0
@assignOrPush s, nodeName, obj
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/sample.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@
<emptytestanother>

</emptytestanother>
<nodeProcessorTest type="number">1234</nodeProcessorTest>
</sample>
15 changes: 12 additions & 3 deletions test/parser.test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ nameCutoff = (name) ->
replaceValueByName = (value, name) ->
return name

sampleNodeProcessor =
canProcess: (node) -> node?.$?.type == "number"
process: (node) -> Number.parseInt(node._)


###
The `validator` function validates the value at the XPath. It also transforms the value
if necessary to conform to the schema or other validation information being used. If there
Expand Down Expand Up @@ -599,7 +604,11 @@ module.exports =
'test valueProcessors key param': skeleton(valueProcessors: [replaceValueByName], (r)->
console.log 'Result object: ' + util.inspect r, false, 10
equ r.sample.valueProcessTest[0], 'valueProcessTest')


'test nodeProcessors': skeleton(nodeProcessors: [sampleNodeProcessor], (r)->
console.log 'Result object: ' + util.inspect r, false, 10
equ r.sample.nodeProcessorTest[0], 1234)

'test parseStringPromise parsing': (test) ->
x2js = new xml2js.Parser()
readFilePromise(fileName).then (data) ->
Expand All @@ -610,7 +619,7 @@ module.exports =
test.finish()
.catch (err) ->
test.fail('Should not error')

'test parseStringPromise with bad input': (test) ->
x2js = new xml2js.Parser()
x2js.parseStringPromise("< a moose bit my sister>").then (r) ->
Expand Down Expand Up @@ -640,7 +649,7 @@ module.exports =
test.finish()
.catch (err) ->
test.fail('Should not error')

'test global parseStringPromise with bad input': (test) ->
xml2js.parseStringPromise("< a moose bit my sister>").then (r) ->
test.fail('Should fail')
Expand Down