diff options
| author | Michael Williamson <mike@zwobble.org> | 2022-11-27 15:01:01 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-02-07 19:39:26 +0000 |
| commit | 0894561a06782812a4e73725ede6642da4501db0 (patch) | |
| tree | a3d30a820bcb8a9de7789f5ee1899d99e1215f1e /lib | |
| parent | aecb9ed67bd2f73275442493b69e88e648273e56 (diff) | |
Replace sax with xmldom
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/xml/reader.js | 112 | ||||
| -rw-r--r-- | lib/xml/xmldom.js | 23 |
2 files changed, 72 insertions, 63 deletions
diff --git a/lib/xml/reader.js b/lib/xml/reader.js index 0c2e7f5..41aabde 100644 --- a/lib/xml/reader.js +++ b/lib/xml/reader.js @@ -1,83 +1,69 @@ var promises = require("../promises"); -var sax = require("sax"); var _ = require("underscore"); +var xmldom = require("./xmldom"); var nodes = require("./nodes"); var Element = nodes.Element; exports.readString = readString; +var Node = xmldom.Node; + function readString(xmlString, namespaceMap) { namespaceMap = namespaceMap || {}; - - var finished = false; - var parser = sax.parser(true, {xmlns: true, position: false}); - - var rootElement = {children: []}; - var currentElement = rootElement; - var stack = []; - - var deferred = promises.defer(); - - parser.onopentag = function(node) { - var attributes = mapObject(node.attributes, function(attribute) { - return attribute.value; - }, mapName); - - var element = new Element(mapName(node), attributes); - currentElement.children.push(element); - stack.push(currentElement); - currentElement = element; - }; - - function mapName(node) { - if (node.uri) { - var mappedPrefix = namespaceMap[node.uri]; + + try { + var document = xmldom.parseFromString(xmlString, "text/xml"); + } catch (error) { + return promises.reject(error); + } + + if (document.documentElement.tagName === "parsererror") { + return promises.resolve(new Error(document.documentElement.textContent)); + } + + function convertNode(node) { + switch (node.nodeType) { + case Node.ELEMENT_NODE: + return convertElement(node); + case Node.TEXT_NODE: + return nodes.text(node.nodeValue); + } + } + + function convertElement(element) { + var convertedName = convertName(element); + + var convertedChildren = []; + _.forEach(element.childNodes, function(childNode) { + var convertedNode = convertNode(childNode); + if (convertedNode) { + convertedChildren.push(convertedNode); + } + }); + + var convertedAttributes = {}; + _.forEach(element.attributes, function(attribute) { + convertedAttributes[convertName(attribute)] = attribute.value; + }); + + return new Element(convertedName, convertedAttributes, convertedChildren); + } + + function convertName(node) { + if (node.namespaceURI) { + var mappedPrefix = namespaceMap[node.namespaceURI]; var prefix; if (mappedPrefix) { prefix = mappedPrefix + ":"; } else { - prefix = "{" + node.uri + "}"; + prefix = "{" + node.namespaceURI + "}"; } - return prefix + node.local; + return prefix + node.localName; } else { - return node.local; + return node.localName; } } - - parser.onclosetag = function(node) { - currentElement = stack.pop(); - }; - - parser.ontext = function(text) { - if (currentElement !== rootElement) { - currentElement.children.push(nodes.text(text)); - } - }; - - parser.onend = function() { - if (!finished) { - finished = true; - deferred.resolve(rootElement.children[0]); - } - }; - - parser.onerror = function(error) { - if (!finished) { - finished = true; - deferred.reject(error); - } - }; - - parser.write(xmlString).close(); - - return deferred.promise; -} -function mapObject(input, valueFunc, keyFunc) { - return _.reduce(input, function(result, value, key) { - var mappedKey = keyFunc(value, key, input); - result[mappedKey] = valueFunc(value, key, input); - return result; - }, {}); + return promises.resolve(convertNode(document.documentElement)); } diff --git a/lib/xml/xmldom.js b/lib/xml/xmldom.js new file mode 100644 index 0000000..752c353 --- /dev/null +++ b/lib/xml/xmldom.js @@ -0,0 +1,23 @@ +var xmldom = require("@xmldom/xmldom"); +var dom = require("@xmldom/xmldom/lib/dom"); + +function parseFromString(string) { + var error = null; + + var domParser = new xmldom.DOMParser({ + errorHandler: function(level, message) { + error = {level: level, message: message}; + } + }); + + var document = domParser.parseFromString(string); + + if (error === null) { + return document; + } else { + throw new Error(error.level + ": " + error.message); + } +} + +exports.parseFromString = parseFromString; +exports.Node = dom.Node; |
