Leonidas-from-XIV / node-xml2js

XML to JavaScript object converter.
MIT License
4.84k stars 598 forks source link

Malformed XML sneaks by callback of parseString #617

Open mandrewpowers opened 3 years ago

mandrewpowers commented 3 years ago

When parsing this malformed XML, <root></root></root>, through parseString with and without a callback function I am experiencing different results. With a callback I am seeing { "root": "" } and no error, but without the callback an error is thrown synchronously. Although, without a callback and a correctly formatted XML string I don't get the results.

Unless I somehow misunderstood the API this seems quite incorrect. I at least expected the callback to receive a populated err argument even if I was using the package incorrectly when it throws as I originally expected. The promisified version of course has the same unexpected behavior.

Node: v12.16.1 xml2js: 0.4.23

Example:

> xml2js.parseString(`<root></root></root>`, {}, (err, result) => console.log(`Results: err=${err}, result=${JSON.stringify(result)}`))
Results: err=null, result={"root":""}
undefined

> xml2js.parseString(`<root></root></root>`, {})
Uncaught Error: Unmatched closing tag: root
Line: 0
Column: 20
Char: >
    at error (/Users/andrewpowers/simplisafe/palpatine/files/src/node_modules/sax/lib/sax.js:651:10)
    at strictFail (/Users/andrewpowers/simplisafe/palpatine/files/src/node_modules/sax/lib/sax.js:677:7)
    at closeTag (/Users/andrewpowers/simplisafe/palpatine/files/src/node_modules/sax/lib/sax.js:879:7)
    at SAXParser.write (/Users/andrewpowers/simplisafe/palpatine/files/src/node_modules/sax/lib/sax.js:1436:13)
    at Parser.exports.Parser.Parser.parseString (/Users/andrewpowers/simplisafe/palpatine/files/src/node_modules/xml2js/lib/parser.js:323:31)
    at Parser.parseString (/Users/andrewpowers/simplisafe/palpatine/files/src/node_modules/xml2js/lib/parser.js:5:59)
    at Object.exports.parseString (/Users/andrewpowers/simplisafe/palpatine/files/src/node_modules/xml2js/lib/parser.js:369:19)
mandrewpowers commented 3 years ago

Updated once I realized I seem to be using the API incorrectly when not passing a callback. This may be a sax problem, but I'm honestly not sure.

mandrewpowers commented 3 years ago

Last additional comment:

Noticed if the extra token is an orphaned opening tag such as <root></root><root>, it is also not detected since the stack seems to clean up even if the stream still has left over token(s).

Leonidas-from-XIV commented 3 years ago

While I agree that this is surprising, it is not all that unexpected since xml2js aims to parse one item from the string and by the time the </root> is encountered the tree is finished, so whatever comes afterwards can be ignored (it probably should not be ignored, because that means it accepts invalid XML but I would assume that many JSON parsers also accept {}} as input only to discard everything after a complete object has been parsed from the input stream.

andrew-stupchuk commented 2 years ago

same issue: first time parseString return an error, for second try i received object with incorrect data . any workarounds?