Skip to content

Commit

Permalink
Added xsd validation to Document
Browse files Browse the repository at this point in the history
Removed libxml/parser.h include

Removed commented line from xml_document.cc
Document.validate now returns a boolean value instead of int
  • Loading branch information
dordille committed Apr 17, 2012
1 parent 7ef1d33 commit b92fbde
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 0 deletions.
5 changes: 5 additions & 0 deletions lib/document.js
Expand Up @@ -68,6 +68,11 @@ Document.prototype.encoding = function(encoding) {
return this._encoding(encoding);
}

/// @return whether the XmlDocument is valid
Document.prototype.validate = function(xsd) {
return this._validate(xsd);
}

module.exports = Document;

/// parse a string into a html document
Expand Down
39 changes: 39 additions & 0 deletions src/xml_document.cc
Expand Up @@ -3,6 +3,7 @@
#include <node.h>

#include <libxml/HTMLparser.h>
#include <libxml/xmlschemas.h>

#include "xml_document.h"
#include "xml_element.h"
Expand Down Expand Up @@ -196,6 +197,40 @@ XmlDocument::FromXmlString(const v8::Arguments& args)
return scope.Close(doc_handle);
}

v8::Handle<v8::Value>
XmlDocument::Validate(const v8::Arguments& args)
{
v8::HandleScope scope;

v8::Local<v8::Array> errors = v8::Array::New();
xmlResetLastError();
xmlSetStructuredErrorFunc(reinterpret_cast<void *>(*errors),
XmlSyntaxError::PushToArray);

XmlDocument* document = ObjectWrap::Unwrap<XmlDocument>(args.Holder());
XmlDocument* documentSchema = ObjectWrap::Unwrap<XmlDocument>(args[0]->ToObject());

xmlSchemaParserCtxtPtr parser_ctxt = xmlSchemaNewDocParserCtxt(documentSchema->xml_obj);
if (parser_ctxt == NULL) {
return v8::ThrowException(v8::Exception::Error(
v8::String::New("Could not create context for schema parser")));
}
xmlSchemaPtr schema = xmlSchemaParse(parser_ctxt);
if (schema == NULL) {
return v8::ThrowException(v8::Exception::Error(
v8::String::New("Invalid XSD schema")));
}
xmlSchemaValidCtxtPtr valid_ctxt = xmlSchemaNewValidCtxt(schema);
if (valid_ctxt == NULL) {
return v8::ThrowException(v8::Exception::Error(
v8::String::New("Unable to create a validation context for the schema")));
}
bool valid = xmlSchemaValidateDoc(valid_ctxt, document->xml_obj) == 0;

return scope.Close(v8::Boolean::New(valid));
}


/// this is a blank object with prototype methods
/// not exposed to the user and not called from js
v8::Handle<v8::Value>
Expand Down Expand Up @@ -252,6 +287,10 @@ XmlDocument::Initialize(v8::Handle<v8::Object> target)
"_toString",
XmlDocument::ToString);

NODE_SET_PROTOTYPE_METHOD(constructor_template,
"_validate",
XmlDocument::Validate);

NODE_SET_METHOD(target, "fromXmlString", XmlDocument::FromXmlString);
NODE_SET_METHOD(target, "fromHtmlString", XmlDocument::FromHtmlString);

Expand Down
1 change: 1 addition & 0 deletions src/xml_document.h
Expand Up @@ -50,6 +50,7 @@ class XmlDocument : public node::ObjectWrap {
static v8::Handle<v8::Value> Doc(const v8::Arguments& args);
static v8::Handle<v8::Value> Errors(const v8::Arguments& args);
static v8::Handle<v8::Value> ToString(const v8::Arguments& args);
static v8::Handle<v8::Value> Validate(const v8::Arguments& args);
};

} // namespace libxmljs
Expand Down
15 changes: 15 additions & 0 deletions test/document.js
Expand Up @@ -138,3 +138,18 @@ module.exports.cloned_node = function(assert) {
assert.equal(doc1_string, doc2.toString()); //doc2 should be the same as doc1 str
assert.done();
};

module.exports.validate = function(assert) {
var xsd = '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"><xs:element name="comment" type="xs:string"/></xs:schema>';
var xml_valid = '<?xml version="1.0"?><comment>A comment</comment>';
var xml_invalid = '<?xml version="1.0"?><commentt>A comment</commentt>';

var xsdDoc = libxml.parseXmlString(xsd);
var xmlDocValid = libxml.parseXmlString(xml_valid);
var xmlDocInvalid = libxml.parseXmlString(xml_invalid);

assert.equal(xmlDocValid.validate(xsdDoc), true);
assert.equal(xmlDocInvalid.validate(xsdDoc), false);

assert.done();
}

0 comments on commit b92fbde

Please sign in to comment.