-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First significant push. Most functionality ok.
- Loading branch information
Showing
20 changed files
with
662 additions
and
178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,104 @@ | ||
node-libxslt | ||
============ | ||
|
||
Node.js bindings for libxslt compatible with libxmljs | ||
Node.js bindings for [libxslt](http://xmlsoft.org/libxslt/) compatible with [libxmljs](https://github.com/polotek/libxmljs/issues/226). | ||
|
||
**Not working yet. Come back later.** | ||
Installation | ||
------------ | ||
|
||
npm install node-libxslt | ||
|
||
Basic usage | ||
----------- | ||
|
||
```js | ||
var lixslt = require('node-libxslt'); | ||
|
||
var stylesheet = libxslt.stylesheet(stylesheetString); | ||
|
||
var params = { | ||
MyParam: 'my value' | ||
}; | ||
|
||
// 'params' parameter is optional | ||
stylesheet.apply(documentString, params, function(err, result){ | ||
// err contains any error from parsing the document or applying the the stylesheet | ||
// result is a string containing the result of the transformation | ||
}); | ||
|
||
``` | ||
|
||
Libxmljs integration | ||
-------------------- | ||
|
||
Node-libxslt depends on [libxmljs](https://github.com/polotek/libxmljs/issues/226) in the same way that [libxslt](http://xmlsoft.org/libxslt/) depends on [libxml](http://xmlsoft.org/). This dependancy makes possible to bundle and to load in memory libxml only once for users of both libraries. | ||
|
||
It is possible to work with libxmljs documents instead of strings: | ||
|
||
```js | ||
var lixslt = require('node-libxslt'); | ||
var libxmljs = require('libxmljs'); | ||
|
||
var stylesheetObj = libxmljs.parseXml(stylesheetString); | ||
var stylesheet = libxslt.stylesheet(stylesheetObj); | ||
|
||
var document = libxmljs.parseXml(documentString); | ||
stylesheet.apply(document, function(err, result){ | ||
// result is now a libxmljs document containing the result of the transformation | ||
}); | ||
|
||
``` | ||
|
||
This is only useful if you already needed to parse a document before applying the stylesheet for previous manipulations. | ||
Or if you wish to be returned a document instead of a string for ulterior manipulations. | ||
In these cases you will prevent extraneous parsings and serializations. | ||
|
||
Sync or async | ||
------------- | ||
|
||
The same *apply()* function can be used in synchronous mode simply by removing the callback parameter. | ||
In this case if a parsing error occurs it will be thrown. | ||
|
||
```js | ||
var lixslt = require('node-libxslt'); | ||
|
||
var stylesheet = libxslt.stylesheet(stylesheetString); | ||
|
||
var result = stylesheet.apply(documentString); | ||
|
||
``` | ||
|
||
The asynchronous function uses the [libuv work queue](http://nikhilm.github.io/uvbook/threads.html#libuv-work-queue) | ||
to provide parallelized computation in node.js worker threads. This makes it non-blocking for the main event loop of node.js. | ||
|
||
Note that libxmljs parsing doesn't use the work queue, so only a part of the process is actually parallelized. | ||
|
||
A small benchmark is available in the project. It has a very limited scope, it uses always the same small transformation a few thousand times. | ||
To run it use: | ||
|
||
node benchmark.js | ||
|
||
This is an example of its results with an intel core i5 3.1GHz: | ||
|
||
``` | ||
10000 synchronous apply from parsed doc in 331ms = 30211/s | ||
10000 asynchronous apply in series from parsed doc in 538ms = 18587/s | ||
10000 asynchronous apply in parallel from parsed doc in 217ms = 46083/s | ||
``` | ||
|
||
Observations: | ||
- it's pretty fast ! | ||
- asynchronous is slower when running in series. | ||
- asynchronous can become faster when concurrency is high. | ||
|
||
Conclusion: | ||
- use asynchronous by default it will be kinder to your main event loop and is pretty fast anyway. | ||
- use synchronous only if you really want the highest performance and expect low concurrency. | ||
- of course you can also use synchronous simply to reduce code depth. If you don't expect a huge load it will be ok. | ||
|
||
OS compatibility | ||
---------------- | ||
|
||
Right now only 64bits linux is supported. The support of other environments is a work in progress. | ||
|
||
For windows user: node-libxslt depends on [node-gyp](https://github.com/TooTallNate/node-gyp), you will have to go through its installation. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
var fs = require('fs'); | ||
var async = require('async'); | ||
var libxmljs = require("libxmljs"); | ||
var libxslt = require('./index'); | ||
|
||
var stylesheetStr = fs.readFileSync('./test/resources/cd.xsl', 'utf8'); | ||
var stylesheetObj = libxmljs.parseXml(stylesheetStr); | ||
var stylesheet = libxslt.stylesheet(stylesheetObj); | ||
var docStr = fs.readFileSync('./test/resources/cd.xml', 'utf8'); | ||
var docObj = libxmljs.parseXml(docStr); | ||
|
||
var bench = function(name, iterations, f) { | ||
return function(callback) { | ||
var before = Date.now(); | ||
f(iterations, function() { | ||
var duration = (Date.now() - before); | ||
console.log('%d %s in %dms = %d/s', iterations, name, duration, Math.round(iterations / (duration / 1000))); | ||
if (callback) callback(); | ||
}); | ||
}; | ||
}; | ||
|
||
var stylesheetParsingStr = function(iterations, callback) { | ||
for (var i = 0; i < iterations; i++) { | ||
libxslt.stylesheet(stylesheetStr); | ||
} | ||
callback(); | ||
}; | ||
|
||
var stylesheetParsingObj = function(iterations, callback) { | ||
for (var i = 0; i < iterations; i++) { | ||
libxslt.stylesheet(stylesheetObj); | ||
} | ||
callback(); | ||
}; | ||
|
||
var applySyncStr = function(iterations, callback) { | ||
for (var i = 0; i < iterations; i++) { | ||
stylesheet.apply(docStr); | ||
} | ||
callback(); | ||
}; | ||
|
||
var applySyncObj = function(iterations, callback) { | ||
for (var i = 0; i < iterations; i++) { | ||
stylesheet.apply(docObj); | ||
} | ||
callback(); | ||
}; | ||
|
||
var applyAsyncSeriesStr = function(iterations, callback) { | ||
var i = 0; | ||
async.eachSeries(new Array(iterations), function(u, callbackEach) { | ||
stylesheet.apply(docStr, function(err, result) { | ||
i++; | ||
callbackEach(err); | ||
}); | ||
}, callback); | ||
}; | ||
|
||
var applyAsyncSeriesObj = function(iterations, callback) { | ||
var i = 0; | ||
async.eachSeries(new Array(iterations), function(u, callbackEach) { | ||
stylesheet.apply(docObj, function(err, result) { | ||
i++; | ||
callbackEach(err); | ||
}); | ||
}, callback); | ||
}; | ||
|
||
var applyAsyncParallelStr = function(iterations, callback) { | ||
var i = 0; | ||
async.eachLimit(new Array(iterations), 10, function(u, callbackEach) { | ||
stylesheet.apply(docStr, function(err, result) { | ||
i++; | ||
callbackEach(err); | ||
}); | ||
}, callback); | ||
}; | ||
|
||
var applyAsyncParallelObj = function(iterations, callback) { | ||
var i = 0; | ||
async.eachLimit(new Array(iterations), 10, function(u, callbackEach) { | ||
stylesheet.apply(docObj, function(err, result) { | ||
i++; | ||
callbackEach(err); | ||
}); | ||
}, callback); | ||
}; | ||
|
||
var iterations = 10000; | ||
async.series([ | ||
//bench('stylesheet parsing from string\t\t\t', iterations, stylesheetParsingStr), | ||
//bench('stylesheet parsing from parsed doc\t\t\t', iterations, stylesheetParsingObj), | ||
//bench('synchronous apply from string\t\t\t', iterations, applySyncStr), | ||
bench('synchronous apply from parsed doc\t\t\t', iterations, applySyncObj), | ||
//bench('asynchronous apply in series from string\t\t', iterations, applyAsyncSeriesStr), | ||
bench('asynchronous apply in series from parsed doc\t', iterations, applyAsyncSeriesObj), | ||
//bench('asynchronous apply in parallel from string\t', iterations, applyAsyncParallelStr), | ||
bench('asynchronous apply in parallel from parsed doc\t', iterations, applyAsyncParallelObj) | ||
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# imitation of this https://github.com/TooTallNate/node-vorbis/blob/master/common.gypi | ||
{ | ||
'variables': { | ||
'node_xmljs': '<!(node -p -e "require(\'path\').dirname(require.resolve(\'libxmljs\'))")', | ||
'xmljs_include_dirs': [ | ||
'<(node_xmljs)/src/', | ||
'<(node_xmljs)/vendor/libxml/include' | ||
], | ||
'conditions': [ | ||
['OS=="win"', { | ||
'xmljs_libraries': [ | ||
'<(node_xmljs)/build/$(Configuration)/xmljs.lib' | ||
], | ||
}, { | ||
'xmljs_libraries': [ | ||
'<(node_xmljs)/build/$(BUILDTYPE)/xmljs.node', | ||
'-Wl,-rpath,<(node_xmljs)/build/$(BUILDTYPE)' | ||
], | ||
}], | ||
], | ||
}, | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.