albanm/node-libxml-xsd

View on GitHub
index.js

Summary

Maintainability
A
1 hr
Test Coverage
/**
 * Node.js bindings for XSD validation from libxml
 * @module libxml-xsd
 */

var fs = require('fs');
var libxmljs = require('libxmljs-mt');
var binding = require('bindings')('node-libxml-xsd');

/**
 * The libxmljs module. Prevents the need for a user's code to require it a second time. Also prevent weird bugs.
 */
exports.libxmljs = libxmljs;

/**
 * A compiled schema. Do not call this constructor, instead use parse or parseFile.
 *
 * store both the source document and the parsed schema
 * if we don't store the schema doc it will be deleted by garbage collector and it will result in segfaults.
 *
 * @constructor
 * @param {Document} schemaDoc - XML document source of the schema
 * @param {Document} schemaObj - Simple wrapper of a XSD schema
 */
var Schema = function(schemaDoc, schemaObj){
    this.schemaDoc = schemaDoc;
    this.schemaObj = schemaObj;
};

/**
 * Parse a XSD schema
 *
 * If no callback is given the function will run synchronously and return the result or throw an error.
 *
 * @param {string|Document} source - The content of the schema as a string or a [libxmljs document]{@link https://github.com/polotek/libxmljs/wiki/Document}
 * @param {parseCallback} [callback] - The callback that handles the response. Expects err and Schema object.
 * @return {Schema} Only if no callback is given.
 */
exports.parse = function(source, callback) {
    // schema can be given as a string or a pre-parsed xml document
    if (typeof source === 'string') {
        try {
            source = libxmljs.parseXml(source);
        } catch (err) {
            if (callback) return callback(err);
            throw err;
        }
    }

    if (callback) {
        binding.schemaAsync(source, function(err, schema){
            if (err) return callback(err);
            callback(null, new Schema(source, schema));
        });
    } else {
        return new Schema(source, binding.schemaSync(source));
    }
};
/**
 * Callback to the parse function
 * @callback parseCallback
 * @param {error} [err]
 * @param {Schema} [schema]
 */

/**
 * Parse a XSD schema
 *
 * @param {stringPath} sourcePath - The path of the file
 * @param {parseFileCallback} callback - The callback that handles the response. Expects err and Schema object.
 */
exports.parseFile = function(sourcePath, callback) {
    fs.readFile(sourcePath, 'utf8', function(err, data){
        if (err) return callback(err);
        exports.parse(data, callback);
    });
};
/**
 * Callback to the parseFile function
 * @callback parseFileCallback
 * @param {error} [err]
 * @param {Schema} [schema]
 */

/**
 * Validate a XML document over a schema
 *
 * If no callback is given the function will run synchronously and return the result or throw an error.
 *
 * @param {string|Document} source - The XML content to validate with the schema, to be given as a string or a [libxmljs document]{@link https://github.com/polotek/libxmljs/wiki/Document}
 * @param {Schema~validateCallback} [callback] - The callback that handles the response. Expects err and an array of validation errors, null if none.
 * @return {string|Document} Only if no callback is given. An array of validation errors, null if none.
 */
Schema.prototype.validate = function(source, callback) {

    // xml can be given as a string or a pre-parsed xml document
    var outputString = false;
    if (typeof source === 'string') {
        try {
            source = libxmljs.parseXml(source);
        } catch (err) {
            if (callback) return callback(err);
            throw err;
        }
        outputString = true;
    }

    if (callback) {
        binding.validateAsync(this.schemaObj, source, function(err, validationErrors){
            if (err) return callback(err);
            return callback(null, validationErrors.length > 0 ? validationErrors : null);
        });
    } else {
        var validationErrors = binding.validateSync(this.schemaObj, source);
        return validationErrors.length > 0 ? validationErrors : null;
    }
};
/**
 * Callback to the Schema.validate function
 * @callback Schema~validateCallback
 * @param {error} [err] - Error when attempting to validate (not a validation error).
 * @param {array} [validationErrors] - A array of errors from validating the schema, null if none.
 */

/**
 * Apply a schema to a XML file
 *
 * @param {string} sourcePath - The path of the file to read
 * @param {Schema~validateFileCallback} callback The callback that handles the response. Expects err and an array of validation errors null if none.
 */
Schema.prototype.validateFile = function(sourcePath, callback) {
    var that = this;
    fs.readFile(sourcePath, 'utf8', function(err, data){
        if (err) return callback(err);
        that.validate(data, callback);
    });
};
/**
 * Callback to the Schema.validateFile function
 * @callback Schema~validateFileCallback
 * @param {error} [err] - Error when attempting to validate (not a validation error).
 * @param {array} [validationErrors] - A array of errors from validating the schema, null if none.
 */