From 9ff57bb770e0296bb2f5b7a41711c53954eb8c4e Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 16 Aug 2015 14:21:25 +0100 Subject: Split xmlreader into nodes and reader modules --- lib/xml/reader.js | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 lib/xml/reader.js (limited to 'lib/xml/reader.js') diff --git a/lib/xml/reader.js b/lib/xml/reader.js new file mode 100644 index 0000000..ab175f2 --- /dev/null +++ b/lib/xml/reader.js @@ -0,0 +1,87 @@ +var promises = require("../promises"); +var sax = require("sax"); +var _ = require("underscore"); + +var Element = require("./nodes").Element; + +exports.readString = readString; + +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]; + var prefix; + if (mappedPrefix) { + prefix = mappedPrefix; + } else { + prefix = "{" + node.uri + "}"; + } + return prefix + ":" + node.local; + } else { + return node.local; + } + } + + parser.onclosetag = function(node) { + currentElement = stack.pop(); + }; + + parser.ontext = function(text) { + if (currentElement !== rootElement) { + currentElement.children.push({ + type: "text", + value: text + }); + } + }; + + parser.onend = function() { + if (!finished) { + finished = true; + deferred.resolve({ + root: 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.call(null, value, key, input); + result[mappedKey] = valueFunc.call(null, value, key, input); + return result; + }, {}); +} -- cgit v1.2.3