Skip to content

Commit c7df57c

Browse files
committed
Add parseStringSync
Create a sync version of parseString to API to permit calling without a callback. The current implemenation is sync due to underlying implementation of SAX parser. Examples: ```js // Via root API var result = xml2js.parseStringSync('< ... >', options) // Via parser var parser = new xml2js.Parser(options); var result = parser.parseStringSync('< ... >'); ``` See #241 by @nobodyman See #319 by @mrparkers
1 parent 847e0c3 commit c7df57c

7 files changed

+117
-2
lines changed

README.md

+20
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,26 @@ not, we got you covered! Starting with 0.2.8 you can also leave it out, in
104104
which case `xml2js` will helpfully add it for you, no bad surprises and
105105
inexplicable bugs!
106106

107+
Synchronous usage
108+
------------------
109+
110+
Forced into a sync use-case? Use the `parseStringSync` method to execute parsing
111+
in a synchronous manner. Failures will result in an thrown error.
112+
113+
```javascript
114+
var fs = require('fs'),
115+
xml2js = require('xml2js');
116+
117+
var data = fs.readFileSync(__dirname + '/foo.xml', 'utf8');
118+
119+
// With parser
120+
var parser = new xml2js.Parser(/* options */);
121+
var result = parser.parseStringSync(data);
122+
123+
// Without parser
124+
var result = xml2js.parseStringSync(data /*, options */);
125+
```
126+
107127
Parsing multiple files
108128
----------------------
109129

lib/parser.js

+25
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/xml2js.js

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@
6363
"lib": "./lib"
6464
},
6565
"scripts": {
66+
"build": "cake build",
6667
"test": "zap",
6768
"coverage": "nyc npm test && nyc report",
68-
"coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls"
69+
"coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls",
70+
"doc": "cake doc"
6971
},
7072
"repository": {
7173
"type": "git",

src/parser.coffee

+21-1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,20 @@ class exports.Parser extends events.EventEmitter
253253
else if @saxParser.ended
254254
throw err
255255

256+
parseStringSync: (str) =>
257+
# SAX events block when given a string instead of a stream
258+
result = undefined
259+
err = undefined
260+
cb = (_err, _result) ->
261+
result = _result
262+
err = _err
263+
264+
# parseString will implicitly call cb (thus setting closure result) before returning
265+
@parseString str, cb
266+
if err
267+
throw err
268+
result
269+
256270
exports.parseString = (str, a, b) ->
257271
# let's determine what we got as arguments
258272
if b?
@@ -267,6 +281,12 @@ exports.parseString = (str, a, b) ->
267281
# and options should be empty - default
268282
options = {}
269283

270-
# the rest is super-easy
271284
parser = new exports.Parser options
272285
parser.parseString str, cb
286+
287+
exports.parseStringSync = (str, a) ->
288+
if typeof a == 'object'
289+
options = a
290+
291+
parser = new exports.Parser options
292+
parser.parseStringSync str

src/xml2js.coffee

+1
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ exports.Builder = builder.Builder
1818
exports.Parser = parser.Parser
1919

2020
exports.parseString = parser.parseString
21+
exports.parseStringSync = parser.parseStringSync

test/parser.test.coffee

+45
Original file line numberDiff line numberDiff line change
@@ -574,3 +574,48 @@ module.exports =
574574
console.log 'Result object: ' + util.inspect r, false, 10
575575
equ r.hasOwnProperty('SAMP'), true
576576
equ r.SAMP.hasOwnProperty('TAGN'), true)
577+
578+
'test sync parsing': (test) ->
579+
x2js = new xml2js.Parser()
580+
data = fs.readFileSync fileName, 'utf8'
581+
r = x2js.parseStringSync data
582+
assert.notEqual r, null
583+
equ r.sample.listtest[0].item[0].subitem[0], 'Foo(1)'
584+
test.finish()
585+
586+
'test sync with bad input': (test) ->
587+
x2js = new xml2js.Parser()
588+
data = fs.readFileSync fileName, 'utf8'
589+
err = null
590+
try
591+
r = x2js.parseStringSync "< a moose bit my sister>";
592+
catch _err
593+
err = _err
594+
assert.notEqual err, null
595+
test.finish()
596+
597+
'test global sync parsing': (test) ->
598+
data = fs.readFileSync fileName, 'utf8'
599+
r = xml2js.parseStringSync data
600+
assert.notEqual r, null
601+
equ r.sample.listtest[0].item[0].subitem[0], 'Foo(1)'
602+
test.finish()
603+
604+
'test global sync parsing with options': (test) ->
605+
data = fs.readFileSync fileName, 'utf8'
606+
r = xml2js.parseStringSync data,
607+
trim: true
608+
normalize: true
609+
console.log r
610+
equ r.sample.whitespacetest[0]._, 'Line One Line Two'
611+
test.finish()
612+
613+
'test global sync with bad input': (test) ->
614+
data = fs.readFileSync fileName, 'utf8'
615+
err = null
616+
try
617+
r = xml2js.parseStringSync "< a moose bit my sister>";
618+
catch _err
619+
err = _err
620+
assert.notEqual err, null
621+
test.finish()

0 commit comments

Comments
 (0)