Permalink
Browse files

jslint and Travis CI stuff.

  • Loading branch information...
1 parent 0b72d8d commit 431d985b0da0af132ce5279e6a1ecab92f1b4964 @SaltwaterC committed Jan 30, 2013
View
@@ -0,0 +1,10 @@
+before_install:
+ - sudo apt-get update -qq
+ - sudo apt-get install -qq bc
+ - npm -g install jslint
+language: node_js
+node_js:
+ - 0.4
+ - 0.6
+ - 0.8
+ - 0.9
View
@@ -1,5 +1,6 @@
## v0.3.11
* Adds more CDATA support [#13](https://github.com/SaltwaterC/libxml-to-js/issues/13). Thanking XApp-Studio for the patch.
+ * jslint compliant.
## v0.3.10
* Fixes a couple of global variable leaks [#10](https://github.com/SaltwaterC/libxml-to-js/pull/10).
View
@@ -1,6 +1,6 @@
-## About
+## About [![build status](https://secure.travis-ci.org/SaltwaterC/libxml-to-js.png?branch=master)](http://travis-ci.org/SaltwaterC/libxml-to-js) ![still maintained](http://stillmaintained.com/SaltwaterC/libxml-to-js.png)
-This is a XML to JavaScript object parser. It uses the [libxmljs](https://github.com/polotek/libxmljs) module for the actual XML parsing. It aims to be an easy [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js) replacement, but it doesn't follow the xml2js API. I used xml2js for my own needs, but the error reporting of the underlying SAX parser is quite broken. This is how libxml-to-js saw the day light.
+This is a XML to JavaScript object parser. It uses the [libxmljs](https://github.com/polotek/libxmljs) module for the actual XML parsing. It aims to be an easy [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js) v1 replacement, but it doesn't follow the xml2js API.
libxml-to-js uses the string parser method of libxmljs. Basically a modified version of the algorithm from [here](http://mscdex.net/code-snippets/) in order to fit the formal specifications of xml2js output.
View
@@ -1,164 +1,166 @@
+'use strict';
+
+var lodash = require('lodash');
var libxmljs = require('libxmljs');
/**
- * Simple object merger
+ * Wraps the lodash object merger
*
* @param obj1
* @param obj2
* @returns obj3
*/
var merge = function (obj1, obj2) {
var obj3 = {};
-
- for (var attrname in obj1) {
- obj3[attrname] = obj1[attrname];
- }
-
- for (var attrname in obj2) {
- obj3[attrname] = obj2[attrname];
- }
-
+ lodash.merge(obj3, obj1, obj2);
return obj3;
};
/**
- * Checks if an object is empty
- * @param obj
- * @returns bool
- */
-var isEmpty = function (obj) {
- for (var prop in obj) {
- if(obj.hasOwnProperty(prop)) {
- return false;
- }
- }
- return true;
-}
-
-/**
* The core function of this module
- * @param obj
- * @param recurse
- * @param namespaces
- * @returns parsedObj
+ *
+ * @param {Object} obj
+ * @param {Boolean} recurse
+ * @param {Object} namespaces
+ * @returns {Object} parsedObj
*/
var libxml2js = function (obj, recurse, namespaces) {
- if (namespaces == undefined) {
+ var i, j, k, atlen, chlen, chtlen, val, old, recValue;
+
+ if (namespaces === undefined) {
namespaces = {};
}
-
+
if ( ! recurse) {
obj = obj.root();
if (obj.namespace()) {
- namespaces['xmlns'] = obj.namespace().href();
+ namespaces.xmlns = obj.namespace().href();
}
}
var jsobj = {}, children = obj.childNodes(), attributes = obj.attrs();
if (attributes.length > 0) {
jsobj['@'] = {};
- for (var i = 0, atlen = attributes.length; i < atlen; i++) {
+ for (i = 0, atlen = attributes.length; i < atlen; i++) {
jsobj['@'][attributes[i].name()] = attributes[i].value();
}
}
- for (var i = 0, chlen = children.length; i < chlen; i++) {
+ for (i = 0, chlen = children.length; i < chlen; i++) {
// <"text" kludge>
- if (children[i].name() == 'text' && children[i].type() == 'text') {
+ if (children[i].name() === 'text' && children[i].type() === 'text') {
jsobj['#'] = children[i].text().trim();
+
if (jsobj['#'].match(/^\s*$/)) {
delete(jsobj['#']);
}
- for (var j = 0, chtlen = children[i].childNodes().length; j < chtlen; j++) {
- if (children[i].child(j).name() == 'text') {
+
+ for (j = 0, chtlen = children[i].childNodes().length; j < chtlen; j++) {
+ if (children[i].child(j).name() === 'text') {
var text = {}, textattrs = children[i].child(j).attrs();
text['#'] = children[i].child(j).text();
if (textattrs.length > 0) {
text['@'] = {};
}
- for (var k = 0, atlen = textattrs.length; k < atlen; i++) {
+ for (k = 0, atlen = textattrs.length; k < atlen; i++) {
text['@'][textattrs[k].name()] = textattrs[k].value();
}
- jsobj['text'] = text;
+
+ jsobj.text = text;
break; // only allow one "<text></text>" element for now
}
}
- continue;
- } else if (children[i].type()=='cdata') {
- var val = children[i].toString().trim();
- val = val.replace(/^\<\!\[CDATA\[/, '').replace(/\]\]\>$/, '');
+ } else if (children[i].type() === 'cdata') {
+ val = children[i].toString().trim();
+ val = val.replace(/^<\!\[CDATA\[/, '').replace(/\]\]\>$/, '');
jsobj['#']=val;
- }
-
- // </"text" kludge>
- var ns = '';
- var namespace = children[i].namespace();
- if (namespace && namespace.prefix() != null) {
- ns = namespace.prefix() + ':';
- namespaces[namespace.prefix()] = namespace.href();
- }
- var key = ns + children[i].name();
-
- if (typeof jsobj[key] == 'undefined') {
- if (children[i].childNodes().length == 1 && children[i].attrs().length == 0 && (children[i].childNodes()[0].type() == 'text' || children[i].childNodes()[0].type() == 'cdata')) {
- var val = children[i].childNodes()[0].toString().trim();
- if (children[i].childNodes()[0].type() == 'cdata') {
- val = val.replace(/^\<\!\[CDATA\[/, '').replace(/\]\]\>$/, '');
+ } else {
+ // </"text" kludge>
+ var ns = '';
+ var namespace = children[i].namespace();
+
+ if (namespace && namespace.prefix() !== null) {
+ ns = namespace.prefix() + ':';
+ namespaces[namespace.prefix()] = namespace.href();
+ }
+ var key = ns + children[i].name();
+
+ if (typeof jsobj[key] === 'undefined') {
+ if (children[i].childNodes().length === 1 && children[i].attrs().length === 0 && (children[i].childNodes()[0].type() === 'text' || children[i].childNodes()[0].type() === 'cdata')) {
+ val = children[i].childNodes()[0].toString().trim();
+
+ if (children[i].childNodes()[0].type() === 'cdata') {
+ val = val.replace(/^<\!\[CDATA\[/, '').replace(/\]\]\>$/, '');
+ }
+
+ jsobj[key] = val;
+ } else {
+ if (children[i].name() !== undefined) {
+ recValue = libxml2js(children[i], true, namespaces);
+ jsobj[key] = recValue.jsobj;
+ merge(namespaces, recValue.namespaces);
+ }
}
- jsobj[key] = val;
} else {
- if (children[i].name() !== undefined) {
- var recValue = libxml2js(children[i], true, namespaces);
- jsobj[key] = recValue.jsobj;
- merge(namespaces, recValue.namespaces);
+ if (typeof jsobj[key] === 'string') {
+ old = jsobj[key];
+ jsobj[key] = [];
+ jsobj[key].push({'#': old});
+ } else if (typeof jsobj[key] === 'object' && jsobj[key].push === undefined) {
+ old = jsobj[key];
+ jsobj[key] = [];
+ jsobj[key].push(old);
}
- }
- } else {
- if (typeof jsobj[key] == 'string') {
- var old = jsobj[key];
- jsobj[key] = [];
- jsobj[key].push({'#': old});
- } else if (typeof jsobj[key] == 'object' && ! ('push' in jsobj[key])) {
- var old = jsobj[key];
- jsobj[key] = [];
- jsobj[key].push(old);
- }
- var recValue = libxml2js(children[i], true, namespaces);
- jsobj[key].push(recValue.jsobj);
- merge(namespaces, recValue.namespaces);
+
+ recValue = libxml2js(children[i], true, namespaces);
+ jsobj[key].push(recValue.jsobj);
+ merge(namespaces, recValue.namespaces);
+ }
}
}
if ( ! recurse) {
- if (namespaces && ! isEmpty(namespaces)) {
+ if (namespaces && ! lodash.isEmpty(namespaces)) {
if ( ! jsobj['@']) {
jsobj['@'] = {};
}
jsobj['@'].xmlns = namespaces;
}
+
return jsobj;
- } else {
- return {
- jsobj: jsobj,
- namespaces: namespaces
- }
}
+
+ return {
+ jsobj: jsobj,
+ namespaces: namespaces
+ };
};
+/**
+ * The module wrapper, with XPath support
+ *
+ * @param {String} xml
+ * @param {String} xpath
+ * @param {Function} callback
+ */
module.exports = function (xml, xpath, callback) {
if ( ! callback) {
callback = xpath;
xpath = null;
}
+
var xmlDocument, jsDocument, selected = [], xmlns = null, error, result;
+
try {
xmlDocument = libxmljs.parseXmlString(xml);
jsDocument = libxml2js(xmlDocument);
+
if (jsDocument['@'] && jsDocument['@'].xmlns) {
xmlns = jsDocument['@'].xmlns;
}
+
if ( !! xpath) {
xmlDocument.find(xpath, xmlns).forEach(function(item) {
selected.push(libxml2js(item, true).jsobj);
@@ -170,14 +172,17 @@ module.exports = function (xml, xpath, callback) {
} catch (err) {
var message = 'libxml error';
var code = 0;
+
if (err && err.message) {
message = err.message;
}
+
error = new Error(message);
if (err && err.code) {
error.code = err.code;
}
}
+
if ( ! error) {
callback(null, result);
} else {
View
@@ -4,7 +4,8 @@
"main": "./lib/libxml-to-js.js",
"description": "XML to JavaScript object parser based on libxmljs",
"dependencies": {
- "libxmljs": ">=0.5.x"
+ "libxmljs": ">=0.5.x",
+ "lodash": "*"
},
"engines": {
"node": ">=0.4.x"
View
@@ -1,15 +1,22 @@
+'use strict';
+
var parser = require('../');
var fs = require('fs');
var assert = require('assert');
-var callback = false;
-var callbackXPath = false;
+var common = require('./includes/common.js');
+
+var callbacks = {
+ parse: 0,
+ parseXpath: 0
+};
var xml = '<thing><real id="width">300</real><real id="height">200</real></thing>';
parser(xml, function (err, res) {
- callback = true;
+ callbacks.parse++;
+
assert.ifError(err);
assert.deepEqual({
"real": [{
@@ -28,7 +35,8 @@ parser(xml, function (err, res) {
});
parser(xml, '//thing/real', function (err, res) {
- callbackXPath = true;
+ callbacks.parseXpath++;
+
assert.ifError(err);
assert.deepEqual([
{
@@ -46,7 +54,4 @@ parser(xml, '//thing/real', function (err, res) {
res);
});
-process.on('exit', function () {
- assert.ok(callback);
- assert.ok(callbackXPath);
-});
+common.teardown(callbacks);
View
@@ -1,16 +1,21 @@
+'use strict';
+
var parser = require('../');
var fs = require('fs');
var assert = require('assert');
-var callback = false;
+var common = require('./includes/common.js');
+
+var callbacks = {
+ parse: 0
+};
parser('This is a broken XML file.', function (err, res) {
- callback = true;
+ callbacks.parse++;
+
assert.ok(err instanceof Error);
- assert.equal(err.code, 4);
+ assert.strictEqual(err.code, 4);
});
-process.on('exit', function () {
- assert.ok(callback);
-});
+common.teardown(callbacks);
Oops, something went wrong.

0 comments on commit 431d985

Please sign in to comment.