Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

libxml-to-js

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

libxml-to-js - npm Package Compare versions

Comparing version 0.3.10 to 0.3.11

.travis.yml

4

CHANGELOG.md

@@ -0,1 +1,5 @@

## 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

@@ -2,0 +6,0 @@ * Fixes a couple of global variable leaks [#10](https://github.com/SaltwaterC/libxml-to-js/pull/10).

169

lib/libxml-to-js.js

@@ -0,5 +1,8 @@

'use strict';
var lodash = require('lodash');
var libxmljs = require('libxmljs');
/**
* Simple object merger
* Wraps the lodash object merger
*

@@ -12,11 +15,3 @@ * @param obj1

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;

@@ -26,31 +21,20 @@ };

/**
* 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();
}

@@ -63,3 +47,3 @@ }

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();

@@ -69,11 +53,13 @@ }

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();

@@ -85,48 +71,56 @@ text['#'] = children[i].child(j).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;
}
// </"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 if (children[i].type() === 'cdata') {
val = children[i].toString().trim();
val = val.replace(/^<\!\[CDATA\[/, '').replace(/\]\]\>$/, '');
jsobj['#']=val;
} 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);
}
}

@@ -136,3 +130,3 @@ }

if ( ! recurse) {
if (namespaces && ! isEmpty(namespaces)) {
if (namespaces && ! lodash.isEmpty(namespaces)) {
if ( ! jsobj['@']) {

@@ -143,11 +137,19 @@ jsobj['@'] = {};

}
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) {

@@ -158,9 +160,13 @@ if ( ! callback) {

}
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) {

@@ -177,5 +183,7 @@ xmlDocument.find(xpath, xmlns).forEach(function(item) {

var code = 0;
if (err && err.message) {
message = err.message;
}
error = new Error(message);

@@ -186,2 +194,3 @@ if (err && err.code) {

}
if ( ! error) {

@@ -188,0 +197,0 @@ callback(null, result);

{
"name": "libxml-to-js",
"version": "0.3.10",
"version": "0.3.11",
"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": "*"
},

@@ -37,2 +38,6 @@ "engines": {

"url": "https://github.com/TokyoIncidents"
},
{
"name": "XApp-Studio",
"url": "https://github.com/XApp-Studio"
}

@@ -39,0 +44,0 @@ ],

@@ -1,4 +0,4 @@

## 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.

@@ -13,2 +13,4 @@ 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.

The installation of the underlying dependency, **libxmljs**, fails if you don't have gcc (or compatible compiler), the [libxml2](http://en.wikipedia.org/wiki/Libxml2) development headers, and the xml2-config script. Under various Linux distributions you may install the appropriate libxml2 development package: libxml2-dev (Debian, Ubuntu, etc), libxml2-devel (RHEL, CentOS, Fedora, etc).
## Usage mode

@@ -87,1 +89,2 @@

* @[TokyoIncidents](https://github.com/TokyoIncidents): fixes a couple of global variables leaks [#10](https://github.com/SaltwaterC/libxml-to-js/pull/10)
* @[XApp-Studio](https://github.com/XApp-Studio): more support for CDATA elements [#13](https://github.com/SaltwaterC/libxml-to-js/issues/13)

@@ -0,1 +1,3 @@

'use strict';
var parser = require('../');

@@ -6,9 +8,14 @@

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);

@@ -32,3 +39,4 @@ assert.deepEqual({

parser(xml, '//thing/real', function (err, res) {
callbackXPath = true;
callbacks.parseXpath++;
assert.ifError(err);

@@ -51,5 +59,2 @@ assert.deepEqual([

process.on('exit', function () {
assert.ok(callback);
assert.ok(callbackXPath);
});
common.teardown(callbacks);

@@ -0,1 +1,3 @@

'use strict';
var parser = require('../');

@@ -6,12 +8,15 @@

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);

@@ -0,1 +1,3 @@

'use strict';
var parser = require('../');

@@ -6,24 +8,29 @@

var callback = false;
var callbackXPath = false;
var common = require('./includes/common.js');
var xml = fs.readFileSync('data/ec2-describeimages.xml').toString();
var callbacks = {
parse: 0,
parseXpath: 0
};
parser(xml, function (err, res) {
callback = true;
fs.readFile('data/ec2-describeimages.xml', function (err, xml) {
assert.ifError(err);
assert.equal(res.imagesSet.item[0].imageId, 'ami-be3adfd7');
assert.equal(res.imagesSet.item[1].imageId, 'ami-be3adfd9');
parser(xml, function (err, res) {
callbacks.parse++;
assert.ifError(err);
assert.strictEqual(res.imagesSet.item[0].imageId, 'ami-be3adfd7');
assert.strictEqual(res.imagesSet.item[1].imageId, 'ami-be3adfd9');
});
parser(xml, '//xmlns:blockDeviceMapping', function (err, res) {
callbacks.parseXpath++;
assert.ifError(err);
assert.strictEqual(res.length, 2);
assert.strictEqual(res[0].item.deviceName, '/dev/sda');
});
});
parser(xml, '//xmlns:blockDeviceMapping', function (err, res) {
callbackXPath = true;
assert.ifError(err);
assert.strictEqual(res.length, 2);
assert.strictEqual(res[0].item.deviceName, '/dev/sda');
});
process.on('exit', function () {
assert.ok(callback);
assert.ok(callbackXPath);
});
common.teardown(callbacks);

@@ -0,1 +1,3 @@

'use strict';
var parser = require('../');

@@ -6,15 +8,25 @@

var callback = false;
var common = require('./includes/common.js');
parser(fs.readFileSync('data/ec2-describevolumes-large.xml').toString(), function (err, res) {
callback = true;
var callbacks = {
parse: 0
};
fs.readFile('data/ec2-describevolumes-large.xml', function (err, xml) {
assert.ifError(err);
for (var i in res.volumeSet.item) {
var volume = res.volumeSet.item[i];
assert.equal(volume.volumeId, 'vol-00000000');
}
parser(xml, function (err, res) {
var i;
callbacks.parse++;
assert.ifError(err);
for (i in res.volumeSet.item) {
if (res.volumeSet.item.hasOwnProperty(i)) {
var volume = res.volumeSet.item[i];
assert.strictEqual(volume.volumeId, 'vol-00000000');
}
}
});
});
process.on('exit', function () {
assert.ok(callback);
});
common.teardown(callbacks);

@@ -0,1 +1,3 @@

'use strict';
var parser = require('../');

@@ -6,19 +8,29 @@

var callback = false;
var common = require('./includes/common.js');
parser(fs.readFileSync('data/namespace.xml').toString(), function (err, res) {
callback = true;
assert.ifError(err);
assert.equal(res['@'].xmlns.atom, 'http://www.w3.org/2005/Atom');
for (var i in res['atom:link']) {
var atom = res['atom:link'][i];
assert.equal(atom['@'].rel, 'self');
assert.equal(atom['@'].type, 'application/rss+xml');
}
assert.equal(res['atom:link'][0]['@'].href, 'http://localhost/wordpress/?feed=rss');
assert.equal(res['atom:link'][1]['@'].href, 'http://localhost/wordpress/?feed=rss2');
var callbacks = {
parse: 0
};
fs.readFile('data/namespace.xml', function (err, xml) {
parser(xml, function (err, res) {
var i;
callbacks.parse++;
assert.ifError(err);
assert.strictEqual(res['@'].xmlns.atom, 'http://www.w3.org/2005/Atom');
for (i in res['atom:link']) {
if (res['atom:link'].hasOwnProperty(i)) {
var atom = res['atom:link'][i];
assert.strictEqual(atom['@'].rel, 'self');
assert.strictEqual(atom['@'].type, 'application/rss+xml');
}
}
assert.strictEqual(res['atom:link'][0]['@'].href, 'http://localhost/wordpress/?feed=rss');
assert.strictEqual(res['atom:link'][1]['@'].href, 'http://localhost/wordpress/?feed=rss2');
});
});
process.on('exit', function () {
assert.ok(callback);
});
common.teardown(callbacks);

@@ -0,1 +1,3 @@

'use strict';
var parser = require('../');

@@ -6,54 +8,58 @@

var callback = false;
var callbackXPath = false;
var common = require('./includes/common.js');
var xml = fs.readFileSync('data/text.xml').toString();
var callbacks = {
parse: 0,
parseXpath: 0
};
parser(xml, function (err, res) {
callback = true;
fs.readFile('data/text.xml', function (err, xml) {
assert.ifError(err);
assert.deepEqual({
'news': [{
parser(xml, function (err, res) {
callbacks.parse++;
assert.ifError(err);
assert.deepEqual({
'news': [{
"auteur": "Bizzard5",
"date": "17 Août 2008",
"text": {}
}, {
"auteur": "Little",
"date": "18 Août 2007",
"text": {
"test": "test"
}
}, {
"auteur": "Bizzard5",
"date": "17 Août 2008",
"text": "C'est un teste"
}, {
"auteur": "Little",
"date": "18 Août 2007",
"text": "Allo"
}, {
"auteur": "Little",
"date": "18 Août 2007",
"text": {
"text": "test"
}
}]
},
res);
});
parser(xml, '//nouvelle/news', function (err, res) {
callbacks.parseXpath++;
assert.ifError(err);
assert.deepEqual({
"auteur": "Bizzard5",
"date": "17 Août 2008",
"text": {}
}, {
"auteur": "Little",
"date": "18 Août 2007",
"text": {
"test": "test"
}
}, {
"auteur": "Bizzard5",
"date": "17 Août 2008",
"text": "C'est un teste"
}, {
"auteur": "Little",
"date": "18 Août 2007",
"text": "Allo"
}, {
"auteur": "Little",
"date": "18 Août 2007",
"text": {
"text": "test"
}
}]
},
res);
},
res[0]);
});
});
parser(xml, '//nouvelle/news', function (err, res) {
callbackXPath = true;
assert.ifError(err);
assert.deepEqual({
"auteur": "Bizzard5",
"date": "17 Août 2008",
"text": {}
},
res[0]);
});
process.on('exit', function () {
assert.ok(callback);
assert.ok(callbackXPath);
});
common.teardown(callbacks);

@@ -0,1 +1,3 @@

'use strict';
var parser = require('../');

@@ -6,28 +8,33 @@

var callback = false;
var callbackXPath = false;
var common = require('./includes/common.js');
var xml = fs.readFileSync('data/wordpress-rss2.xml').toString();
var callbacks = {
parse: 0,
parseXpath: 0
};
parser(xml, function (err, res) {
callback = true;
fs.readFile('data/wordpress-rss2.xml', function (err, xml) {
assert.ifError(err);
assert.equal(res['@'].version, '2.0');
assert.equal(res['@'].xmlns.atom, 'http://www.w3.org/2005/Atom');
assert.equal(res.channel.title, 'WordPress');
assert.equal(res.channel['atom:link']['@'].href, 'http://localhost/wordpress/?feed=rss2');
assert.equal(res.channel.item.title, 'Hello world!');
assert.equal(res.channel.item.category, 'Uncategorized'); // CDATA element
parser(xml, function (err, res) {
callbacks.parse++;
assert.ifError(err);
assert.strictEqual(res['@'].version, '2.0');
assert.strictEqual(res['@'].xmlns.atom, 'http://www.w3.org/2005/Atom');
assert.strictEqual(res.channel.title, 'WordPress');
assert.strictEqual(res.channel['atom:link']['@'].href, 'http://localhost/wordpress/?feed=rss2');
assert.strictEqual(res.channel.item.title, 'Hello world!');
assert.strictEqual(res.channel.item.category, 'Uncategorized'); // CDATA element
});
parser(xml, '//dc:creator', function (err, res) {
callbacks.parseXpath++;
assert.ifError(err);
assert.strictEqual(res.length, 1);
assert.strictEqual(res[0]['#'], 'admin');
});
});
parser(xml, '//dc:creator', function (err, res) {
callbackXPath = true;
assert.ifError(err);
assert.strictEqual(res.length, 1);
assert.strictEqual(res[0]['#'], 'admin');
});
process.on('exit', function () {
assert.ok(callback);
assert.ok(callbackXPath);
});
common.teardown(callbacks);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc