rng.js
Summary
This file defines objects for parsing and using RelaxNG schemas.
Version: 0.8
$Id: overview-summary-rng.js.html,v 1.12 2006/08/23 23:30:17 jameso Exp $
Author: James A. Overton
mozile.require("mozile.dom");
mozile.require("mozile.xml");
mozile.provide("mozile.rng.*");
mozile.rng = new Object();
mozile.rng.prototype = new mozile.Module;
mozile.rng.debug = false;
mozile.rng.getName = function() {
if(this._name) return this._name;
if(this._element.getAttribute("name")) {
var match = this._element.getAttribute("name").match(/^\s*(.+?)\s*$/);
if(match && match.length == 2) {
this._name = match[1];
return this._name;
}
}
throw Error("This RNG '"+ this.getType() +"' element must have a 'name' attribute.");
}
mozile.rng.getLocalName = function() {
if(this._localName) return this._localName;
var name = this.getName();
if(name.indexOf(":")) this._localName = name.substring(name.indexOf(":") + 1, name.length);
else this._localName = name;
return this._localName;
}
mozile.rng.getPrefix = function() {
if(this._prefix) return this._prefix;
var name = this.getName();
if(name.indexOf(":")) this._prefix = name.substring(0, name.indexOf(":"));
else this._prefix = null;
return this._prefix;
}
mozile.rng.checkType = function(types, type) {
if(typeof(types) == "string" && types == type) return true;
if(types.length) {
for(var i=0; i < types.length; i++) {
if(types[i] == type) return true;
}
}
return false;
}
mozile.rng.validateSequence = function(node, validation) {
if(!node) throw Error("mozile.rng.validateSequence() requires a node.");
if(!validation) throw Error("mozile.rng.validateSequence() requires an mozile.rng.Validation object.");
var RNGChildren = this.getChildNodes();
if(RNGChildren.length == 0) return validation;
for(var r=0; r < RNGChildren.length; r++) {
if(!validation.isValid) break;
validation = RNGChildren[r].validate(node, validation);
if(node.nodeType == mozile.dom.ELEMENT_NODE && validation.isEmpty)
validation.logError(this, node, "The parent element should be empty, but it contains child elements.");
if(validation.getCurrentElement()) {
node = validation.getCurrentElement();
if(mozile.dom.getNextSiblingElement(node)) node = mozile.dom.getNextSiblingElement(node);
}
}
return validation;
}
mozile.rng.validateMany = function(node, validation) {
if(!node) throw Error("mozile.rng.validateMany() requires a node.");
if(!validation) throw Error("mozile.rng.validateMany() requires an mozile.rng.Validation object.");
var result;
validation.count = 0;
while(true) {
result = validation.branch();
result = this._validateSequence(node, result);
if(result.isValid) {
validation.count++;
validation.merge(result);
if(result.getCurrentElement() && mozile.dom.getNextSiblingElement(result.getCurrentElement()) ) {
node = mozile.dom.getNextSiblingElement(result.getCurrentElement());
continue;
}
}
if(mozile.rng.debug) validation.append(result, true);
break;
}
return validation;
}
mozile.rng.validateInterleave = function(node, validation) {
if(!node) throw Error("mozile.rng.validateInterleave() requires a node.");
if(!validation) throw Error("mozile.rng.validateInterleave() requires an mozile.rng.Validation object.");
validation.logMessage(this, node, "Validating interleave...");
var RNGChildren = new Array();
for(var c=0; c < this.getChildNodes().length; c++) {
RNGChildren.push(this.getChildNodes()[c]);
}
var type;
var length = RNGChildren.length;
for(var i=0; i < length; i++) {
for(var r=0; r < RNGChildren.length; r++) {
var result = validation.branch();
result = RNGChildren[r].validate(node, result);
if(result.isValid) {
type = RNGChildren[r].getType();
if( (RNGChildren[r].getType() == "optional" ||
RNGChildren[r].getType() == "zeroOrMore") &&
!result.count )
continue;
validation.merge(result);
if(result.getCurrentElement() && mozile.dom.getNextSiblingElement(result.getCurrentElement()) ) {
node = mozile.dom.getNextSiblingElement(result.getCurrentElement());
}
RNGChildren.splice(r, 1);
break;
}
}
}
if(RNGChildren.length > 0) {
for(r=0; r < RNGChildren.length; r++) {
if(!validation.isValid) break;
type = RNGChildren[r].getType();
if(type != "optional" && type != "zeroOrMore")
validation.logError(this, node, "There were non-optional RNG children which did not match any elements.");
}
}
if(validation.isValid) validation.logMessage(this, node, "Interleave is valid.");
return validation;
}
mozile.rng.combine = function(target) {
var combineType;
var combineA = this._element.getAttribute("combine");
var combineB = target._element.getAttribute("combine");
if(combineA && combineB) {
if(combineA == combineB) combineType = combineA;
else throw Error("In order to combine RNG elements, their 'combine' attributes muct match. '"+ combineA +"' != '"+ combineB +"'");
}
else {
if(combineA) combineType = combineA;
else if(combineB) combineType = combineB;
else throw Error("In order to combine RNG elements, at least one must have a 'combine' attribute.");
}
if(combineType != "choice" && combineType != "interleave")
throw Error("RNG 'define' or 'start' elements can only have 'combine' attribute values of 'choice' or 'interleave', not '"+ combineType +"'.");
this._element.setAttribute("combine", combineType);
var combineObject;
if(this.getChildNodes().length == 1 &&
this.getChildNode(0).getType() == combineType) {
combineObject = this.getChildNode(0);
}
else {
var validation = new mozile.rng.Validation();
combineObject = this.getSchema().parseElement(mozile.dom.createElementNS(mozile.xml.ns.rng, combineType), validation, true);
this.appendChild(combineObject);
while(this.getChildNodes().length > 1) {
combineObject.appendChild(this.removeChild(this.getChildNode(0)));
}
}
var targetObject = target;
if(target.getChildNodes().length == 1 &&
target.getChildNode(0).getType() == combineType) {
targetObject = target.getChildNode(0);
}
while(targetObject.getChildNodes().length) {
combineObject.appendChild(targetObject.removeChild(targetObject.getChildNode(0)));
}
return this;
}
mozile.rng.Schema = function(target) {
this._documents = new Object();
this._types = new Object();
this._names = new Object();
this._root = null;
if(target) this.parse(target);
}
mozile.rng.Schema.prototype.constructor = mozile.rng.Schema;
mozile.rng.Schema.prototype.toString = function() { return "[object mozile.rng.Schema]" };
mozile.rng.Schema.prototype.getType = function() {
return "schema";
}
mozile.rng.Schema.prototype.parse = function(target) {
var element;
var filepath;
if(typeof(target) == "string") {
if(target.indexOf("<") > - 1) {
element = mozile.xml.parse(target).documentElement;
filepath = location.toString();
}
else {
var doc = this.load(target);
if(!doc) throw Error("Could not load schema '"+ target +"'.");
element = doc.documentElement;
filepath = target;
}
}
else if(target.nodeType) {
element = target;
filepath = location.toString();
}
else throw Error("Unknown target given in mozile.rng.Schema.parse().");
if(!this.filepath) this.filepath = filepath;
var validation = new mozile.rng.Validation();
validation.logMessage(this, null, "Starting to parse schema");
var result = this.parseElement(element, validation);
if(!result) {
validation.logError(this, null, "An invalid result was returned from the parsing operation: "+result);
return validation;
}
var root = result;
if(root.getType() == "element" || root.getType() == "grammar") {
this._root = root;
}
else {
validation.logError(this, null, "Schema has no root element.");
return validation;
}
var includes = this.getNodes("include");
if(!includes) return validation;
for(var i=0; i < includes.length; i++) {
validation = includes[i].include(validation);
}
return validation;
}
mozile.rng.Schema.prototype.parseElement = function(element, validation, omitValidation) {
var rngNode = this._createRNGNode(element, validation);
if(!rngNode) {
return null;
}
else validation.logMessage(rngNode, element, "Adding RNG '"+ rngNode.getType() +"' node.");
if(omitValidation != true) {
validation = rngNode.selfValidate(validation);
if(!validation.isValid) return {node: null, validation: validation};
}
if(element.hasChildNodes()) {
var child;
for(var c=0; c < element.childNodes.length; c++) {
child = this.parseElement(element.childNodes[c], validation);
if(child) rngNode.appendChild(child);
}
}
return rngNode;
}
mozile.rng.Schema.prototype._createRNGNode = function(element, validation) {
if(!element.nodeType || element.nodeType != mozile.dom.ELEMENT_NODE) return null;
if(element.namespaceURI != mozile.xml.ns.rng) return null;
var result;
var type = mozile.dom.getLocalName(element);
switch(type) {
case "grammar": result = new mozile.rng.Grammar(element, this); break;
case "start": result = new mozile.rng.Start(element, this); break;
case "element": result = new mozile.rng.Element(element, this); break;
case "attribute": result = new mozile.rng.Attribute(element, this); break;
case "empty": result = new mozile.rng.Empty(element, this); break;
case "text": result = new mozile.rng.Text(element, this); break;
case "group": result = new mozile.rng.Group(element, this); break;
case "optional": result = new mozile.rng.Optional(element, this); break;
case "oneOrMore": result = new mozile.rng.OneOrMore(element, this); break;
case "zeroOrMore": result = new mozile.rng.ZeroOrMore(element, this); break;
case "choice": result = new mozile.rng.Choice(element, this); break;
case "define": result = new mozile.rng.Define(element, this); break;
case "ref": result = new mozile.rng.Ref(element, this); break;
case "include": result = new mozile.rng.Include(element, this); break;
case "data": result = new mozile.rng.Data(element, this); break;
case "param": result = new mozile.rng.Param(element, this); break;
case "value": result = new mozile.rng.Value(element, this); break;
case "interleave": result = new mozile.rng.Interleave(element, this); break;
case "div": result = new mozile.rng.Div(element, this); break;
default:
validation.logError(this, null, "Method mozile.rng.Schema._createRNGNode() found an unknown element '"+ element.nodeName +"' with the RNG namespace.");
return null;
}
if(result) {
this._indexNode(result);
return result;
}
else return null;
}
mozile.rng.Schema.prototype._indexNode = function(node) {
var type = node.getType();
if(!this._types[type]) this._types[type] = new Array();
this._types[type].push(node);
if(node.getName) {
var name = node.getName();
if(!this._names[type]) this._names[type] = new Object();
if(!this._names[type][name]) this._names[type][name] = new Array();
this._names[type][name].push(node);
}
}
mozile.rng.Schema.prototype.getNodes = function(type, name) {
if(name) {
if(this._names[type] && this._names[type][name])
return this._names[type][name];
else return new Array();
}
else {
if(this._types[type]) return this._types[type];
else return new Array();
}
}
mozile.rng.Schema.prototype.load = function(filepath, forceLoad) {
if(!forceLoad && this._documents[filepath]) return this._documents[filepath];
var xmlDoc = mozile.xml.load(filepath);
if(xmlDoc) this._documents[filepath] = xmlDoc;
return xmlDoc;
}
mozile.rng.Schema.prototype.validate = function(element) {
if(!element) element = document.documentElement;
if(!this._root) return false;
var validation = new mozile.rng.Validation();
this._root.resetAll();
this._root.validate(element, validation);
return validation;
}
mozile.rng.Validation = function() {
this.isValid = true;
this.isEmpty = false;
this.allowText = false;
this._currentElement = null;
this._currentParent = null;
this._lastValidElement = null;
this._validAttributes = new Array();
this._messages = new Array();
}
mozile.rng.Validation.prototype.toString = function() { return "[object mozile.rng.Validation]" };
mozile.rng.Validation.prototype.getType = function() {
return "validation";
}
mozile.rng.Validation.prototype.getCurrentElement = function() {
return this._currentElement;
}
mozile.rng.Validation.prototype.setCurrentElement = function(element) {
if(element.nodeType == mozile.dom.ELEMENT_NODE) {
if(element == this._lastValidElement) {
this.logError(this, element, "An element has been marked as valid twice, which indicated an error");
}
else {
this._lastValidElement = this._currentElement;
this._currentElement = element;
}
}
return element;
}
mozile.rng.Validation.prototype.getCurrentParent = function() {
return this._currentParent;
}
mozile.rng.Validation.prototype.setCurrentParent = function(element) {
this._currentParent = element;
return element;
}
mozile.rng.Validation.prototype.addAttribute = function(attr) {
this._validAttributes.push(attr);
return attr;
}
mozile.rng.Validation.prototype.isAttributeValid = function(attr) {
for(var a=0; a < this._validAttributes.length; a++) {
if(mozile.browser.isMozilla && mozile.browser.mozillaVersion < 1.8) {
if(this._validAttributes[a].nodeName == attr.nodeName) return true;
}
if(this._validAttributes[a] == attr) return true;
}
return false;
}
mozile.rng.Validation.prototype.logMessage = function(rngNode, node, message, type) {
if(!type) type = "Message";
this._messages.push({"type": type, "rngNode": rngNode, "node": node, "message": message});
}
mozile.rng.Validation.prototype.logError = function(rngNode, node, message) {
this.logMessage(rngNode, node, message, "Error");
this.isValid = false;
}
mozile.rng.Validation.prototype.getFirstError = function() {
for(var m=0; m < this._messages.length; m++) {
if(this._messages[m].type != "Message") return this._messages[m];
}
return null;
}
mozile.rng.Validation.prototype.branch = function() {
var validation = new mozile.rng.Validation();
validation._currentParent = this._currentParent;
return validation;
}
mozile.rng.Validation.prototype.append = function(validation, status) {
this._messages = this._messages.concat(validation._messages);
if(status) this.isValid = status;
else if(!validation.isValid) this.isValid = false;
}
mozile.rng.Validation.prototype.merge = function(validation) {
this.append(validation);
this._validAttributes = this._validAttributes.concat(validation._validAttributes);
if(validation.isEmpty) this.isEmpty = true;
if(validation.allowText) this.allowText = true;
if(validation._currentElement) this._currentElement = validation._currentElement;
if(validation._lastValidElement) this._lastValidElement = validation._lastValidElement;
}
mozile.rng.Validation.prototype.report = function(errorsOnly) {
mozile.require("mozile.util");
mozile.require("mozile.xpath");
var messages = new Array();
var maxType = 8;
var maxName = 0;
var maxLocation = 0;
var msg;
var location;
var rngName
var lastNode;
var lastLocation;
for(var m=0; m < this._messages.length; m++) {
msg = this._messages[m];
if(errorsOnly && msg.type == "Message") continue;
rngName = "validation";
if(msg.rngNode) {
if(msg.rngNode.getType()) rngName = mozile.util.pad(msg.rngNode.getType(), 11, true);
if(msg.rngNode.getName) rngName = rngName +" "+ msg.rngNode.getName();
}
location = "";
if(msg.node) {
if(msg.node == lastNode) location = lastLocation;
else {
location = mozile.xpath.getXPath(msg.node);
location = location.replace(/xmlns:/g, "");
lastNode = msg.node;
lastLocation = location;
if(location.length > maxLocation) maxLocation = location.length;
}
}
if(rngName.length > maxName) maxName = rngName.length;
messages.push([msg.type, rngName, location, msg.message]);
}
var output = new Array();
var maxNum = Math.ceil( Math.log(messages.length+1) / Math.log(10) ) + 1;
for(m=0; m < messages.length; m++) {
msg = messages[m];
output.push( mozile.util.pad((m+1) +".", maxNum) +" "+ mozile.util.pad(msg[0], maxType) +" "+ mozile.util.pad(msg[1], maxName) +" "+ mozile.util.pad(msg[2], maxLocation) +" "+ msg[3] );
}
return output.join(mozile.linesep);
}
mozile.rng.Node = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Node.prototype._cached = [this._mustHaveCache, this._mayHaveCache, this._descendantElementsCache, this._type];
mozile.rng.Node.prototype.toString = function() {
var type = this.getType();
type = type.charAt(0).toUpperCase() + type.substring(1);
var name = "";
if(this.getName) name = " '"+ this.getName() +"'";
return "[object mozile.rng."+ type + name +"]";
}
mozile.rng.Node.prototype.getType = function() {
if(!this._type) this._type = mozile.dom.getLocalName(this._element);
return this._type;
}
mozile.rng.Node.prototype.getSchema = function() {
return this._schema;
}
mozile.rng.Node.prototype.getGrammar = function() {
var node = this;
while(node) {
if(node.getType() == "grammar") return node;
node = node.getParentNode();
}
return null;
}
mozile.rng.Node.prototype.getParentNode = function() {
if(this._parentNode) return this._parentNode;
return null;
}
mozile.rng.Node.prototype.getParentElement = function() {
var parent = this.getParentNode();
while(parent) {
if(parent.getType() == "element") return parent;
parent = parent.getParentNode();
}
return null;
}
mozile.rng.Node.prototype.getNextSibling = function() {
var parent = this.getParentNode();
if(!parent) return null;
var siblings = parent.getChildNodes();
for(var r=0; r < siblings.length; r++) {
if(siblings[r] == this) {
if(siblings[r+1]) return siblings[r+1];
}
}
return null;
}
mozile.rng.Node.prototype.getChildNodes = function() {
if(!this._childNodes) this._childNodes = new Array();
return this._childNodes;
}
mozile.rng.Node.prototype.getChildNode = function(index) {
var children = this.getChildNodes();
if(children && children.length &&
children.length > 0 && index < children.length)
return children[index];
else return null;
}
mozile.rng.Node.prototype.appendChild = function(child) {
if(child) {
this.getChildNodes().push(child);
child._parentNode = this;
}
return child;
}
mozile.rng.Node.prototype.removeChild = function(child) {
var children = new Array();
for(var c=0; c < this.getChildNodes().length; c++) {
if(this.getChildNodes()[c] == child) continue;
children.push(this.getChildNodes()[c]);
}
if(children.length == this.getChildNodes().length)
throw Error("mozile.rng.Node.removeChild(): The given node is not child of this node.");
else this._childNodes = children;
child._parentNode = null;
return child;
}
mozile.rng.Node.prototype.getDescendants = function(types, deep) {
if(deep !== false) deep = true;
var descendants = new Array();
if(!deep && mozile.rng.checkType(types, this.getType())) {
descendants.push(this);
}
else {
var result;
for(var c=0; c < this.getChildNodes().length; c++) {
result = this.getChildNode(c).getDescendants(types, false);
descendants = descendants.concat(result);
}
}
return descendants;
}
mozile.rng.Node.prototype.mustContain = function(type) {
if(!this._mustHaveCache) this._mustHaveCache = new Object();
if(this._mustHaveCache[type]) return this._mustHaveCache[type];
var result = false;
for(var c=0; c < this.getChildNodes().length; c++) {
if(this.getChildNodes()[c].mustHave(type)) {
result = true;
break;
}
}
this._mustHaveCache[type] = result;
return result;
}
mozile.rng.Node.prototype.mayContain = function(type) {
if(!this._mayHaveCache) this._mayHaveCache = new Object();
if(this._mayHaveCache[type]) return this._mayHaveCache[type];
var result = false;
for(var c=0; c < this.getChildNodes().length; c++) {
if(this.getChildNodes()[c].mayHave(type)) {
result = true;
break;
}
}
this._mayHaveCache[type] = result;
return result;
}
mozile.rng.Node.prototype.mustHave = function(type) {
if(this.getType() == type) return true;
else return this.mustContain(type);
}
mozile.rng.Node.prototype.mayHave = function(type) {
if(this.getType() == type) return true;
else return this.mayContain(type);
}
mozile.rng.Node.prototype.reset = function() {
for(var i=0; i < this._cached.length; i++) {
this._cached[i] = undefined;
}
}
mozile.rng.Node.prototype.resetAll = function() {
this.reset();
for(var c=0; c < this.getChildNodes().length; c++) {
this.getChildNodes()[c].reset;
}
}
mozile.rng.Node.prototype.selfValidate = function(validation) {
if(!mozile.dom.getFirstChildElement(this._element))
validation.logError(this, this._element, "This RNG element must have at least one child element.");
return validation;
}
mozile.rng.Node.prototype.selfValidateAll = function(validation) {
validation = this.selfValidate(validation);
validation.logMessage(this, null, "Self validated.");
for(var r=0; r < this.getChildNodes().length; r++) {
if(!validation.isValid) break;
validation = this.getChildNodes()[r].selfValidateAll(validation);
}
return validation;
}
mozile.rng.Node.prototype.validate = function(node, validation) {
validation.logError(this, node, "The validate() method is not defined yet for "+ this +".");
return validation;
}
mozile.rng.Grammar = function(element, schema) {
this._element = element;
this._schema = schema;
this._start = null;
this._definitions = new Object;
}
mozile.rng.Grammar.prototype = new mozile.rng.Node;
mozile.rng.Grammar.prototype.constructor = mozile.rng.Grammar;
mozile.rng.Grammar.prototype.getParentGrammar = function() {
var parent = this.getParentNode();
while(parent) {
if(parent.getType() == "grammar") return parent;
parent = parent.getParentNode();
}
return null;
}
mozile.rng.Grammar.prototype.appendChild = function(child) {
if(child && child.getType) {
switch(child.getType()) {
case "start":
return this.setStart(child);
break;
case "define":
return this.addDefinition(child);
break;
case "include":
case "div":
break;
default:
throw Error("RNG grammar element cannot have a child of type '"+ child.getType() +"'.");
break;
}
this.getChildNodes().push(child);
child._parentNode = this;
}
return child;
}
mozile.rng.Grammar.prototype.getStart = function() {
if(this._start) return this._start;
else return null;
}
mozile.rng.Grammar.prototype.setStart = function(start) {
if(start.getType && start.getType() == "start") {
if(this._start) this._start.combine(start);
else {
this._start = start;
this.getChildNodes().push(start);
start._parentNode = this;
}
return start;
}
else return null;
}
mozile.rng.Grammar.prototype.getDefinition = function(name) {
if(this._definitions[name]) return this._definitions[name];
else return null;
}
mozile.rng.Grammar.prototype.addDefinition = function(definition) {
if(this._definitions[definition.getName()]) {
definition = this._definitions[definition.getName()].combine(definition);
}
else {
this._definitions[definition.getName()] = definition;
this.getChildNodes().push(definition);
definition._parentNode = this;
}
return definition;
}
mozile.rng.Grammar.prototype.mustHave = function(type) {
if(this.getType() == type) return true;
var result = false;
var start = this.getStart();
if(start) result = start.mustHave(type);
else throw Error("mozile.rng.Grammar.mustHave() requires getStart() to return a mozile.rng.Start object.");
return result;
}
mozile.rng.Grammar.prototype.mayHave = function(type) {
if(this.getType() == type) return true;
var result = false;
var start = this.getStart();
if(start) result = start.mayHave(type);
else throw Error("mozile.rng.Grammar.mayHave() requires getStart() to return a mozile.rng.Start object.");
return result;
}
mozile.rng.Grammar.prototype.validate = function(node, validation) {
var start = this.getStart();
if(start) validation = start.validate(node, validation);
else validation.logError(this, node, "RNG grammar element must have a start element in order to validate a node, but it does not.");
return validation;
}
mozile.rng.Start = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Start.prototype = new mozile.rng.Node;
mozile.rng.Start.prototype.constructor = mozile.rng.Start;
mozile.rng.Start.prototype.combine = mozile.rng.combine;
mozile.rng.Start.prototype.selfValidate = function(validation) {
if(!this._element.parentNode || mozile.dom.getLocalName(this._element.parentNode) != "grammar")
validation.logError(this, this._element, "This RNG element must be the child of a grammar element.");
if(!mozile.dom.getFirstChildElement(this._element))
validation.logError(this, this._element, "This RNG element must have at least one child element.");
var combine = this._element.getAttribute("combine");
if(combine) {
if(combine != "choice" && combine != "interleave")
validation.logError(this, this._element, "This RNG 'start' element has an invalid 'combine' attribute value of '"+ combine +"'.");
}
return validation;
}
mozile.rng.Start.prototype.validate = function(node, validation) {
var RNGChild = this.getChildNode(0);
if(RNGChild) validation = RNGChild.validate(node, validation);
return validation;
}
mozile.rng.Element = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Element.prototype = new mozile.rng.Node;
mozile.rng.Element.prototype.constructor = mozile.rng.Element;
mozile.rng.Element.prototype._cached = [this._mustHaveCache, this._mayHaveCache, this._descendantElementsCache, this._type, this._name, this._localName, this._prefix, this._namespace];
mozile.rng.Element.prototype.getName = mozile.rng.getName;
mozile.rng.Element.prototype.getLocalName = mozile.rng.getLocalName;
mozile.rng.Element.prototype.getPrefix = mozile.rng.getPrefix;
mozile.rng.Element.prototype.getNamespace = function() {
if(this._namespace) return this._namespace;
if(this._element.getAttribute("ns")) this._namespace = this._element.getAttribute("ns");
else if(this.getPrefix()) this._namespace = mozile.dom.lookupNamespaceURI(this._element, this.getPrefix());
else {
var parent = this.getParentNode();
while(parent && parent._element) {
if(parent._element.getAttribute("ns")) {
this._namespace = parent._element.getAttribute("ns");
break;
}
parent = parent.getParentNode();
}
}
if(!this._namespace) this._namespace = null;
return this._namespace;
}
mozile.rng.Element.prototype.mustHave = function(type) {
if(this.getType() == type) return true;
else return false;
}
mozile.rng.Element.prototype.mayHave = function(type) {
if(this.getType() == type) return true;
else return false;
}
mozile.rng.Element.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.Element.validate() requires a node.");
if(!validation) validation = new mozile.rng.Validation();
validation = this._validateElement(node, validation);
if(!validation.isValid) return validation;
validation.logMessage(this, node, "Validating element...");
var result = new mozile.rng.Validation();
result.setCurrentParent(node);
result = this._validateChildElements(node, result);
if(result.isValid) result = this._validateText(node, result);
if(result.isValid) result = this._validateAttributes(node, result);
if(result.isValid) result.logMessage(this, node, "Element is valid.");
else result.logError(this, node, "Element is not valid.");
validation.append(result);
validation.setCurrentElement(node);
return validation;
}
mozile.rng.Element.prototype._validateElement = function(node, validation) {
if(!node) throw Error("mozile.rng.Element._validateElement() requires a node.");
if(!validation) throw Error("mozile.rng.Element._validateElement() requires an mozile.rng.Validation object.");
if(node.nodeType != mozile.dom.ELEMENT_NODE) validation.logError(this, node, "Not an element.");
if(!validation.isValid) return validation;
if(mozile.dom.getLocalName(node) != this.getLocalName()) validation.logError(this, node, "Names do not match. '"+ mozile.dom.getLocalName(node) +"' != '"+ this.getLocalName() +"'");
if(!validation.isValid) return validation;
var ns = this.getNamespace();
if(ns) {
if(node.namespaceURI != ns) validation.logError(this, node, "Namespaces do not match. '"+ node.namespaceURI +"' != '"+ ns +"'");
}
else {
if(node.namespaceURI) validation.logError(this, node, "This element has the namespace '"+ node.namespaceURI +"'but the RNG element has no namespace.");
}
if(!validation.isValid) return validation;
return validation;
}
mozile.rng.Element.prototype._validateSequence = mozile.rng.validateSequence;
mozile.rng.Element.prototype._validateChildElements = function(node, validation) {
if(!node) throw Error("mozile.rng.Element._validateChildElements() requires a node.");
if(!validation) throw Error("mozile.rng.Element._validateChildElements() requires an mozile.rng.Validation object.");
var RNGChildren = this.getChildNodes();
var child = mozile.dom.getFirstChildElement(node);
var r=0;
if(!child) {
for(r=0; r < RNGChildren.length; r++) {
if(RNGChildren[r].mustHave("element")) {
validation.logError(this, node, "This element must have child elements, but it does not.");
return validation;
}
}
if(node.firstChild) validation.logMessage(this, node, "Element has no child elements.");
}
if(!child) {
if(node.attributes.length > 0) child = node.attributes[0];
else {
for(r=0; r < RNGChildren.length; r++) {
if(RNGChildren[r].mustHave("attribute")) {
validation.logError(this, node, "This element must have attributes, but it does not.");
return validation;
}
}
}
}
if(!child && node.firstChild) {
child = node.firstChild;
}
if(!child) validation.logMessage(this, node, "Element has no child nodes or attributes.");
else {
validation = this._validateSequence(child, validation);
if(validation.isValid) {
var overflow;
if(mozile.dom.getFirstChildElement(node) && !validation.getCurrentElement())
overflow = mozile.dom.getFirstChildElement(node);
if(validation.getCurrentElement() && mozile.dom.getNextSiblingElement(validation.getCurrentElement()) )
overflow = mozile.dom.getNextSiblingElement(validation.getCurrentElement());
if(overflow) {
validation.logError(this, node, "There are elements which are not matched by any RNG rules: '"+ overflow.nodeName +"'.");
}
}
if(mozile.dom.getFirstChildElement(node) && validation.isValid) validation.logMessage(this, node, "All child elements are valid.");
}
return validation;
}
mozile.rng.Element.prototype._validateText = function(node, validation) {
if(!node) throw Error("mozile.rng.Element._validateText() requires a node.");
if(!validation) throw Error("mozile.rng.Element._validateText() requires an mozile.rng.Validation object.");
var child;
for(var r=0; r < node.childNodes.length; r++) {
child = node.childNodes[r];
if(child.nodeType != mozile.dom.TEXT_NODE) continue;
if(mozile.dom.isWhitespace(child)) continue;
if(validation.isEmpty) validation.logError(this, node, "This element contains text, but it is supposed to be empty.");
if(!validation.allowText) validation.logError(this, node, "This element contains text but that is not allowed.");
if(validation.isValid) {
validation.logMessage(this, node, "Element has text content.");
break;
}
}
return validation;
}
mozile.rng.Element.prototype._validateAttributes = function(node, validation) {
var attr;
for(var r=0; r < node.attributes.length; r++) {
attr = node.attributes[r];
if(mozile.dom.isIgnored(attr)) continue;
if(validation.isEmpty) validation.logError(this, node, "This element contains attributes, but it is supposed to be empty.");
if(validation.isAttributeValid(attr)) continue;
validation.logError(this, node, "This element contains an invalid attribute: "+ attr.nodeName);
}
if(validation.isValid && node.attributes.length > 0) validation.logMessage(this, node, "All attributes are valid.");
return validation;
}
mozile.rng.Attribute = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Attribute.prototype = new mozile.rng.Node;
mozile.rng.Attribute.prototype.constructor = mozile.rng.Attribute;
mozile.rng.Attribute.prototype._cached = [this._mustHaveCache, this._mayHaveCache, this._descendantElementsCache, this._type, this._name, this._localName, this._prefix, this._namespace];
mozile.rng.Attribute.prototype.getName = mozile.rng.getName;
mozile.rng.Attribute.prototype.getLocalName = mozile.rng.getLocalName;
mozile.rng.Attribute.prototype.getPrefix = mozile.rng.getPrefix;
mozile.rng.Attribute.prototype.getNamespace = function() {
if(this._namespace) return this._namespace;
if(this._element.getAttribute("ns")) this._namespace = this._element.getAttribute("ns");
else if(this.getPrefix()) {
if(this.getPrefix() == "xml") this._namespace = null;
else this._namespace = mozile.dom.lookupNamespaceURI(this._element, this.getPrefix());
}
if(!this._namespace) this._namespace = null;
return this._namespace;
}
mozile.rng.Attribute.prototype.selfValidate = function(validation) {
return validation;
}
mozile.rng.Attribute.prototype.mustHave = function(type) {
if(this.getType() == type) return true;
else return false;
}
mozile.rng.Attribute.prototype.mayHave = function(type) {
if(this.getType() == type) return true;
else return false;
}
mozile.rng.Attribute.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.Attribute.validate() requires a node.");
if(!validation) throw Error("mozile.rng.Attribute.validate() requires an mozile.rng.Validation object.");
var element = validation.getCurrentParent();
if(!element) throw Error("mozile.rng.Attribute.validate() requires the Validation object to have a 'current parent' element.");
if(element) {
var attr;
var ns = this.getNamespace();
if(ns) {
if(element.getAttributeNodeNS) attr = element.getAttributeNodeNS(ns, this.getLocalName());
else {
var prefix = mozile.dom.lookupPrefix(element, ns);
if(prefix) attr = element.getAttributeNode(prefix +":"+ this.getLocalName());
}
}
else attr = element.getAttributeNode(this.getLocalName());
if(attr) {
validation.addAttribute(attr);
validation.logMessage(this, element, "Attribute "+ attr.nodeName +" validated.");
}
else validation.logError(this, element, "Attribute "+ this.getName() +" not found.");
}
else validation.logError(this, node, "The node has no parent node.");
return validation;
}
mozile.rng.Text = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Text.prototype = new mozile.rng.Node;
mozile.rng.Text.prototype.constructor = mozile.rng.Text;
mozile.rng.Text.prototype.mustHave = function(type) {
if(this.getType() == type) return true;
else return false;
}
mozile.rng.Text.prototype.mayHave = function(type) {
if(this.getType() == type) return true;
else return false;
}
mozile.rng.Text.prototype.selfValidate = function(validation) {
if(mozile.dom.getFirstChildElement(this._element))
validation.logError(this, this._element, "This RNG element must not have any child elements.");
return validation;
}
mozile.rng.Text.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.Text.validate() requires a node.");
if(!validation) throw Error("mozile.rng.Text.validate() requires an mozile.rng.Validation object.");
if(!validation.allowText) validation.logMessage(this, node.parentNode, "This element is allowed to contain text.");
validation.allowText = true;
return validation;
}
mozile.rng.Empty = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Empty.prototype = new mozile.rng.Node;
mozile.rng.Empty.prototype.constructor = mozile.rng.Empty;
mozile.rng.Empty.prototype.mustHave = function(type) {
if(this.getType() == type) return true;
else return false;
}
mozile.rng.Empty.prototype.mayHave = function(type) {
if(this.getType() == type) return true;
else return false;
}
mozile.rng.Empty.prototype.selfValidate = function(validation) {
if(mozile.dom.getFirstChildElement(this._element))
validation.logError(this, this._element, "This RNG element must not have any child elements.");
return validation;
}
mozile.rng.Empty.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.Empty.validate() requires a node.");
if(!validation) throw Error("mozile.rng.Empty.validate() requires an mozile.rng.Validation object.");
validation.isEmpty = true;
validation.logMessage(this, node.parentNode, "This element must be empty.");
return validation;
}
mozile.rng.Group = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Group.prototype = new mozile.rng.Node;
mozile.rng.Group.prototype.constructor = mozile.rng.Group;
mozile.rng.Group.prototype.selfValidate = function(validation) {
if(mozile.dom.getChildElements(this._element).length < 2)
validation.logError(this, this._element, "This RNG element must have at least two child elements.");
return validation;
}
mozile.rng.Group.prototype._validateSequence = mozile.rng.validateSequence;
mozile.rng.Group.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.Group.validate() requires a node.");
if(!validation) throw Error("mozile.rng.Group.validate() requires an mozile.rng.Validation object.");
validation = this._validateSequence(node, validation);
if(validation.isValid) validation.logMessage(this, validation.getCurrentElement(), "Group is valid.");
return validation;
}
mozile.rng.Optional = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Optional.prototype = new mozile.rng.Node;
mozile.rng.Optional.prototype.constructor = mozile.rng.Optional;
mozile.rng.Optional.prototype.mustHave = function(type) {
if(this.getType() == type) return true;
else return false;
}
mozile.rng.Optional.prototype._validateSequence = mozile.rng.validateSequence;
mozile.rng.Optional.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.Optional.validate() requires a node.");
if(!validation) throw Error("mozile.rng.Optional.validate() requires an mozile.rng.Validation object.");
var result = validation.branch();
result = this._validateSequence(node, result);
if(result.isValid) {
validation.count = 1;
validation.merge(result);
validation.logMessage(this, validation.getCurrentElement(), "Option is present.");
}
else {
if(mozile.rng.debug) validation.append(result, true);
validation.logMessage(this, node, "Option is not present.");
}
return validation;
}
mozile.rng.ZeroOrMore = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.ZeroOrMore.prototype = new mozile.rng.Node;
mozile.rng.ZeroOrMore.prototype.constructor = mozile.rng.ZeroOrMore;
mozile.rng.ZeroOrMore.prototype.mustHave = function(type) {
if(this.getType() == type) return true;
else return false;
}
mozile.rng.ZeroOrMore.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.ZeroOrMore.validate() requires a node.");
if(!validation) throw Error("mozile.rng.ZeroOrMore.validate() requires an mozile.rng.Validation object.");
validation = this._validateMany(node, validation);
validation.logMessage(this, validation.getCurrentElement(), "ZeroOrMore matched "+ validation.count +" times.");
return validation;
}
mozile.rng.ZeroOrMore.prototype._validateSequence = mozile.rng.validateSequence;
mozile.rng.ZeroOrMore.prototype._validateMany = mozile.rng.validateMany;
mozile.rng.OneOrMore = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.OneOrMore.prototype = new mozile.rng.Node;
mozile.rng.OneOrMore.prototype.constructor = mozile.rng.OneOrMore;
mozile.rng.OneOrMore.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.OneOrMore.validate() requires a node.");
if(!validation) throw Error("mozile.rng.OneOrMore.validate() requires an mozile.rng.Validation object.");
validation = this._validateMany(node, validation);
if(validation.count == 0) validation.logError(this, validation.getCurrentElement(), "OneOrMore did not match any nodes.");
validation.logMessage(this, validation.getCurrentElement(), "OneOrMore matched "+ validation.count +" times.");
return validation;
}
mozile.rng.OneOrMore.prototype._validateSequence = mozile.rng.validateSequence;
mozile.rng.OneOrMore.prototype._validateMany = mozile.rng.validateMany;
mozile.rng.Choice = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Choice.prototype = new mozile.rng.Node;
mozile.rng.Choice.prototype.constructor = mozile.rng.Choice;
mozile.rng.Choice.prototype.mustHave = function(type) {
if(this.getType() == type) return true;
if(!this._mustHaveCache) this._mustHaveCache = new Object();
if(this._mustHaveCache[type]) return this._mustHaveCache[type];
var result = true;
for(var c=0; c < this.getChildNodes().length; c++) {
if(!this.getChildNodes()[c].mustHave(type)) {
result = false;
break;
}
}
this._mustHaveCache[type] = result;
return result;
}
mozile.rng.Choice.prototype.selfValidate = function(validation) {
if(mozile.dom.getChildElements(this._element).length < 2)
validation.logError(this, this._element, "This RNG element must have at least two child elements.");
return validation;
}
mozile.rng.Choice.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.Choice.validate() requires a node.");
if(!validation) throw Error("mozile.rng.Choice.validate() requires an mozile.rng.Validation object.");
var RNGChildren = this.getChildNodes();
var r = 0;
for(r=0; r < RNGChildren.length; r++) {
if(validation.allowText) break;
if(RNGChildren[r].getType() == "text") validation = RNGChildren[r].validate(node, validation);
}
var result;
for(r=0; r < RNGChildren.length; r++) {
if(RNGChildren[r].getType() == "text" && node.nodeType == mozile.dom.ELEMENT_NODE) continue;
result = validation.branch();
result = RNGChildren[r].validate(node, result);
if(result.isValid) break;
else if(mozile.rng.debug) validation.append(result, true);
}
if(result && result.isValid) {
validation.merge(result);
validation.logMessage(this, validation.getCurrentElement(), "Choice number "+ (r+1) +" selected.");
}
else validation.logError(this, node, "All choices failed to validate.");
return validation;
}
mozile.rng.Define = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Define.prototype = new mozile.rng.Node;
mozile.rng.Define.prototype.constructor = mozile.rng.Define;
mozile.rng.Define.prototype.getName = mozile.rng.getName;
mozile.rng.Define.prototype.combine = mozile.rng.combine;
mozile.rng.Define.prototype.selfValidate = function(validation) {
if(!this._element.parentNode)
validation.logError(this, this._element, "This RNG element must be the child of a 'grammar', 'include', or 'div' element.");
var parentName = mozile.dom.getLocalName(this._element.parentNode);
if (parentName != "grammar" && parentName != "include" && parentName != "div")
validation.logError(this, this._element, "This RNG element must be the child of a 'grammar', 'include', or 'div' element.");
if(!mozile.dom.getFirstChildElement(this._element))
validation.logError(this, this._element, "This RNG element must have at least one child element.");
if(!this.getName())
validation.logError(this, this._element, "This RNG element must have a 'name' attribute.");
var combine = this._element.getAttribute("combine");
if(combine) {
if(combine != "choice" && combine != "interleave")
validation.logError(this, this._element, "This RNG 'define' element has an invalid 'combine' attribute value of '"+ combine +"'.");
}
return validation;
}
mozile.rng.Define.prototype._validateSequence = mozile.rng.validateSequence;
mozile.rng.Define.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.Define.validate() requires a node.");
if(!validation) throw Error("mozile.rng.Define.validate() requires an mozile.rng.Validation object.");
validation = this._validateSequence(node, validation);
if(validation.isValid) validation.logMessage(this, validation.getCurrentElement(), "Definition is valid.");
return validation;
}
mozile.rng.Ref = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Ref.prototype = new mozile.rng.Node;
mozile.rng.Ref.prototype.constructor = mozile.rng.Ref;
mozile.rng.Ref.prototype._cached = [this._type, this._name, this._grammar, this._definition];
mozile.rng.Ref.prototype.getName = mozile.rng.getName;
mozile.rng.Ref.prototype.getDefinition = function() {
if(!this._grammar) this._grammar = this.getGrammar()
if(this._grammar) {
if(!this._definition) this._definition = this.getGrammar().getDefinition(this.getName());
if(this._definition) return this._definition;
}
return null;
}
mozile.rng.Ref.prototype.getDescendants = function(types, deep) {
if(!deep && mozile.rng.checkType(types, this.getType())) return new Array(this);
else if(this.getDefinition()) return this.getDefinition().getDescendants(types, deep);
else return new Array();
}
mozile.rng.Ref.prototype.mustHave = function(type) {
if(this.getType() == type) return true;
if(this.getDefinition()) return this.getDefinition().mustHave(type);
else return false;
}
mozile.rng.Ref.prototype.mayHave = function(type) {
if(this.getType() == type) return true;
if(this.getDefinition()) return this.getDefinition().mayHave(type);
else return false;
}
mozile.rng.Ref.prototype.selfValidate = function(validation) {
if(mozile.dom.getFirstChildElement(this._element))
validation.logError(this, this._element, "This RNG element must not have any child elements.");
if(!this.getName())
validation.logError(this, this._element, "This RNG element must have a 'name' attribute.");
return validation;
}
mozile.rng.Ref.prototype.validate = function(node, validation) {
if(this.getDefinition()) {
validation.logMessage(this, node, "Reference followed.");
validation = this.getDefinition().validate(node, validation);
}
else validation.logError(this, node, "This reference does not have a matching definition.");
return validation;
}
mozile.rng.Data = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Data.prototype = new mozile.rng.Node;
mozile.rng.Data.prototype.constructor = mozile.rng.Data;
mozile.rng.Data.prototype.selfValidate = function(validation) {
if(!this._element.getAttribute("type"))
validation.logError(this, this._element, "This RNG element must have an 'type' attribute.");
return validation;
}
mozile.rng.Param = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Param.prototype = new mozile.rng.Node;
mozile.rng.Param.prototype.constructor = mozile.rng.Param;
mozile.rng.Value = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Value.prototype = new mozile.rng.Node;
mozile.rng.Value.prototype.constructor = mozile.rng.Value;
mozile.rng.Value.prototype.selfValidate = function(validation) {
for(var r=0; r < this._element.childNodes.length; r++) {
if(this._element.childNodes[r].nodeType == mozile.dom.TEXT_NODE &&
!mozile.dom.isWhitespace(this._element.childNodes[r])) {
return validation;
}
}
validation.logError(this, this._element, "This RNG element must contain non-whitespace text.");
return validation;
}
mozile.rng.Include = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Include.prototype = new mozile.rng.Node;
mozile.rng.Include.prototype.constructor = mozile.rng.Include;
mozile.rng.Include.prototype.selfValidate = function(validation) {
if(!this._element.parentNode || mozile.dom.getLocalName(this._element.parentNode) != "grammar")
validation.logError(this, this._element, "This RNG element must be the child of a grammar element.");
if(!this._element.getAttribute("href"))
validation.logError(this, this._element, "This RNG element must have an 'href' attribute.");
return validation;
}
mozile.rng.Include.prototype.include = function(validation) {
if(!validation) throw Error("mozile.rng.Include.include() requires an mozile.rng.Validation object.");
var href = this._element.getAttribute("href");
var schema = this.getSchema();
var grammar = this.getGrammar();
if(!href || !schema || !grammar) {
validation.logError(this, this._element, "mozile.rng.Include.include() requires an 'href', a schema, and a grammar, but one or more was missing.");
return validation;
}
var root;
if(this.filepath) root = this.filepath;
else if(schema.filepath) root = schema.filepath;
var URI = mozile.getAbsolutePath(href, root);
var filepath = mozile.getDirectory(URI);
validation.logMessage(this, this._element, "Including RNG content from '"+ URI +"'.");
var rngDoc = schema.load(URI);
if(!rngDoc || !rngDoc.documentElement ||
mozile.dom.getLocalName(rngDoc.documentElement) != "grammar") {
validation.logError(this, null, "mozile.rng.Include.include() could not load schema at '"+ URI +"'.");
return validation;
}
var children = rngDoc.documentElement.childNodes;
for(var c=0; c < children.length; c++) {
var child = null;
switch(mozile.dom.getLocalName(children[c])) {
case "start":
child = schema.parseElement(children[c], validation);
break;
case "define":
for(var i=0; i < this._element.childNodes.length; i++) {
var includeChild = this._element.childNodes[i];
if(includeChild.nodeType != mozile.dom.ELEMENT_NODE) continue;
var includeChildName = includeChild.getAttribute("name");
if(mozile.dom.getLocalName(includeChild) == "define" &&
includeChildName == children[c].getAttribute("name") ) {
validation.logMessage(this, includeChild, "Overriding defintition of '"+ includeChildName +"'.");
child = schema.parseElement(includeChild, validation);
break;
}
}
if(!child) child = schema.parseElement(children[c], validation);
break;
case "include":
child = schema.parseElement(children[c], validation);
child.filepath = filepath;
break;
default:
child = null;
break;
}
if(child) grammar.appendChild(child);
}
return validation;
}
mozile.rng.Interleave = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Interleave.prototype = new mozile.rng.Node;
mozile.rng.Interleave.prototype.constructor = mozile.rng.Interleave;
mozile.rng.Interleave.prototype.selfValidate = function(validation) {
if(mozile.dom.getChildElements(this._element).length < 2)
validation.logError(this, this._element, "This RNG element must have at least two child elements.");
return validation;
}
mozile.rng.Interleave.prototype.validate = mozile.rng.validateInterleave;
mozile.rng.Div = function(element, schema) {
this._element = element;
this._schema = schema;
}
mozile.rng.Div.prototype = new mozile.rng.Node;
mozile.rng.Div.prototype.constructor = mozile.rng.Div;
mozile.rng.Div.prototype.selfValidate = function(validation) {
if(!this._element.parentNode ||
mozile.dom.getLocalName(this._element.parentNode) != "grammar" )
validation.logError(this, this._element, "This RNG element must be the child of a 'grammar' element.");
return validation;
}
mozile.rng.Div.prototype._validateSequence = mozile.rng.validateSequence;
mozile.rng.Div.prototype.validate = function(node, validation) {
if(!node) throw Error("mozile.rng.Div.validate() requires a node.");
if(!validation) throw Error("mozile.rng.Div.validate() requires an mozile.rng.Validation object.");
validation = this._validateSequence(node, validation);
if(validation.isValid) validation.logMessage(this, validation.getCurrentElement(), "Div is valid.");
return validation;
}
Documentation generated by
JSDoc on Wed Aug 23 18:45:51 2006