diff --git a/Cakefile b/Cakefile new file mode 100644 index 0000000..db1cee0 --- /dev/null +++ b/Cakefile @@ -0,0 +1,8 @@ +{spawn} = require 'child_process' +fs = require 'fs' + +task 'build', 'coffee -> js', -> + files = (file for file in fs.readdirSync '.' when file.match(/\.coffee$/)) + proc = spawn 'coffee', ['-c'].concat files + proc.stderr.on 'data', (buffer) -> console.log buffer.toString() + proc.on 'exit', (status) -> process.exit(1) if status != 0 diff --git a/README.md b/README.md new file mode 100644 index 0000000..34842ac --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +This module converts streams of XML to streams of JS objects. Unlike other +SAX modules, it doesn't give you every tag and text node seperately, but lets you +specify tag names you want to filter for. When this module encounters a tag with +that name, its content will be collected until the closing tag was reached, and +then you will receive the tag with all its attributes and children in one +object. + +Compiling +========= +To compile the `.coffee` files to Javascript, use `cake build`. You will need +[Coffeescript](http://coffeescript.org/) for that. diff --git a/index.coffee b/index.coffee new file mode 100644 index 0000000..181baa4 --- /dev/null +++ b/index.coffee @@ -0,0 +1,26 @@ +sax = require 'sax' + +last = (array) -> array[array.length-1] + +exports.createParser = (cbError, cbFinished, wantedNodes, strict) -> + interestingStack = [] + element = null + parser = sax.parser strict + parser.onerror = cbError + parser.onend = cbFinished + parser.onopentag = ({name, attributes}) -> + console.log " opening #{name}" + if wantedNodes[name]? or element? + parent = element + element = {parent, name, attributes, children: []} + parent?.children.push element + if wantedNodes[name]? + interestingStack.push name + parser.onclosetag = (name) -> + if name is last interestingStack + interestingStack.pop() + wantedNodes[name] element + element = element?.parent + parser.ontext = (text) -> + element?.children.push text + parser diff --git a/index.js b/index.js new file mode 100644 index 0000000..eefa487 --- /dev/null +++ b/index.js @@ -0,0 +1,46 @@ +(function() { + var last, sax; + sax = require('sax'); + last = function(array) { + return array[array.length - 1]; + }; + exports.createParser = function(cbError, cbFinished, wantedNodes, strict) { + var element, interestingStack, parser; + interestingStack = []; + element = null; + parser = sax.parser(strict); + parser.onerror = cbError; + parser.onend = cbFinished; + parser.onopentag = function(_arg) { + var attributes, name, parent; + name = _arg.name, attributes = _arg.attributes; + console.log(" opening " + name); + if ((wantedNodes[name] != null) || (element != null)) { + parent = element; + element = { + parent: parent, + name: name, + attributes: attributes, + children: [] + }; + if (parent != null) { + parent.children.push(element); + } + } + if (wantedNodes[name] != null) { + return interestingStack.push(name); + } + }; + parser.onclosetag = function(name) { + if (name === last(interestingStack)) { + interestingStack.pop(); + wantedNodes[name](element); + } + return element = element != null ? element.parent : void 0; + }; + parser.ontext = function(text) { + return element != null ? element.children.push(text) : void 0; + }; + return parser; + }; +}).call(this); diff --git a/package.json b/package.json new file mode 100644 index 0000000..4bcf0c8 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ "name": "halfstreamxml" +, "version": "0.1.0" +, "description": "converts a stream of XML to a stream of objects" +, "keywords": + [ "XML" + , "stream" + , "SAX" + ] +, "homepage": "http://github.com/thejh/node-halfstreamxml" +, "author": "Jann Horn" +, "main": "FIXME" +, "repository": + { "type": "git" + , "url": "http://github.com/thejh/node-halfstreamxml.git" + } +, "dependencies": + { "sax": "0.1.2" + } +, "files": + { "package.json" + , "index.js" + } +} diff --git a/test.coffee b/test.coffee new file mode 100644 index 0000000..296f193 --- /dev/null +++ b/test.coffee @@ -0,0 +1,10 @@ +halfstreamxml = require './index' +onerror = (e) -> + console.error "ERROR: #{e}" +onfinish = -> + console.log "DONE" +wantednodes = + PERSON: (person) -> + console.log "received person: #{JSON.stringify person, ['name', 'attributes', 'age', 'children']}" +parser = halfstreamxml.createParser onerror, onfinish, wantednodes, false +parser.write('BarfooFoo Bar').close() diff --git a/test.js b/test.js new file mode 100644 index 0000000..320feea --- /dev/null +++ b/test.js @@ -0,0 +1,17 @@ +(function() { + var halfstreamxml, onerror, onfinish, parser, wantednodes; + halfstreamxml = require('./index'); + onerror = function(e) { + return console.error("ERROR: " + e); + }; + onfinish = function() { + return console.log("DONE"); + }; + wantednodes = { + PERSON: function(person) { + return console.log("received person: " + (JSON.stringify(person, ['name', 'attributes', 'age', 'children']))); + } + }; + parser = halfstreamxml.createParser(onerror, onfinish, wantednodes, false); + parser.write('BarfooFoo Bar').close(); +}).call(this);