diff --git a/Gruntfile.js b/Gruntfile.js index 40a79c8a..96f22d76 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -130,7 +130,8 @@ module.exports = function(grunt) { "src/js/lib/vkbeautify.js", "src/js/lib/Sortable.js", "src/js/lib/bootstrap-colorpicker.js", - + "src/js/lib/xpath.js", + // Custom libraries "src/js/lib/canvas_components.js", diff --git a/src/js/config/Categories.js b/src/js/config/Categories.js index f75a5484..7f55eef5 100755 --- a/src/js/config/Categories.js +++ b/src/js/config/Categories.js @@ -189,6 +189,8 @@ const Categories = [ "Extract file paths", "Extract dates", "Regular expression", + "XPath expression", + "CSS selector", ] }, { diff --git a/src/js/config/OperationConfig.js b/src/js/config/OperationConfig.js index 5591a43c..9e7a68e4 100755 --- a/src/js/config/OperationConfig.js +++ b/src/js/config/OperationConfig.js @@ -1938,6 +1938,42 @@ const OperationConfig = { }, ] }, + "XPath expression": { + description: "Extract information from an xml document with an XPath query", + run: Extract.run_xpath, + input_type: "string", + output_type: "string", + args: [ + { + name: "XPath", + type: "string", + value: Extract.XPATH_INITIAL + }, + { + name: "Result delimiter", + type: "binary_short_string", + value: Extract.XPATH_DELIMITER + } + ] + }, + "CSS selector": { + description: "Extract information from an HTML document with an CSS selector", + run: Extract.run_css_query, + input_type: "string", + output_type: "string", + args: [ + { + name: "CSS selector", + type: "string", + value: Extract.SELECTOR_INITIAL + }, + { + name: "Delimiter", + type: "binary_short_string", + value: Extract.CSS_QUERY_DELIMITER + }, + ] + }, "From UNIX Timestamp": { description: "Converts a UNIX timestamp to a datetime string.

e.g. 978346800 becomes Mon 1 January 2001 11:00:00 UTC", run: DateTime.run_from_unix_timestamp, diff --git a/src/js/lib/xpath.js b/src/js/lib/xpath.js new file mode 100644 index 00000000..4a1e3d7d --- /dev/null +++ b/src/js/lib/xpath.js @@ -0,0 +1,8466 @@ +(function(){/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +// Javascript objects +var cString = window.String, + cBoolean = window.Boolean, + cNumber = window.Number, + cObject = window.Object, + cArray = window.Array, + cRegExp = window.RegExp, + cDate = window.Date, + cFunction = window.Function, + cMath = window.Math, +// Error Objects + cError = window.Error, + cSyntaxError= window.SyntaxError, + cTypeError = window.TypeError, +// misc + fIsNaN = window.isNaN, + fIsFinite = window.isFinite, + nNaN = window.NaN, + nInfinity = window.Infinity, + // Functions + fWindow_btoa = window.btoa, + fWindow_atob = window.atob, + fWindow_parseInt= window.parseInt, + fString_trim =(function() { + return cString.prototype.trim ? function(sValue) {return cString(sValue).trim();} : function(sValue) { + return cString(sValue).replace(/^\s+|\s+$/g, ''); + }; + })(), + fArray_indexOf =(function() { + return cArray.prototype.indexOf ? function(aValue, vItem) {return aValue.indexOf(vItem);} : function(aValue, vItem) { + for (var nIndex = 0, nLength = aValue.length; nIndex < nLength; nIndex++) + if (aValue[nIndex] === vItem) + return nIndex; + return -1; + }; + })(); + +var sNS_XSD = "http://www.w3.org/2001/XMLSchema", + sNS_XPF = "http://www.w3.org/2005/xpath-functions", + sNS_XNS = "http://www.w3.org/2000/xmlns/", + sNS_XML = "http://www.w3.org/XML/1998/namespace"; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cException(sCode + + ) { + + this.code = sCode; + this.message = + + oException_messages[sCode]; +}; + +cException.prototype = new cError; + +// "http://www.w3.org/2005/xqt-errors" + +var oException_messages = {}; +oException_messages["XPDY0002"] = "Evaluation of an expression relies on some part of the dynamic context that has not been assigned a value."; +oException_messages["XPST0003"] = "Expression is not a valid instance of the grammar"; +oException_messages["XPTY0004"] = "Type is not appropriate for the context in which the expression occurs"; +oException_messages["XPST0008"] = "Expression refers to an element name, attribute name, schema type name, namespace prefix, or variable name that is not defined in the static context"; +oException_messages["XPST0010"] = "Axis not supported"; +oException_messages["XPST0017"] = "Expanded QName and number of arguments in a function call do not match the name and arity of a function signature"; +oException_messages["XPTY0018"] = "The result of the last step in a path expression contains both nodes and atomic values"; +oException_messages["XPTY0019"] = "The result of a step (other than the last step) in a path expression contains an atomic value."; +oException_messages["XPTY0020"] = "In an axis step, the context item is not a node."; +oException_messages["XPST0051"] = "It is a static error if a QName that is used as an AtomicType in a SequenceType is not defined in the in-scope schema types as an atomic type."; +oException_messages["XPST0081"] = "A QName used in an expression contains a namespace prefix that cannot be expanded into a namespace URI by using the statically known namespaces."; +// +oException_messages["FORG0001"] = "Invalid value for cast/constructor."; +oException_messages["FORG0003"] = "fn:zero-or-one called with a sequence containing more than one item."; +oException_messages["FORG0004"] = "fn:one-or-more called with a sequence containing no items."; +oException_messages["FORG0005"] = "fn:exactly-one called with a sequence containing zero or more than one item."; +oException_messages["FORG0006"] = "Invalid argument type."; +// +oException_messages["FODC0001"] = "No context document."; +// +oException_messages["FORX0001"] = "Invalid regular expression flags."; +// +oException_messages["FOCA0002"] = "Invalid lexical value."; +// +oException_messages["FOCH0002"] = "Unsupported collation."; + +oException_messages["FONS0004"] = "No namespace found for prefix."; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cLexer(sValue) { + var aMatch = sValue.match(/\$?(?:(?![0-9-])(?:\w[\w.-]*|\*):)?(?![0-9-])(?:\w[\w.-]*|\*)|\(:|:\)|\/\/|\.\.|::|\d+(?:\.\d*)?(?:[eE][+-]?\d+)?|\.\d+(?:[eE][+-]?\d+)?|"[^"]*(?:""[^"]*)*"|'[^']*(?:''[^']*)*'|<<|>>|[!<>]=|(?![0-9-])[\w-]+:\*|\s+|./g); + if (aMatch) { + var nStack = 0; + for (var nIndex = 0, nLength = aMatch.length; nIndex < nLength; nIndex++) + if (aMatch[nIndex] == '(:') + nStack++; + else + if (aMatch[nIndex] == ':)' && nStack) + nStack--; + else + if (!nStack && !/^\s/.test(aMatch[nIndex])) + this[this.length++] = aMatch[nIndex]; + if (nStack) + throw new cException("XPST0003" + + ); + } +}; + +cLexer.prototype.index = 0; +cLexer.prototype.length = 0; + +cLexer.prototype.reset = function() { + this.index = 0; +}; + +cLexer.prototype.peek = function(nOffset) { + return this[this.index +(nOffset || 0)] || ''; +}; + +cLexer.prototype.next = function(nOffset) { + return(this.index+= nOffset || 1) < this.length; +}; + +cLexer.prototype.back = function(nOffset) { + return(this.index-= nOffset || 1) > 0; +}; + +cLexer.prototype.eof = function() { + return this.index >= this.length; +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cDOMAdapter() { + +}; + +// Custom members +cDOMAdapter.prototype.isNode = function(oNode) { + return oNode &&!!oNode.nodeType; +}; + +cDOMAdapter.prototype.getProperty = function(oNode, sName) { + return oNode[sName]; +}; + +// Standard members +cDOMAdapter.prototype.isSameNode = function(oNode, oNode2) { + return oNode == oNode2; +}; + +cDOMAdapter.prototype.compareDocumentPosition = function(oNode, oNode2) { + return oNode.compareDocumentPosition(oNode2); +}; + +cDOMAdapter.prototype.lookupNamespaceURI = function(oNode, sPrefix) { + return oNode.lookupNamespaceURI(sPrefix); +}; + +// Document object members +cDOMAdapter.prototype.getElementById = function(oNode, sId) { + return oNode.getElementById(sId); +}; + +// Element/Document object members +cDOMAdapter.prototype.getElementsByTagNameNS = function(oNode, sNameSpaceURI, sLocalName) { + return oNode.getElementsByTagNameNS(sNameSpaceURI, sLocalName); +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cDynamicContext(oStaticContext, vItem, oScope, oDOMAdapter) { + // + this.staticContext = oStaticContext; + // + this.item = vItem; + // + this.scope = oScope || {}; + this.stack = {}; + // + this.DOMAdapter = oDOMAdapter || new cDOMAdapter; + // + var oDate = new cDate, + nOffset = oDate.getTimezoneOffset(); + this.dateTime = new cXSDateTime(oDate.getFullYear(), oDate.getMonth() + 1, oDate.getDate(), oDate.getHours(), oDate.getMinutes(), oDate.getSeconds() + oDate.getMilliseconds() / 1000, -nOffset); + this.timezone = new cXSDayTimeDuration(0, cMath.abs(~~(nOffset / 60)), cMath.abs(nOffset % 60), 0, nOffset > 0); +}; + +cDynamicContext.prototype.item = null; +cDynamicContext.prototype.position = 0; +cDynamicContext.prototype.size = 0; +// +cDynamicContext.prototype.scope = null; +cDynamicContext.prototype.stack = null; // Variables stack +// +cDynamicContext.prototype.dateTime = null; +cDynamicContext.prototype.timezone = null; +// +cDynamicContext.prototype.staticContext = null; + +// Stack management +cDynamicContext.prototype.pushVariable = function(sName, vValue) { + if (!this.stack.hasOwnProperty(sName)) + this.stack[sName] = []; + this.stack[sName].push(this.scope[sName]); + this.scope[sName] = vValue; +}; + +cDynamicContext.prototype.popVariable = function(sName) { + if (this.stack.hasOwnProperty(sName)) { + this.scope[sName] = this.stack[sName].pop(); + if (!this.stack[sName].length) { + delete this.stack[sName]; + if (typeof this.scope[sName] == "undefined") + delete this.scope[sName]; + } + } +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cStaticContext() { + this.dataTypes = {}; + this.documents = {}; + this.functions = {}; + this.collations = {}; + this.collections= {}; +}; + +cStaticContext.prototype.baseURI = null; +// +cStaticContext.prototype.dataTypes = null; +cStaticContext.prototype.documents = null; +// +cStaticContext.prototype.functions = null; +cStaticContext.prototype.defaultFunctionNamespace = null; +// +cStaticContext.prototype.collations = null; +cStaticContext.prototype.defaultCollationName = sNS_XPF + "/collation/codepoint"; +// +cStaticContext.prototype.collections = null; +// +cStaticContext.prototype.namespaceResolver = null; +cStaticContext.prototype.defaultElementNamespace = null; + +// +var rStaticContext_uri = /^(?:\{([^\}]+)\})?(.+)$/; +// +cStaticContext.prototype.setDataType = function(sUri, fFunction) { + var aMatch = sUri.match(rStaticContext_uri); + if (aMatch) + if (aMatch[1] != sNS_XSD) + this.dataTypes[sUri] = fFunction; +}; + +cStaticContext.prototype.getDataType = function(sUri) { + var aMatch = sUri.match(rStaticContext_uri); + if (aMatch) + return aMatch[1] == sNS_XSD ? hStaticContext_dataTypes[aMatch[2]] : this.dataTypes[sUri]; +}; + +cStaticContext.prototype.setDocument = function(sUri, fFunction) { + this.documents[sUri] = fFunction; +}; + +cStaticContext.prototype.getDocument = function(sUri) { + return this.documents[sUri]; +}; + +cStaticContext.prototype.setFunction = function(sUri, fFunction) { + var aMatch = sUri.match(rStaticContext_uri); + if (aMatch) + if (aMatch[1] != sNS_XPF) + this.functions[sUri] = fFunction; +}; + +cStaticContext.prototype.getFunction = function(sUri) { + var aMatch = sUri.match(rStaticContext_uri); + if (aMatch) + return aMatch[1] == sNS_XPF ? hStaticContext_functions[aMatch[2]] : this.functions[sUri]; +}; + +cStaticContext.prototype.setCollation = function(sUri, fFunction) { + this.collations[sUri] = fFunction; +}; + +cStaticContext.prototype.getCollation = function(sUri) { + return this.collations[sUri]; +}; + +cStaticContext.prototype.setCollection = function(sUri, fFunction) { + this.collections[sUri] = fFunction; +}; + +cStaticContext.prototype.getCollection = function(sUri) { + return this.collections[sUri]; +}; + +cStaticContext.prototype.getURIForPrefix = function(sPrefix) { + var oResolver = this.namespaceResolver, + fResolver = oResolver && oResolver.lookupNamespaceURI ? oResolver.lookupNamespaceURI : oResolver, + sNameSpaceURI; + if (fResolver instanceof cFunction && (sNameSpaceURI = fResolver.call(oResolver, sPrefix))) + return sNameSpaceURI; + if (sPrefix == 'fn') + return sNS_XPF; + if (sPrefix == 'xs') + return sNS_XSD; + if (sPrefix == "xml") + return sNS_XML; + if (sPrefix == "xmlns") + return sNS_XNS; + // + throw new cException("XPST0081" + + ); +}; + +// Static members +//Converts non-null JavaScript object to XML Schema object +cStaticContext.js2xs = function(vItem) { + // Convert types from JavaScript to XPath 2.0 + if (typeof vItem == "boolean") + vItem = new cXSBoolean(vItem); + else + if (typeof vItem == "number") + vItem =(fIsNaN(vItem) ||!fIsFinite(vItem)) ? new cXSDouble(vItem) : fNumericLiteral_parseValue(cString(vItem)); + else + vItem = new cXSString(cString(vItem)); + // + return vItem; +}; + +// Converts non-null XML Schema object to JavaScript object +cStaticContext.xs2js = function(vItem) { + if (vItem instanceof cXSBoolean) + vItem = vItem.valueOf(); + else + if (fXSAnyAtomicType_isNumeric(vItem)) + vItem = vItem.valueOf(); + else + vItem = vItem.toString(); + // + return vItem; +}; + +// System functions with signatures, operators and types +var hStaticContext_functions = {}, + hStaticContext_signatures = {}, + hStaticContext_dataTypes = {}, + hStaticContext_operators = {}; + +function fStaticContext_defineSystemFunction(sName, aParameters, fFunction) { + // Register function + hStaticContext_functions[sName] = fFunction; + // Register signature + hStaticContext_signatures[sName] = aParameters; +}; + +function fStaticContext_defineSystemDataType(sName, fFunction) { + // Register dataType + hStaticContext_dataTypes[sName] = fFunction; +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cExpression(sExpression, oStaticContext) { + var oLexer = new cLexer(sExpression), + oExpr = fExpr_parse(oLexer, oStaticContext); + // + if (!oLexer.eof()) + throw new cException("XPST0003" + + ); + // + if (!oExpr) + throw new cException("XPST0003" + + ); + this.internalExpression = oExpr; +}; + +cExpression.prototype.internalExpression = null; + +// Public methods +cExpression.prototype.evaluate = function(oContext) { + return this.internalExpression.evaluate(oContext); +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cStringCollator() { + +}; + +cStringCollator.prototype.equals = function(sValue1, sValue2) { + throw "Not implemented"; +}; + +cStringCollator.prototype.compare = function(sValue1, sValue2) { + throw "Not implemented"; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSConstants(){}; + +// XML Schema 1.0 Datatypes +cXSConstants.ANYSIMPLETYPE_DT = 1; +cXSConstants.STRING_DT = 2; +cXSConstants.BOOLEAN_DT = 3; +cXSConstants.DECIMAL_DT = 4; +cXSConstants.FLOAT_DT = 5; +cXSConstants.DOUBLE_DT = 6; +cXSConstants.DURATION_DT = 7; +cXSConstants.DATETIME_DT = 8; +cXSConstants.TIME_DT = 9; +cXSConstants.DATE_DT = 10; +cXSConstants.GYEARMONTH_DT = 11; +cXSConstants.GYEAR_DT = 12; +cXSConstants.GMONTHDAY_DT = 13; +cXSConstants.GDAY_DT = 14; +cXSConstants.GMONTH_DT = 15; +cXSConstants.HEXBINARY_DT = 16; +cXSConstants.BASE64BINARY_DT = 17; +cXSConstants.ANYURI_DT = 18; +cXSConstants.QNAME_DT = 19; +cXSConstants.NOTATION_DT = 20; +cXSConstants.NORMALIZEDSTRING_DT = 21; +cXSConstants.TOKEN_DT = 22; +cXSConstants.LANGUAGE_DT = 23; +cXSConstants.NMTOKEN_DT = 24; +cXSConstants.NAME_DT = 25; +cXSConstants.NCNAME_DT = 26; +cXSConstants.ID_DT = 27; +cXSConstants.IDREF_DT = 28; +cXSConstants.ENTITY_DT = 29; +cXSConstants.INTEGER_DT = 30; +cXSConstants.NONPOSITIVEINTEGER_DT = 31; +cXSConstants.NEGATIVEINTEGER_DT = 32; +cXSConstants.LONG_DT = 33; +cXSConstants.INT_DT = 34; +cXSConstants.SHORT_DT = 35; +cXSConstants.BYTE_DT = 36; +cXSConstants.NONNEGATIVEINTEGER_DT = 37; +cXSConstants.UNSIGNEDLONG_DT = 38; +cXSConstants.UNSIGNEDINT_DT = 39; +cXSConstants.UNSIGNEDSHORT_DT = 40; +cXSConstants.UNSIGNEDBYTE_DT = 41; +cXSConstants.POSITIVEINTEGER_DT = 42; +cXSConstants.LISTOFUNION_DT = 43; +cXSConstants.LIST_DT = 44; +cXSConstants.UNAVAILABLE_DT = 45; + +// XML Schema 1.1 Datatypes +cXSConstants.DATETIMESTAMP_DT = 46; +cXSConstants.DAYMONTHDURATION_DT = 47; +cXSConstants.DAYTIMEDURATION_DT = 48; +cXSConstants.PRECISIONDECIMAL_DT = 49; +cXSConstants.ANYATOMICTYPE_DT = 50; +cXSConstants.ANYTYPE_DT = 51; + +// +cXSConstants.XT_YEARMONTHDURATION_DT=-1; +cXSConstants.XT_UNTYPEDATOMIC_DT =-2; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cExpr() { + this.items = []; +}; + +cExpr.prototype.items = null; + +// Static members +function fExpr_parse (oLexer, oStaticContext) { + var oItem; + if (oLexer.eof() ||!(oItem = fExprSingle_parse(oLexer, oStaticContext))) + return; + + // Create expression + var oExpr = new cExpr; + oExpr.items.push(oItem); + while (oLexer.peek() == ',') { + oLexer.next(); + if (oLexer.eof() ||!(oItem = fExprSingle_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + oExpr.items.push(oItem); + } + return oExpr; +}; + +// Public members +cExpr.prototype.evaluate = function(oContext) { + var oSequence = []; + for (var nIndex = 0, nLength = this.items.length; nIndex < nLength; nIndex++) + oSequence = hStaticContext_operators["concatenate"].call(oContext, oSequence, this.items[nIndex].evaluate(oContext)); + return oSequence; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cExprSingle() { + +}; + +// Static members +function fExprSingle_parse (oLexer, oStaticContext) { + if (!oLexer.eof()) + return fIfExpr_parse(oLexer, oStaticContext) + || fForExpr_parse(oLexer, oStaticContext) + || fQuantifiedExpr_parse(oLexer, oStaticContext) + || fOrExpr_parse(oLexer, oStaticContext); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cForExpr() { + this.bindings = []; + this.returnExpr = null; +}; + +cForExpr.prototype.bindings = null; +cForExpr.prototype.returnExpr = null; + +// Static members +function fForExpr_parse (oLexer, oStaticContext) { + if (oLexer.peek() == "for" && oLexer.peek(1).substr(0, 1) == '$') { + oLexer.next(); + + var oForExpr = new cForExpr, + oExpr; + do { + oForExpr.bindings.push(fSimpleForBinding_parse(oLexer, oStaticContext)); + } + while (oLexer.peek() == ',' && oLexer.next()); + + if (oLexer.peek() != "return") + throw new cException("XPST0003" + + ); + + oLexer.next(); + if (oLexer.eof() ||!(oExpr = fExprSingle_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + + oForExpr.returnExpr = oExpr; + return oForExpr; + } +}; + +// Public members +// for $x in X, $y in Y, $z in Z return $x + $y + $z +// for $x in X return for $y in Y return for $z in Z return $x + $y + $z +cForExpr.prototype.evaluate = function (oContext) { + var oSequence = []; + (function(oSelf, nBinding) { + var oBinding = oSelf.bindings[nBinding++], + oSequence1 = oBinding.inExpr.evaluate(oContext), + sUri = (oBinding.namespaceURI ? '{' + oBinding.namespaceURI + '}' : '') + oBinding.localName; + for (var nIndex = 0, nLength = oSequence1.length; nIndex < nLength; nIndex++) { + oContext.pushVariable(sUri, oSequence1[nIndex]); + if (nBinding < oSelf.bindings.length) + arguments.callee(oSelf, nBinding); + else + oSequence = oSequence.concat(oSelf.returnExpr.evaluate(oContext)); + oContext.popVariable(sUri); + } + })(this, 0); + + return oSequence; +}; + +// +function cSimpleForBinding(sPrefix, sLocalName, sNameSpaceURI, oInExpr) { + this.prefix = sPrefix; + this.localName = sLocalName; + this.namespaceURI = sNameSpaceURI; + this.inExpr = oInExpr; +}; + +cSimpleForBinding.prototype.prefix = null; +cSimpleForBinding.prototype.localName = null; +cSimpleForBinding.prototype.namespaceURI = null; +cSimpleForBinding.prototype.inExpr = null; + +function fSimpleForBinding_parse (oLexer, oStaticContext) { + var aMatch = oLexer.peek().substr(1).match(rNameTest); + if (!aMatch) + throw new cException("XPST0003" + + ); + + if (aMatch[1] == '*' || aMatch[2] == '*') + throw new cException("XPST0003" + + ); + + oLexer.next(); + if (oLexer.peek() != "in") + throw new cException("XPST0003" + + ); + + oLexer.next(); + var oExpr; + if (oLexer.eof() ||!(oExpr = fExprSingle_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + + return new cSimpleForBinding(aMatch[1] || null, aMatch[2], aMatch[1] ? oStaticContext.getURIForPrefix(aMatch[1]) : null, oExpr); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cIfExpr(oCondExpr, oThenExpr, oElseExpr) { + this.condExpr = oCondExpr; + this.thenExpr = oThenExpr; + this.elseExpr = oElseExpr; +}; + +cIfExpr.prototype.condExpr = null; +cIfExpr.prototype.thenExpr = null; +cIfExpr.prototype.elseExpr = null; + +// Static members +function fIfExpr_parse (oLexer, oStaticContext) { + var oCondExpr, + oThenExpr, + oElseExpr; + if (oLexer.peek() == "if" && oLexer.peek(1) == '(') { + oLexer.next(2); + // + if (oLexer.eof() ||!(oCondExpr = fExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + // + if (oLexer.peek() != ')') + throw new cException("XPST0003" + + ); + + oLexer.next(); + if (oLexer.peek() != "then") + throw new cException("XPST0003" + + ); + + oLexer.next(); + if (oLexer.eof() ||!(oThenExpr = fExprSingle_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + + if (oLexer.peek() != "else") + throw new cException("XPST0003" + + ); + + oLexer.next(); + if (oLexer.eof() ||!(oElseExpr = fExprSingle_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + // + return new cIfExpr(oCondExpr, oThenExpr, oElseExpr); + } +}; + +// Public members +cIfExpr.prototype.evaluate = function (oContext) { + return this[fFunction_sequence_toEBV(this.condExpr.evaluate(oContext), oContext) ? "thenExpr" : "elseExpr"].evaluate(oContext); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cQuantifiedExpr(sQuantifier) { + this.quantifier = sQuantifier; + this.bindings = []; + this.satisfiesExpr = null; +}; + +cQuantifiedExpr.prototype.bindings = null; +cQuantifiedExpr.prototype.quantifier = null; +cQuantifiedExpr.prototype.satisfiesExpr = null; + +// Static members +function fQuantifiedExpr_parse (oLexer, oStaticContext) { + var sQuantifier = oLexer.peek(); + if ((sQuantifier == "some" || sQuantifier == "every") && oLexer.peek(1).substr(0, 1) == '$') { + oLexer.next(); + + var oQuantifiedExpr = new cQuantifiedExpr(sQuantifier), + oExpr; + do { + oQuantifiedExpr.bindings.push(fSimpleQuantifiedBinding_parse(oLexer, oStaticContext)); + } + while (oLexer.peek() == ',' && oLexer.next()); + + if (oLexer.peek() != "satisfies") + throw new cException("XPST0003" + + ); + + oLexer.next(); + if (oLexer.eof() ||!(oExpr = fExprSingle_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + + oQuantifiedExpr.satisfiesExpr = oExpr; + return oQuantifiedExpr; + } +}; + +// Public members +cQuantifiedExpr.prototype.evaluate = function (oContext) { + // TODO: re-factor + var bEvery = this.quantifier == "every", + bResult = bEvery ? true : false; + (function(oSelf, nBinding) { + var oBinding = oSelf.bindings[nBinding++], + oSequence1 = oBinding.inExpr.evaluate(oContext), + sUri = (oBinding.namespaceURI ? '{' + oBinding.namespaceURI + '}' : '') + oBinding.localName; + for (var nIndex = 0, nLength = oSequence1.length; (nIndex < nLength) && (bEvery ? bResult :!bResult); nIndex++) { + oContext.pushVariable(sUri, oSequence1[nIndex]); + if (nBinding < oSelf.bindings.length) + arguments.callee(oSelf, nBinding); + else + bResult = fFunction_sequence_toEBV(oSelf.satisfiesExpr.evaluate(oContext), oContext); + oContext.popVariable(sUri); + } + })(this, 0); + + return [new cXSBoolean(bResult)]; +}; + + + +// +function cSimpleQuantifiedBinding(sPrefix, sLocalName, sNameSpaceURI, oInExpr) { + this.prefix = sPrefix; + this.localName = sLocalName; + this.namespaceURI = sNameSpaceURI; + this.inExpr = oInExpr; +}; + +cSimpleQuantifiedBinding.prototype.prefix = null; +cSimpleQuantifiedBinding.prototype.localName = null; +cSimpleQuantifiedBinding.prototype.namespaceURI = null; +cSimpleQuantifiedBinding.prototype.inExpr = null; + +function fSimpleQuantifiedBinding_parse (oLexer, oStaticContext) { + var aMatch = oLexer.peek().substr(1).match(rNameTest); + if (!aMatch) + throw new cException("XPST0003" + + ); + + if (aMatch[1] == '*' || aMatch[2] == '*') + throw new cException("XPST0003" + + ); + + oLexer.next(); + if (oLexer.peek() != "in") + throw new cException("XPST0003" + + ); + + oLexer.next(); + var oExpr; + if (oLexer.eof() ||!(oExpr = fExprSingle_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + + return new cSimpleQuantifiedBinding(aMatch[1] || null, aMatch[2], aMatch[1] ? oStaticContext.getURIForPrefix(aMatch[1]) : null, oExpr); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cComparisonExpr(oLeft, oRight, sOperator) { + this.left = oLeft; + this.right = oRight; + this.operator = sOperator; +}; + +cComparisonExpr.prototype.left = null; +cComparisonExpr.prototype.right = null; +cComparisonExpr.prototype.operator = null; + +// Static members +function fComparisonExpr_parse (oLexer, oStaticContext) { + var oExpr, + oRight; + if (oLexer.eof() ||!(oExpr = fRangeExpr_parse(oLexer, oStaticContext))) + return; + if (!(oLexer.peek() in hComparisonExpr_operators)) + return oExpr; + + // Comparison expression + var sOperator = oLexer.peek(); + oLexer.next(); + if (oLexer.eof() ||!(oRight = fRangeExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + return new cComparisonExpr(oExpr, oRight, sOperator); +}; + +// Public members +cComparisonExpr.prototype.evaluate = function (oContext) { + var oResult = hComparisonExpr_operators[this.operator](this, oContext); + return oResult == null ? [] : [oResult]; +}; + +// General comparison +function fComparisonExpr_GeneralComp(oExpr, oContext) { + var oLeft = fFunction_sequence_atomize(oExpr.left.evaluate(oContext), oContext); + if (!oLeft.length) + return new cXSBoolean(false); + + var oRight = fFunction_sequence_atomize(oExpr.right.evaluate(oContext), oContext); + if (!oRight.length) + return new cXSBoolean(false); + + var bResult = false; + for (var nLeftIndex = 0, nLeftLength = oLeft.length, bLeft, vLeft; (nLeftIndex < nLeftLength) &&!bResult; nLeftIndex++) { + for (var nRightIndex = 0, nRightLength = oRight.length, bRight, vRight; (nRightIndex < nRightLength) &&!bResult; nRightIndex++) { + + vLeft = oLeft[nLeftIndex]; + vRight = oRight[nRightIndex]; + + bLeft = vLeft instanceof cXSUntypedAtomic; + bRight = vRight instanceof cXSUntypedAtomic; + + if (bLeft && bRight) { + // cast xs:untypedAtomic to xs:string + vLeft = cXSString.cast(vLeft); + vRight = cXSString.cast(vRight); + } + else { + // + if (bLeft) { + // Special: durations + if (vRight instanceof cXSDayTimeDuration) + vLeft = cXSDayTimeDuration.cast(vLeft); + else + if (vRight instanceof cXSYearMonthDuration) + vLeft = cXSYearMonthDuration.cast(vLeft); + else + // + if (vRight.primitiveKind) + vLeft = hStaticContext_dataTypes[vRight.primitiveKind].cast(vLeft); + } + else + if (bRight) { + // Special: durations + if (vLeft instanceof cXSDayTimeDuration) + vRight = cXSDayTimeDuration.cast(vRight); + else + if (vLeft instanceof cXSYearMonthDuration) + vRight = cXSYearMonthDuration.cast(vRight); + else + // + if (vLeft.primitiveKind) + vRight = hStaticContext_dataTypes[vLeft.primitiveKind].cast(vRight); + } + + // cast xs:anyURI to xs:string + if (vLeft instanceof cXSAnyURI) + vLeft = cXSString.cast(vLeft); + if (vRight instanceof cXSAnyURI) + vRight = cXSString.cast(vRight); + } + + bResult = hComparisonExpr_ValueComp_operators[hComparisonExpr_GeneralComp_map[oExpr.operator]](vLeft, vRight, oContext).valueOf(); + } + } + return new cXSBoolean(bResult); +}; + +var hComparisonExpr_GeneralComp_map = { + '=': 'eq', + '!=': 'ne', + '>': 'gt', + '<': 'lt', + '>=': 'ge', + '<=': 'le' +}; + +// Value comparison +function fComparisonExpr_ValueComp(oExpr, oContext) { + var oLeft = fFunction_sequence_atomize(oExpr.left.evaluate(oContext), oContext); + if (!oLeft.length) + return null; + // Assert cardinality + fFunctionCall_assertSequenceCardinality(oContext, oLeft, '?' + + ); + + var oRight = fFunction_sequence_atomize(oExpr.right.evaluate(oContext), oContext); + if (!oRight.length) + return null; + // Assert cardinality + fFunctionCall_assertSequenceCardinality(oContext, oRight, '?' + + ); + + var vLeft = oLeft[0], + vRight = oRight[0]; + + // cast xs:untypedAtomic to xs:string + if (vLeft instanceof cXSUntypedAtomic) + vLeft = cXSString.cast(vLeft); + if (vRight instanceof cXSUntypedAtomic) + vRight = cXSString.cast(vRight); + + // cast xs:anyURI to xs:string + if (vLeft instanceof cXSAnyURI) + vLeft = cXSString.cast(vLeft); + if (vRight instanceof cXSAnyURI) + vRight = cXSString.cast(vRight); + + // + return hComparisonExpr_ValueComp_operators[oExpr.operator](vLeft, vRight, oContext); +}; + +// +var hComparisonExpr_ValueComp_operators = {}; +hComparisonExpr_ValueComp_operators['eq'] = function(oLeft, oRight, oContext) { + var sOperator = ''; + + if (fXSAnyAtomicType_isNumeric(oLeft)) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "numeric-equal"; + } + else + if (oLeft instanceof cXSBoolean) { + if (oRight instanceof cXSBoolean) + sOperator = "boolean-equal"; + } + else + if (oLeft instanceof cXSString) { + if (oRight instanceof cXSString) + return hStaticContext_operators["numeric-equal"].call(oContext, hStaticContext_functions["compare"].call(oContext, oLeft, oRight), new cXSInteger(0)); + } + else + if (oLeft instanceof cXSDate) { + if (oRight instanceof cXSDate) + sOperator = "date-equal"; + } + else + if (oLeft instanceof cXSTime) { + if (oRight instanceof cXSTime) + sOperator = "time-equal"; + } + else + if (oLeft instanceof cXSDateTime) { + if (oRight instanceof cXSDateTime) + sOperator = "dateTime-equal"; + } + else + if (oLeft instanceof cXSDuration) { + if (oRight instanceof cXSDuration) + sOperator = "duration-equal"; + } + else + if (oLeft instanceof cXSGYearMonth) { + if (oRight instanceof cXSGYearMonth) + sOperator = "gYearMonth-equal"; + } + else + if (oLeft instanceof cXSGYear) { + if (oRight instanceof cXSGYear) + sOperator = "gYear-equal"; + } + else + if (oLeft instanceof cXSGMonthDay) { + if (oRight instanceof cXSGMonthDay) + sOperator = "gMonthDay-equal"; + } + else + if (oLeft instanceof cXSGMonth) { + if (oRight instanceof cXSGMonth) + sOperator = "gMonth-equal"; + } + else + if (oLeft instanceof cXSGDay) { + if (oRight instanceof cXSGDay) + sOperator = "gDay-equal"; + } + // skipped: xs:anyURI (covered by xs:string) + else + if (oLeft instanceof cXSQName) { + if (oRight instanceof cXSQName) + sOperator = "QName-equal"; + } + else + if (oLeft instanceof cXSHexBinary) { + if (oRight instanceof cXSHexBinary) + sOperator = "hexBinary-equal"; + } + else + if (oLeft instanceof cXSBase64Binary) { + if (oRight instanceof cXSBase64Binary) + sOperator = "base64Binary-equal"; + } + + // Call operator function + if (sOperator) + return hStaticContext_operators[sOperator].call(oContext, oLeft, oRight); + + // skipped: xs:NOTATION + throw new cException("XPTY0004" + + ); // Cannot compare {type1} to {type2} +}; +hComparisonExpr_ValueComp_operators['ne'] = function(oLeft, oRight, oContext) { + return new cXSBoolean(!hComparisonExpr_ValueComp_operators['eq'](oLeft, oRight, oContext).valueOf()); +}; +hComparisonExpr_ValueComp_operators['gt'] = function(oLeft, oRight, oContext) { + var sOperator = ''; + + if (fXSAnyAtomicType_isNumeric(oLeft)) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "numeric-greater-than"; + } + else + if (oLeft instanceof cXSBoolean) { + if (oRight instanceof cXSBoolean) + sOperator = "boolean-greater-than"; + } + else + if (oLeft instanceof cXSString) { + if (oRight instanceof cXSString) + return hStaticContext_operators["numeric-greater-than"].call(oContext, hStaticContext_functions["compare"].call(oContext, oLeft, oRight), new cXSInteger(0)); + } + else + if (oLeft instanceof cXSDate) { + if (oRight instanceof cXSDate) + sOperator = "date-greater-than"; + } + else + if (oLeft instanceof cXSTime) { + if (oRight instanceof cXSTime) + sOperator = "time-greater-than"; + } + else + if (oLeft instanceof cXSDateTime) { + if (oRight instanceof cXSDateTime) + sOperator = "dateTime-greater-than"; + } + else + if (oLeft instanceof cXSYearMonthDuration) { + if (oRight instanceof cXSYearMonthDuration) + sOperator = "yearMonthDuration-greater-than"; + } + else + if (oLeft instanceof cXSDayTimeDuration) { + if (oRight instanceof cXSDayTimeDuration) + sOperator = "dayTimeDuration-greater-than"; + } + + // Call operator function + if (sOperator) + return hStaticContext_operators[sOperator].call(oContext, oLeft, oRight); + + // skipped: xs:anyURI (covered by xs:string) + throw new cException("XPTY0004" + + ); // Cannot compare {type1} to {type2} +}; +hComparisonExpr_ValueComp_operators['lt'] = function(oLeft, oRight, oContext) { + var sOperator = ''; + + if (fXSAnyAtomicType_isNumeric(oLeft)) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "numeric-less-than"; + } + else + if (oLeft instanceof cXSBoolean) { + if (oRight instanceof cXSBoolean) + sOperator = "boolean-less-than"; + } + else + if (oLeft instanceof cXSString) { + if (oRight instanceof cXSString) + return hStaticContext_operators["numeric-less-than"].call(oContext, hStaticContext_functions["compare"].call(oContext, oLeft, oRight), new cXSInteger(0)); + } + else + if (oLeft instanceof cXSDate) { + if (oRight instanceof cXSDate) + sOperator = "date-less-than"; + } + else + if (oLeft instanceof cXSTime) { + if (oRight instanceof cXSTime) + sOperator = "time-less-than"; + } + else + if (oLeft instanceof cXSDateTime) { + if (oRight instanceof cXSDateTime) + sOperator = "dateTime-less-than"; + } + else + if (oLeft instanceof cXSYearMonthDuration) { + if (oRight instanceof cXSYearMonthDuration) + sOperator = "yearMonthDuration-less-than"; + } + else + if (oLeft instanceof cXSDayTimeDuration) { + if (oRight instanceof cXSDayTimeDuration) + sOperator = "dayTimeDuration-less-than"; + } + + // Call operator function + if (sOperator) + return hStaticContext_operators[sOperator].call(oContext, oLeft, oRight); + + // skipped: xs:anyURI (covered by xs:string) + throw new cException("XPTY0004" + + ); // Cannot compare {type1} to {type2} +}; +hComparisonExpr_ValueComp_operators['ge'] = function(oLeft, oRight, oContext) { + var sOperator = ''; + + if (fXSAnyAtomicType_isNumeric(oLeft)) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "numeric-less-than"; + } + else + if (oLeft instanceof cXSBoolean) { + if (oRight instanceof cXSBoolean) + sOperator = "boolean-less-than"; + } + else + if (oLeft instanceof cXSString) { + if (oRight instanceof cXSString) + return hStaticContext_operators["numeric-greater-than"].call(oContext, hStaticContext_functions["compare"].call(oContext, oLeft, oRight), new cXSInteger(-1)); + } + else + if (oLeft instanceof cXSDate) { + if (oRight instanceof cXSDate) + sOperator = "date-less-than"; + } + else + if (oLeft instanceof cXSTime) { + if (oRight instanceof cXSTime) + sOperator = "time-less-than"; + } + else + if (oLeft instanceof cXSDateTime) { + if (oRight instanceof cXSDateTime) + sOperator = "dateTime-less-than"; + } + else + if (oLeft instanceof cXSYearMonthDuration) { + if (oRight instanceof cXSYearMonthDuration) + sOperator = "yearMonthDuration-less-than"; + } + else + if (oLeft instanceof cXSDayTimeDuration) { + if (oRight instanceof cXSDayTimeDuration) + sOperator = "dayTimeDuration-less-than"; + } + + // Call operator function + if (sOperator) + return new cXSBoolean(!hStaticContext_operators[sOperator].call(oContext, oLeft, oRight).valueOf()); + + // skipped: xs:anyURI (covered by xs:string) + throw new cException("XPTY0004" + + ); // Cannot compare {type1} to {type2} +}; +hComparisonExpr_ValueComp_operators['le'] = function(oLeft, oRight, oContext) { + var sOperator = ''; + + if (fXSAnyAtomicType_isNumeric(oLeft)) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "numeric-greater-than"; + } + else + if (oLeft instanceof cXSBoolean) { + if (oRight instanceof cXSBoolean) + sOperator = "boolean-greater-than"; + } + else + if (oLeft instanceof cXSString) { + if (oRight instanceof cXSString) + return hStaticContext_operators["numeric-less-than"].call(oContext, hStaticContext_functions["compare"].call(oContext, oLeft, oRight), new cXSInteger(1)); + } + else + if (oLeft instanceof cXSDate) { + if (oRight instanceof cXSDate) + sOperator = "date-greater-than"; + } + else + if (oLeft instanceof cXSTime) { + if (oRight instanceof cXSTime) + sOperator = "time-greater-than"; + } + else + if (oLeft instanceof cXSDateTime) { + if (oRight instanceof cXSDateTime) + sOperator = "dateTime-greater-than"; + } + else + if (oLeft instanceof cXSYearMonthDuration) { + if (oRight instanceof cXSYearMonthDuration) + sOperator = "yearMonthDuration-greater-than"; + } + else + if (oLeft instanceof cXSDayTimeDuration) { + if (oRight instanceof cXSDayTimeDuration) + sOperator = "dayTimeDuration-greater-than"; + } + + // Call operator function + if (sOperator) + return new cXSBoolean(!hStaticContext_operators[sOperator].call(oContext, oLeft, oRight).valueOf()); + + // skipped: xs:anyURI (covered by xs:string) + throw new cException("XPTY0004" + + ); // Cannot compare {type1} to {type2} +}; + +// Node comparison +function fComparisonExpr_NodeComp(oExpr, oContext) { + var oLeft = oExpr.left.evaluate(oContext); + if (!oLeft.length) + return null; + // Assert cardinality + fFunctionCall_assertSequenceCardinality(oContext, oLeft, '?' + + ); + // Assert item type + fFunctionCall_assertSequenceItemType(oContext, oLeft, cXTNode + + ); + + var oRight = oExpr.right.evaluate(oContext); + if (!oRight.length) + return null; + // Assert cardinality + fFunctionCall_assertSequenceCardinality(oContext, oRight, '?' + + ); + // Assert item type + fFunctionCall_assertSequenceItemType(oContext, oRight, cXTNode + + ); + + return hComparisonExpr_NodeComp_operators[oExpr.operator](oLeft[0], oRight[0], oContext); +}; + +var hComparisonExpr_NodeComp_operators = {}; +hComparisonExpr_NodeComp_operators['is'] = function(oLeft, oRight, oContext) { + return hStaticContext_operators["is-same-node"].call(oContext, oLeft, oRight); +}; +hComparisonExpr_NodeComp_operators['>>'] = function(oLeft, oRight, oContext) { + return hStaticContext_operators["node-after"].call(oContext, oLeft, oRight); +}; +hComparisonExpr_NodeComp_operators['<<'] = function(oLeft, oRight, oContext) { + return hStaticContext_operators["node-before"].call(oContext, oLeft, oRight); +}; + +// Operators +var hComparisonExpr_operators = { + // GeneralComp + '=': fComparisonExpr_GeneralComp, + '!=': fComparisonExpr_GeneralComp, + '<': fComparisonExpr_GeneralComp, + '<=': fComparisonExpr_GeneralComp, + '>': fComparisonExpr_GeneralComp, + '>=': fComparisonExpr_GeneralComp, + // ValueComp + 'eq': fComparisonExpr_ValueComp, + 'ne': fComparisonExpr_ValueComp, + 'lt': fComparisonExpr_ValueComp, + 'le': fComparisonExpr_ValueComp, + 'gt': fComparisonExpr_ValueComp, + 'ge': fComparisonExpr_ValueComp, + // NodeComp + 'is': fComparisonExpr_NodeComp, + '>>': fComparisonExpr_NodeComp, + '<<': fComparisonExpr_NodeComp +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cAdditiveExpr(oExpr) { + this.left = oExpr; + this.items = []; +}; + +cAdditiveExpr.prototype.left = null; +cAdditiveExpr.prototype.items = null; + +// +var hAdditiveExpr_operators = {}; +hAdditiveExpr_operators['+'] = function(oLeft, oRight, oContext) { + var sOperator = '', + bReverse = false; + + if (fXSAnyAtomicType_isNumeric(oLeft)) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "numeric-add"; + } + else + if (oLeft instanceof cXSDate) { + if (oRight instanceof cXSYearMonthDuration) + sOperator = "add-yearMonthDuration-to-date"; + else + if (oRight instanceof cXSDayTimeDuration) + sOperator = "add-dayTimeDuration-to-date"; + } + else + if (oLeft instanceof cXSYearMonthDuration) { + if (oRight instanceof cXSDate) { + sOperator = "add-yearMonthDuration-to-date"; + bReverse = true; + } + else + if (oRight instanceof cXSDateTime) { + sOperator = "add-yearMonthDuration-to-dateTime"; + bReverse = true; + } + else + if (oRight instanceof cXSYearMonthDuration) + sOperator = "add-yearMonthDurations"; + } + else + if (oLeft instanceof cXSDayTimeDuration) { + if (oRight instanceof cXSDate) { + sOperator = "add-dayTimeDuration-to-date"; + bReverse = true; + } + else + if (oRight instanceof cXSTime) { + sOperator = "add-dayTimeDuration-to-time"; + bReverse = true; + } + else + if (oRight instanceof cXSDateTime) { + sOperator = "add-dayTimeDuration-to-dateTime"; + bReverse = true; + } + else + if (oRight instanceof cXSDayTimeDuration) + sOperator = "add-dayTimeDurations"; + } + else + if (oLeft instanceof cXSTime) { + if (oRight instanceof cXSDayTimeDuration) + sOperator = "add-dayTimeDuration-to-time"; + } + else + if (oLeft instanceof cXSDateTime) { + if (oRight instanceof cXSYearMonthDuration) + sOperator = "add-yearMonthDuration-to-dateTime"; + else + if (oRight instanceof cXSDayTimeDuration) + sOperator = "add-dayTimeDuration-to-dateTime"; + } + + // Call operator function + if (sOperator) + return hStaticContext_operators[sOperator].call(oContext, bReverse ? oRight : oLeft, bReverse ? oLeft : oRight); + + // + throw new cException("XPTY0004" + + ); // Arithmetic operator is not defined for arguments of types ({type1}, {type2}) +}; +hAdditiveExpr_operators['-'] = function (oLeft, oRight, oContext) { + var sOperator = ''; + + if (fXSAnyAtomicType_isNumeric(oLeft)) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "numeric-subtract"; + } + else + if (oLeft instanceof cXSDate) { + if (oRight instanceof cXSDate) + sOperator = "subtract-dates"; + else + if (oRight instanceof cXSYearMonthDuration) + sOperator = "subtract-yearMonthDuration-from-date"; + else + if (oRight instanceof cXSDayTimeDuration) + sOperator = "subtract-dayTimeDuration-from-date"; + } + else + if (oLeft instanceof cXSTime) { + if (oRight instanceof cXSTime) + sOperator = "subtract-times"; + else + if (oRight instanceof cXSDayTimeDuration) + sOperator = "subtract-dayTimeDuration-from-time"; + } + else + if (oLeft instanceof cXSDateTime) { + if (oRight instanceof cXSDateTime) + sOperator = "subtract-dateTimes"; + else + if (oRight instanceof cXSYearMonthDuration) + sOperator = "subtract-yearMonthDuration-from-dateTime"; + else + if (oRight instanceof cXSDayTimeDuration) + sOperator = "subtract-dayTimeDuration-from-dateTime"; + } + else + if (oLeft instanceof cXSYearMonthDuration) { + if (oRight instanceof cXSYearMonthDuration) + sOperator = "subtract-yearMonthDurations"; + } + else + if (oLeft instanceof cXSDayTimeDuration) { + if (oRight instanceof cXSDayTimeDuration) + sOperator = "subtract-dayTimeDurations"; + } + + // Call operator function + if (sOperator) + return hStaticContext_operators[sOperator].call(oContext, oLeft, oRight); + + // + throw new cException("XPTY0004" + + ); // Arithmetic operator is not defined for arguments of types ({type1}, {type2}) +}; + +// Static members +function fAdditiveExpr_parse (oLexer, oStaticContext) { + var oExpr; + if (oLexer.eof() ||!(oExpr = fMultiplicativeExpr_parse(oLexer, oStaticContext))) + return; + if (!(oLexer.peek() in hAdditiveExpr_operators)) + return oExpr; + + // Additive expression + var oAdditiveExpr = new cAdditiveExpr(oExpr), + sOperator; + while ((sOperator = oLexer.peek()) in hAdditiveExpr_operators) { + oLexer.next(); + if (oLexer.eof() ||!(oExpr = fMultiplicativeExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + oAdditiveExpr.items.push([sOperator, oExpr]); + } + return oAdditiveExpr; +}; + +// Public members +cAdditiveExpr.prototype.evaluate = function (oContext) { + var oLeft = fFunction_sequence_atomize(this.left.evaluate(oContext), oContext); + + if (!oLeft.length) + return []; + // Assert cardinality + fFunctionCall_assertSequenceCardinality(oContext, oLeft, '?' + + ); + + var vLeft = oLeft[0]; + if (vLeft instanceof cXSUntypedAtomic) + vLeft = cXSDouble.cast(vLeft); // cast to xs:double + + for (var nIndex = 0, nLength = this.items.length, oRight, vRight; nIndex < nLength; nIndex++) { + oRight = fFunction_sequence_atomize(this.items[nIndex][1].evaluate(oContext), oContext); + + if (!oRight.length) + return []; + // Assert cardinality + fFunctionCall_assertSequenceCardinality(oContext, oRight, '?' + + ); + + vRight = oRight[0]; + if (vRight instanceof cXSUntypedAtomic) + vRight = cXSDouble.cast(vRight); // cast to xs:double + + vLeft = hAdditiveExpr_operators[this.items[nIndex][0]](vLeft, vRight, oContext); + } + return [vLeft]; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cMultiplicativeExpr(oExpr) { + this.left = oExpr; + this.items = []; +}; + +cMultiplicativeExpr.prototype.left = null; +cMultiplicativeExpr.prototype.items = null; + +// +var hMultiplicativeExpr_operators = {}; +hMultiplicativeExpr_operators['*'] = function (oLeft, oRight, oContext) { + var sOperator = '', + bReverse = false; + + if (fXSAnyAtomicType_isNumeric(oLeft)) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "numeric-multiply"; + else + if (oRight instanceof cXSYearMonthDuration) { + sOperator = "multiply-yearMonthDuration"; + bReverse = true; + } + else + if (oRight instanceof cXSDayTimeDuration) { + sOperator = "multiply-dayTimeDuration"; + bReverse = true; + } + } + else { + if (oLeft instanceof cXSYearMonthDuration) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "multiply-yearMonthDuration"; + } + else + if (oLeft instanceof cXSDayTimeDuration) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "multiply-dayTimeDuration"; + } + } + + // Call operator function + if (sOperator) + return hStaticContext_operators[sOperator].call(oContext, bReverse ? oRight : oLeft, bReverse ? oLeft : oRight); + + // + throw new cException("XPTY0004" + + ); // Arithmetic operator is not defined for arguments of types ({type1}, {type2}) +}; +hMultiplicativeExpr_operators['div'] = function (oLeft, oRight, oContext) { + var sOperator = ''; + + if (fXSAnyAtomicType_isNumeric(oLeft)) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "numeric-divide"; + } + else + if (oLeft instanceof cXSYearMonthDuration) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "divide-yearMonthDuration"; + else + if (oRight instanceof cXSYearMonthDuration) + sOperator = "divide-yearMonthDuration-by-yearMonthDuration"; + } + else + if (oLeft instanceof cXSDayTimeDuration) { + if (fXSAnyAtomicType_isNumeric(oRight)) + sOperator = "divide-dayTimeDuration"; + else + if (oRight instanceof cXSDayTimeDuration) + sOperator = "divide-dayTimeDuration-by-dayTimeDuration"; + } + // Call operator function + if (sOperator) + return hStaticContext_operators[sOperator].call(oContext, oLeft, oRight); + + // + throw new cException("XPTY0004" + + ); // Arithmetic operator is not defined for arguments of types ({type1}, {type2}) +}; +hMultiplicativeExpr_operators['idiv'] = function (oLeft, oRight, oContext) { + if (fXSAnyAtomicType_isNumeric(oLeft) && fXSAnyAtomicType_isNumeric(oRight)) + return hStaticContext_operators["numeric-integer-divide"].call(oContext, oLeft, oRight); + // + throw new cException("XPTY0004" + + ); // Arithmetic operator is not defined for arguments of types ({type1}, {type2}) +}; +hMultiplicativeExpr_operators['mod'] = function (oLeft, oRight, oContext) { + if (fXSAnyAtomicType_isNumeric(oLeft) && fXSAnyAtomicType_isNumeric(oRight)) + return hStaticContext_operators["numeric-mod"].call(oContext, oLeft, oRight); + // + throw new cException("XPTY0004" + + ); // Arithmetic operator is not defined for arguments of types ({type1}, {type2}) +}; + +// Static members +function fMultiplicativeExpr_parse (oLexer, oStaticContext) { + var oExpr; + if (oLexer.eof() ||!(oExpr = fUnionExpr_parse(oLexer, oStaticContext))) + return; + if (!(oLexer.peek() in hMultiplicativeExpr_operators)) + return oExpr; + + // Additive expression + var oMultiplicativeExpr = new cMultiplicativeExpr(oExpr), + sOperator; + while ((sOperator = oLexer.peek()) in hMultiplicativeExpr_operators) { + oLexer.next(); + if (oLexer.eof() ||!(oExpr = fUnionExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + oMultiplicativeExpr.items.push([sOperator, oExpr]); + } + return oMultiplicativeExpr; +}; + +// Public members +cMultiplicativeExpr.prototype.evaluate = function (oContext) { + var oLeft = fFunction_sequence_atomize(this.left.evaluate(oContext), oContext); + + // + if (!oLeft.length) + return []; + // Assert cardinality + fFunctionCall_assertSequenceCardinality(oContext, oLeft, '?' + + ); + + var vLeft = oLeft[0]; + if (vLeft instanceof cXSUntypedAtomic) + vLeft = cXSDouble.cast(vLeft); // cast to xs:double + + for (var nIndex = 0, nLength = this.items.length, oRight, vRight; nIndex < nLength; nIndex++) { + oRight = fFunction_sequence_atomize(this.items[nIndex][1].evaluate(oContext), oContext); + + if (!oRight.length) + return []; + // Assert cardinality + fFunctionCall_assertSequenceCardinality(oContext, oRight, '?' + + ); + + vRight = oRight[0]; + if (vRight instanceof cXSUntypedAtomic) + vRight = cXSDouble.cast(vRight); // cast to xs:double + + vLeft = hMultiplicativeExpr_operators[this.items[nIndex][0]](vLeft, vRight, oContext); + } + return [vLeft]; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cUnaryExpr(sOperator, oExpr) { + this.operator = sOperator; + this.expression = oExpr; +}; + +cUnaryExpr.prototype.operator = null; +cUnaryExpr.prototype.expression = null; + +// +var hUnaryExpr_operators = {}; +hUnaryExpr_operators['-'] = function(oRight, oContext) { + if (fXSAnyAtomicType_isNumeric(oRight)) + return hStaticContext_operators["numeric-unary-minus"].call(oContext, oRight); + // + throw new cException("XPTY0004" + + ); // Arithmetic operator is not defined for arguments of types ({type1}, {type2}) +}; +hUnaryExpr_operators['+'] = function(oRight, oContext) { + if (fXSAnyAtomicType_isNumeric(oRight)) + return hStaticContext_operators["numeric-unary-plus"].call(oContext, oRight); + // + throw new cException("XPTY0004" + + ); // Arithmetic operator is not defined for arguments of types ({type1}, {type2}) +}; + +// Static members +// UnaryExpr := ("-" | "+")* ValueExpr +function fUnaryExpr_parse (oLexer, oStaticContext) { + if (oLexer.eof()) + return; + if (!(oLexer.peek() in hUnaryExpr_operators)) + return fValueExpr_parse(oLexer, oStaticContext); + + // Unary expression + var sOperator = '+', + oExpr; + while (oLexer.peek() in hUnaryExpr_operators) { + if (oLexer.peek() == '-') + sOperator = sOperator == '-' ? '+' : '-'; + oLexer.next(); + } + if (oLexer.eof() ||!(oExpr = fValueExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + return new cUnaryExpr(sOperator, oExpr); +}; + +cUnaryExpr.prototype.evaluate = function (oContext) { + var oRight = fFunction_sequence_atomize(this.expression.evaluate(oContext), oContext); + + // + if (!oRight.length) + return []; + // Assert cardinality + fFunctionCall_assertSequenceCardinality(oContext, oRight, '?' + + ); + + var vRight = oRight[0]; + if (vRight instanceof cXSUntypedAtomic) + vRight = cXSDouble.cast(vRight); // cast to xs:double + + return [hUnaryExpr_operators[this.operator](vRight, oContext)]; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cValueExpr() { + +}; + +// Static members +function fValueExpr_parse (oLexer, oStaticContext) { + return fPathExpr_parse(oLexer, oStaticContext); +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cOrExpr(oExpr) { + this.left = oExpr; + this.items = []; +}; + +cOrExpr.prototype.left = null; +cOrExpr.prototype.items = null; + +// Static members +function fOrExpr_parse (oLexer, oStaticContext) { + var oExpr; + if (oLexer.eof() ||!(oExpr = fAndExpr_parse(oLexer, oStaticContext))) + return; + if (oLexer.peek() != "or") + return oExpr; + + // Or expression + var oOrExpr = new cOrExpr(oExpr); + while (oLexer.peek() == "or") { + oLexer.next(); + if (oLexer.eof() ||!(oExpr = fAndExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + oOrExpr.items.push(oExpr); + } + return oOrExpr; +}; + +// Public members +cOrExpr.prototype.evaluate = function (oContext) { + var bValue = fFunction_sequence_toEBV(this.left.evaluate(oContext), oContext); + for (var nIndex = 0, nLength = this.items.length; (nIndex < nLength) && !bValue; nIndex++) + bValue = fFunction_sequence_toEBV(this.items[nIndex].evaluate(oContext), oContext); + return [new cXSBoolean(bValue)]; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cAndExpr(oExpr) { + this.left = oExpr; + this.items = []; +}; + +cAndExpr.prototype.left = null; +cAndExpr.prototype.items = null; + +// Static members +function fAndExpr_parse (oLexer, oStaticContext) { + var oExpr; + if (oLexer.eof() ||!(oExpr = fComparisonExpr_parse(oLexer, oStaticContext))) + return; + if (oLexer.peek() != "and") + return oExpr; + + // And expression + var oAndExpr = new cAndExpr(oExpr); + while (oLexer.peek() == "and") { + oLexer.next(); + if (oLexer.eof() ||!(oExpr = fComparisonExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + oAndExpr.items.push(oExpr); + } + return oAndExpr; +}; + +// Public members +cAndExpr.prototype.evaluate = function (oContext) { + var bValue = fFunction_sequence_toEBV(this.left.evaluate(oContext), oContext); + for (var nIndex = 0, nLength = this.items.length; (nIndex < nLength) && bValue; nIndex++) + bValue = fFunction_sequence_toEBV(this.items[nIndex].evaluate(oContext), oContext); + return [new cXSBoolean(bValue)]; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cStepExpr() { + +}; + +cStepExpr.prototype.predicates = null; + +// Static members +function fStepExpr_parse (oLexer, oStaticContext) { + if (!oLexer.eof()) + return fFilterExpr_parse(oLexer, oStaticContext) + || fAxisStep_parse(oLexer, oStaticContext); +}; + +function fStepExpr_parsePredicates (oLexer, oStaticContext, oStep) { + var oExpr; + // Parse predicates + while (oLexer.peek() == '[') { + oLexer.next(); + + if (oLexer.eof() ||!(oExpr = fExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + + oStep.predicates.push(oExpr); + + if (oLexer.peek() != ']') + throw new cException("XPST0003" + + ); + + oLexer.next(); + } +}; + +// Public members +cStepExpr.prototype.applyPredicates = function(oSequence, oContext) { + var vContextItem = oContext.item, + nContextPosition= oContext.position, + nContextSize = oContext.size; + // + for (var nPredicateIndex = 0, oSequence1, nPredicateLength = this.predicates.length; nPredicateIndex < nPredicateLength; nPredicateIndex++) { + oSequence1 = oSequence; + oSequence = []; + for (var nIndex = 0, oSequence2, nLength = oSequence1.length; nIndex < nLength; nIndex++) { + // Set new context + oContext.item = oSequence1[nIndex]; + oContext.position = nIndex + 1; + oContext.size = nLength; + // + oSequence2 = this.predicates[nPredicateIndex].evaluate(oContext); + // + if (oSequence2.length == 1 && fXSAnyAtomicType_isNumeric(oSequence2[0])) { + if (oSequence2[0].valueOf() == nIndex + 1) + oSequence.push(oSequence1[nIndex]); + } + else + if (fFunction_sequence_toEBV(oSequence2, oContext)) + oSequence.push(oSequence1[nIndex]); + } + } + // Restore context + oContext.item = vContextItem; + oContext.position = nContextPosition; + oContext.size = nContextSize; + // + return oSequence; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cAxisStep(sAxis, oTest) { + this.axis = sAxis; + this.test = oTest; + this.predicates = []; +}; + +cAxisStep.prototype = new cStepExpr; + +cAxisStep.prototype.axis = null; +cAxisStep.prototype.test = null; + +// +var hAxisStep_axises = {}; +// Forward axis +hAxisStep_axises["attribute"] = {}; +hAxisStep_axises["child"] = {}; +hAxisStep_axises["descendant"] = {}; +hAxisStep_axises["descendant-or-self"] = {}; +hAxisStep_axises["following"] = {}; +hAxisStep_axises["following-sibling"] = {}; +hAxisStep_axises["self"] = {}; +// hAxisStep_axises["namespace"] = {}; // deprecated in 2.0 +// Reverse axis +hAxisStep_axises["ancestor"] = {}; +hAxisStep_axises["ancestor-or-self"] = {}; +hAxisStep_axises["parent"] = {}; +hAxisStep_axises["preceding"] = {}; +hAxisStep_axises["preceding-sibling"] = {}; + +// Static members +function fAxisStep_parse (oLexer, oStaticContext) { + var sAxis = oLexer.peek(), + oExpr, + oStep; + if (oLexer.peek(1) == '::') { + if (!(sAxis in hAxisStep_axises)) + throw new cException("XPST0003" + + ); + + oLexer.next(2); + if (oLexer.eof() ||!(oExpr = fNodeTest_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + // + oStep = new cAxisStep(sAxis, oExpr); + } + else + if (sAxis == '..') { + oLexer.next(); + oStep = new cAxisStep("parent", new cKindTest("node")); + } + else + if (sAxis == '@') { + oLexer.next(); + if (oLexer.eof() ||!(oExpr = fNodeTest_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + // + oStep = new cAxisStep("attribute", oExpr); + } + else { + if (oLexer.eof() ||!(oExpr = fNodeTest_parse(oLexer, oStaticContext))) + return; + oStep = new cAxisStep(oExpr instanceof cKindTest && oExpr.name == "attribute" ? "attribute" : "child", oExpr); + } + // + fStepExpr_parsePredicates(oLexer, oStaticContext, oStep); + + return oStep; +}; + +// Public members +cAxisStep.prototype.evaluate = function (oContext) { + var oItem = oContext.item; + + if (!oContext.DOMAdapter.isNode(oItem)) + throw new cException("XPTY0020"); + + var oSequence = [], + fGetProperty= oContext.DOMAdapter.getProperty, + nType = fGetProperty(oItem, "nodeType"); + + switch (this.axis) { + // Forward axis + case "attribute": + if (nType == 1) + for (var aAttributes = fGetProperty(oItem, "attributes"), nIndex = 0, nLength = aAttributes.length; nIndex < nLength; nIndex++) + oSequence.push(aAttributes[nIndex]); + break; + + case "child": + for (var oNode = fGetProperty(oItem, "firstChild"); oNode; oNode = fGetProperty(oNode, "nextSibling")) + oSequence.push(oNode); + break; + + case "descendant-or-self": + oSequence.push(oItem); + // No break left intentionally + case "descendant": + fAxisStep_getChildrenForward(fGetProperty(oItem, "firstChild"), oSequence, fGetProperty); + break; + + case "following": + // TODO: Attribute node context + for (var oParent = oItem, oSibling; oParent; oParent = fGetProperty(oParent, "parentNode")) + if (oSibling = fGetProperty(oParent, "nextSibling")) + fAxisStep_getChildrenForward(oSibling, oSequence, fGetProperty); + break; + + case "following-sibling": + for (var oNode = oItem; oNode = fGetProperty(oNode, "nextSibling");) + oSequence.push(oNode); + break; + + case "self": + oSequence.push(oItem); + break; + + // Reverse axis + case "ancestor-or-self": + oSequence.push(oItem); + // No break left intentionally + case "ancestor": + for (var oNode = nType == 2 ? fGetProperty(oItem, "ownerElement") : oItem; oNode = fGetProperty(oNode, "parentNode");) + oSequence.push(oNode); + break; + + case "parent": + var oParent = nType == 2 ? fGetProperty(oItem, "ownerElement") : fGetProperty(oItem, "parentNode"); + if (oParent) + oSequence.push(oParent); + break; + + case "preceding": + // TODO: Attribute node context + for (var oParent = oItem, oSibling; oParent; oParent = fGetProperty(oParent, "parentNode")) + if (oSibling = fGetProperty(oParent, "previousSibling")) + fAxisStep_getChildrenBackward(oSibling, oSequence, fGetProperty); + break; + + case "preceding-sibling": + for (var oNode = oItem; oNode = fGetProperty(oNode, "previousSibling");) + oSequence.push(oNode); + break; + } + + // Apply test + if (oSequence.length && !(this.test instanceof cKindTest && this.test.name == "node")) { + var oSequence1 = oSequence; + oSequence = []; + for (var nIndex = 0, nLength = oSequence1.length; nIndex < nLength; nIndex++) { + if (this.test.test(oSequence1[nIndex], oContext)) + oSequence.push(oSequence1[nIndex]); + } + } + + // Apply predicates + if (oSequence.length && this.predicates.length) + oSequence = this.applyPredicates(oSequence, oContext); + + // Reverse results if reverse axis + switch (this.axis) { + case "ancestor": + case "ancestor-or-self": + case "parent": + case "preceding": + case "preceding-sibling": + oSequence.reverse(); + } + + return oSequence; +}; + +// +function fAxisStep_getChildrenForward(oNode, oSequence, fGetProperty) { + for (var oChild; oNode; oNode = fGetProperty(oNode, "nextSibling")) { + oSequence.push(oNode); + if (oChild = fGetProperty(oNode, "firstChild")) + fAxisStep_getChildrenForward(oChild, oSequence, fGetProperty); + } +}; + +function fAxisStep_getChildrenBackward(oNode, oSequence, fGetProperty) { + for (var oChild; oNode; oNode = fGetProperty(oNode, "previousSibling")) { + if (oChild = fGetProperty(oNode, "lastChild")) + fAxisStep_getChildrenBackward(oChild, oSequence, fGetProperty); + oSequence.push(oNode); + } +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cPathExpr() { + this.items = []; +}; + +cPathExpr.prototype.items = null; + +// Static members +function fPathExpr_parse (oLexer, oStaticContext) { + if (oLexer.eof()) + return; + var sSingleSlash = '/', + sDoubleSlash = '/' + '/'; + + var oPathExpr = new cPathExpr(), + sSlash = oLexer.peek(), + oExpr; + // Parse first step + if (sSlash == sDoubleSlash || sSlash == sSingleSlash) { + oLexer.next(); + oPathExpr.items.push(new cFunctionCall(null, "root", sNS_XPF)); + // + if (sSlash == sDoubleSlash) + oPathExpr.items.push(new cAxisStep("descendant-or-self", new cKindTest("node"))); + } + + // + if (oLexer.eof() ||!(oExpr = fStepExpr_parse(oLexer, oStaticContext))) { + if (sSlash == sSingleSlash) + return oPathExpr.items[0]; // '/' expression + if (sSlash == sDoubleSlash) + throw new cException("XPST0003" + + ); + return; + } + oPathExpr.items.push(oExpr); + + // Parse other steps + while ((sSlash = oLexer.peek()) == sSingleSlash || sSlash == sDoubleSlash) { + if (sSlash == sDoubleSlash) + oPathExpr.items.push(new cAxisStep("descendant-or-self", new cKindTest("node"))); + // + oLexer.next(); + if (oLexer.eof() ||!(oExpr = fStepExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + // + oPathExpr.items.push(oExpr); + } + + if (oPathExpr.items.length == 1) + return oPathExpr.items[0]; + + // + return oPathExpr; +}; + +// Public members +cPathExpr.prototype.evaluate = function (oContext) { + var vContextItem = oContext.item; + // + var oSequence = [vContextItem]; + for (var nItemIndex = 0, nItemLength = this.items.length, oSequence1; nItemIndex < nItemLength; nItemIndex++) { + oSequence1 = []; + for (var nIndex = 0, nLength = oSequence.length; nIndex < nLength; nIndex++) { + // Set new context item + oContext.item = oSequence[nIndex]; + // + for (var nRightIndex = 0, oSequence2 = this.items[nItemIndex].evaluate(oContext), nRightLength = oSequence2.length; nRightIndex < nRightLength; nRightIndex++) + if ((nItemIndex < nItemLength - 1) && !oContext.DOMAdapter.isNode(oSequence2[nRightIndex])) + throw new cException("XPTY0019"); + else + if (fArray_indexOf(oSequence1, oSequence2[nRightIndex]) ==-1) + oSequence1.push(oSequence2[nRightIndex]); + } + oSequence = oSequence1; + }; + // Restore context item + oContext.item = vContextItem; + // + return fFunction_sequence_order(oSequence, oContext); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cNodeTest() { + +}; + +// Static members +function fNodeTest_parse (oLexer, oStaticContext) { + if (!oLexer.eof()) + return fKindTest_parse(oLexer, oStaticContext) + || fNameTest_parse(oLexer, oStaticContext); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cKindTest(sName) { + this.name = sName; + this.args = []; +}; + +cKindTest.prototype = new cNodeTest; + +cKindTest.prototype.name = null; +cKindTest.prototype.args = null; + +var hKindTest_names = {}; +// +hKindTest_names["document-node"] = {}; +hKindTest_names["element"] = {}; +hKindTest_names["attribute"] = {}; +hKindTest_names["processing-instruction"] = {}; +hKindTest_names["comment"] = {}; +hKindTest_names["text"] = {}; +hKindTest_names["node"] = {}; +// +hKindTest_names["schema-element"] = {}; +hKindTest_names["schema-attribute"] = {}; + +// Static members +function fKindTest_parse (oLexer, oStaticContext) { + var sName = oLexer.peek(), + oValue; + if (oLexer.peek(1) == '(') { + // + if (!(sName in hKindTest_names)) + throw new cException("XPST0003" + + ); + + // + oLexer.next(2); + // + var oTest = new cKindTest(sName); + if (oLexer.peek() != ')') { + if (sName == "document-node") { + // TODO: parse test further + } + else + if (sName == "element") { + // TODO: parse test further + } + else + if (sName == "attribute") { + // TODO: parse test further + } + else + if (sName == "processing-instruction") { + oValue = fStringLiteral_parse(oLexer, oStaticContext); + if (!oValue) { + oValue = new cStringLiteral(new cXSString(oLexer.peek())); + oLexer.next(); + } + oTest.args.push(oValue); + } + else + if (sName == "schema-attribute") { + // TODO: parse test further + } + else + if (sName == "schema-element") { + // TODO: parse test further + } + } + else { + if (sName == "schema-attribute") + throw new cException("XPST0003" + + ); + else + if (sName == "schema-element") + throw new cException("XPST0003" + + ); + } + + if (oLexer.peek() != ')') + throw new cException("XPST0003" + + ); + oLexer.next(); + + return oTest; + } +}; + +// Public members +cKindTest.prototype.test = function (oNode, oContext) { + var fGetProperty = oContext.DOMAdapter.getProperty, + nType = oContext.DOMAdapter.isNode(oNode) ? fGetProperty(oNode, "nodeType") : 0, + sTarget; + switch (this.name) { + // Node type test + case "node": return !!nType; + case "attribute": if (nType != 2) return false; break; + case "document-node": return nType == 9; + case "element": return nType == 1; + case "processing-instruction": if (nType != 7) return false; break; + case "comment": return nType == 8; + case "text": return nType == 3 || nType == 4; + + // Schema tests + case "schema-attribute": + throw "KindTest '" + "schema-attribute" + "' not implemented"; + + case "schema-element": + throw "KindTest '" + "schema-element" + "' not implemented"; + } + + // Additional tests + if (nType == 2) + return fGetProperty(oNode, "prefix") != "xmlns" && fGetProperty(oNode, "localName") != "xmlns"; + if (nType == 7) { + sTarget = fGetProperty(oNode, "target"); + return this.args.length ? sTarget == this.args[0].value : sTarget != "xml"; + } + + return true; +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cNameTest(sPrefix, sLocalName, sNameSpaceURI) { + this.prefix = sPrefix; + this.localName = sLocalName; + this.namespaceURI = sNameSpaceURI; +}; + +cNameTest.prototype = new cNodeTest; + +cNameTest.prototype.prefix = null; +cNameTest.prototype.localName = null; +cNameTest.prototype.namespaceURI = null; + +// Static members +var rNameTest = /^(?:(?![0-9-])(\w[\w.-]*|\*)\:)?(?![0-9-])(\w[\w.-]*|\*)$/; +function fNameTest_parse (oLexer, oStaticContext) { + var aMatch = oLexer.peek().match(rNameTest); + if (aMatch) { + if (aMatch[1] == '*' && aMatch[2] == '*') + throw new cException("XPST0003" + + ); + oLexer.next(); + return new cNameTest(aMatch[1] || null, aMatch[2], aMatch[1] ? aMatch[1] == '*' ? '*' : oStaticContext.getURIForPrefix(aMatch[1]) || null : oStaticContext.defaultElementNamespace); + } +}; + +// Public members +cNameTest.prototype.test = function (oNode, oContext) { + var fGetProperty = oContext.DOMAdapter.getProperty, + nType = fGetProperty(oNode, "nodeType"); + if (nType == 1 || nType == 2) { + if (this.localName == '*') + return (nType == 1 || (fGetProperty(oNode, "prefix") != "xmlns" && fGetProperty(oNode, "localName") != "xmlns")) && (!this.prefix || fGetProperty(oNode, "namespaceURI") == this.namespaceURI); + if (this.localName == fGetProperty(oNode, "localName")) + return this.namespaceURI == '*' || (nType == 2 && !this.prefix && !fGetProperty(oNode, "prefix")) || fGetProperty(oNode, "namespaceURI") == this.namespaceURI; + } + // + return false; +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cPrimaryExpr() { + +}; + +// Static members +function fPrimaryExpr_parse (oLexer, oStaticContext) { + if (!oLexer.eof()) + return fContextItemExpr_parse(oLexer, oStaticContext) + || fParenthesizedExpr_parse(oLexer, oStaticContext) + || fFunctionCall_parse(oLexer, oStaticContext) + || fVarRef_parse(oLexer, oStaticContext) + || fLiteral_parse(oLexer, oStaticContext); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cParenthesizedExpr(oExpr) { + this.expression = oExpr; +}; + +// Static members +function fParenthesizedExpr_parse (oLexer, oStaticContext) { + if (oLexer.peek() == '(') { + oLexer.next(); + // Check if not empty (allowed) + var oExpr = null; + if (oLexer.peek() != ')') + oExpr = fExpr_parse(oLexer, oStaticContext); + + // + if (oLexer.peek() != ')') + throw new cException("XPST0003" + + ); + + oLexer.next(); + + // + return new cParenthesizedExpr(oExpr); + } +}; + +// Public members +cParenthesizedExpr.prototype.evaluate = function (oContext) { + return this.expression ? this.expression.evaluate(oContext) : []; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cContextItemExpr() { + +}; + +// Static members +function fContextItemExpr_parse (oLexer, oStaticContext) { + if (oLexer.peek() == '.') { + oLexer.next(); + return new cContextItemExpr; + } +}; + +// Public members +cContextItemExpr.prototype.evaluate = function (oContext) { + if (oContext.item == null) + throw new cException("XPDY0002" + + ); + // + return [oContext.item]; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cLiteral() { + +}; + +cLiteral.prototype.value = null; + +// Static members +function fLiteral_parse (oLexer, oStaticContext) { + if (!oLexer.eof()) + return fNumericLiteral_parse(oLexer, oStaticContext) + || fStringLiteral_parse(oLexer, oStaticContext); +}; + +// Public members +cLiteral.prototype.evaluate = function (oContext) { + return [this.value]; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cNumericLiteral(oValue) { + this.value = oValue; +}; + +cNumericLiteral.prototype = new cLiteral; + +// Integer | Decimal | Double +var rNumericLiteral = /^[+\-]?(?:(?:(\d+)(?:\.(\d*))?)|(?:\.(\d+)))(?:[eE]([+-])?(\d+))?$/; +function fNumericLiteral_parse (oLexer, oStaticContext) { + var sValue = oLexer.peek(), + vValue = fNumericLiteral_parseValue(sValue); + if (vValue) { + oLexer.next(); + return new cNumericLiteral(vValue); + } +}; + +function fNumericLiteral_parseValue(sValue) { + var aMatch = sValue.match(rNumericLiteral); + if (aMatch) { + var cType = cXSInteger; + if (aMatch[5]) + cType = cXSDouble; + else + if (aMatch[2] || aMatch[3]) + cType = cXSDecimal; + return new cType(+sValue); + } +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cStringLiteral(oValue) { + this.value = oValue; +}; + +cStringLiteral.prototype = new cLiteral; + +var rStringLiteral = /^'([^']*(?:''[^']*)*)'|"([^"]*(?:""[^"]*)*)"$/; +function fStringLiteral_parse (oLexer, oStaticContext) { + var aMatch = oLexer.peek().match(rStringLiteral); + if (aMatch) { + oLexer.next(); + return new cStringLiteral(new cXSString(aMatch[1] ? aMatch[1].replace("''", "'") : aMatch[2] ? aMatch[2].replace('""', '"') : '')); + } +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cFilterExpr(oPrimary) { + this.expression = oPrimary; + this.predicates = []; +}; + +cFilterExpr.prototype = new cStepExpr; + +cFilterExpr.prototype.expression = null; + +// Static members +function fFilterExpr_parse (oLexer, oStaticContext) { + var oExpr; + if (oLexer.eof() ||!(oExpr = fPrimaryExpr_parse(oLexer, oStaticContext))) + return; + + var oFilterExpr = new cFilterExpr(oExpr); + // Parse predicates + fStepExpr_parsePredicates(oLexer, oStaticContext, oFilterExpr); + + // If no predicates found + if (oFilterExpr.predicates.length == 0) + return oFilterExpr.expression; + + return oFilterExpr; +}; + +// Public members +cFilterExpr.prototype.evaluate = function (oContext) { + var oSequence = this.expression.evaluate(oContext); + if (this.predicates.length && oSequence.length) + oSequence = this.applyPredicates(oSequence, oContext); + return oSequence; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cVarRef(sPrefix, sLocalName, sNameSpaceURI) { + this.prefix = sPrefix; + this.localName = sLocalName; + this.namespaceURI = sNameSpaceURI; +}; + +cVarRef.prototype.prefix = null; +cVarRef.prototype.localName = null; +cVarRef.prototype.namespaceURI = null; + +// Static members +function fVarRef_parse (oLexer, oStaticContext) { + if (oLexer.peek().substr(0, 1) == '$') { + var aMatch = oLexer.peek().substr(1).match(rNameTest); + if (aMatch) { + if (aMatch[1] == '*' || aMatch[2] == '*') + throw new cException("XPST0003" + + ); + + var oVarRef = new cVarRef(aMatch[1] || null, aMatch[2], aMatch[1] ? oStaticContext.getURIForPrefix(aMatch[1]) : null); + oLexer.next(); + return oVarRef; + } + } +}; + +// Public members +cVarRef.prototype.evaluate = function (oContext) { + var sUri = (this.namespaceURI ? '{' + this.namespaceURI + '}' : '') + this.localName; + if (oContext.scope.hasOwnProperty(sUri)) + return [oContext.scope[sUri]]; + // + throw new cException("XPST0008" + + ); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cFunctionCall(sPrefix, sLocalName, sNameSpaceURI) { + this.prefix = sPrefix; + this.localName = sLocalName; + this.namespaceURI = sNameSpaceURI; + this.args = []; +}; + +cFunctionCall.prototype.prefix = null; +cFunctionCall.prototype.localName = null; +cFunctionCall.prototype.namespaceURI = null; +cFunctionCall.prototype.args = null; + +// Static members +function fFunctionCall_parse (oLexer, oStaticContext) { + var aMatch = oLexer.peek().match(rNameTest); + if (aMatch && oLexer.peek(1) == '(') { + // Reserved "functions" + if (!aMatch[1] && (aMatch[2] in hKindTest_names)) + return fAxisStep_parse(oLexer, oStaticContext); + // Other functions + if (aMatch[1] == '*' || aMatch[2] == '*') + throw new cException("XPST0003" + + ); + var oFunctionCallExpr = new cFunctionCall(aMatch[1] || null, aMatch[2], aMatch[1] ? oStaticContext.getURIForPrefix(aMatch[1]) || null : oStaticContext.defaultFunctionNamespace), + oExpr; + oLexer.next(2); + // + if (oLexer.peek() != ')') { + do { + if (oLexer.eof() ||!(oExpr = fExprSingle_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + // + oFunctionCallExpr.args.push(oExpr); + } + while (oLexer.peek() == ',' && oLexer.next()); + // + if (oLexer.peek() != ')') + throw new cException("XPST0003" + + ); + } + oLexer.next(); + return oFunctionCallExpr; + } +}; + +// Public members +cFunctionCall.prototype.evaluate = function (oContext) { + var aArguments = [], + aParameters, + fFunction; + + // Evaluate arguments + for (var nIndex = 0, nLength = this.args.length; nIndex < nLength; nIndex++) + aArguments.push(this.args[nIndex].evaluate(oContext)); + + var sUri = (this.namespaceURI ? '{' + this.namespaceURI + '}' : '') + this.localName; + // Call function + if (this.namespaceURI == sNS_XPF) { + if (fFunction = hStaticContext_functions[this.localName]) { + // Validate/Cast arguments + if (aParameters = hStaticContext_signatures[this.localName]) + fFunctionCall_prepare(this.localName, aParameters, fFunction, aArguments, oContext); + // + var vResult = fFunction.apply(oContext, aArguments); + // + return vResult == null ? [] : vResult instanceof cArray ? vResult : [vResult]; + } + throw new cException("XPST0017" + + ); + } + else + if (this.namespaceURI == sNS_XSD) { + if ((fFunction = hStaticContext_dataTypes[this.localName]) && this.localName != "NOTATION" && this.localName != "anyAtomicType") { + // + fFunctionCall_prepare(this.localName, [[cXSAnyAtomicType, '?']], fFunction, aArguments, oContext); + // + return aArguments[0] === null ? [] : [fFunction.cast(aArguments[0])]; + } + throw new cException("XPST0017" + + ); + } + else + if (fFunction = oContext.staticContext.getFunction(sUri)) { + // + var vResult = fFunction.apply(oContext, aArguments); + // + return vResult == null ? [] : vResult instanceof cArray ? vResult : [vResult]; + } + // + throw new cException("XPST0017" + + ); +}; + +var aFunctionCall_numbers = ["first", "second", "third", "fourth", "fifth"]; +function fFunctionCall_prepare(sName, aParameters, fFunction, aArguments, oContext) { + var oArgument, + nArgumentsLength = aArguments.length, + oParameter, + nParametersLength = aParameters.length, + nParametersRequired = 0; + + // Determine amount of parameters required + while ((nParametersRequired < aParameters.length) && !aParameters[nParametersRequired][2]) + nParametersRequired++; + + // Validate arguments length + if (nArgumentsLength > nParametersLength) + throw new cException("XPST0017" + + ); + else + if (nArgumentsLength < nParametersRequired) + throw new cException("XPST0017" + + ); + + for (var nIndex = 0; nIndex < nArgumentsLength; nIndex++) { + oParameter = aParameters[nIndex]; + oArgument = aArguments[nIndex]; + // Check sequence cardinality + fFunctionCall_assertSequenceCardinality(oContext, oArgument, oParameter[1] + + ); + // Check sequence items data types consistency + fFunctionCall_assertSequenceItemType(oContext, oArgument, oParameter[0] + + ); + if (oParameter[1] != '+' && oParameter[1] != '*') + aArguments[nIndex] = oArgument.length ? oArgument[0] : null; + } +}; + +function fFunctionCall_assertSequenceItemType(oContext, oSequence, cItemType + + ) { + // + for (var nIndex = 0, nLength = oSequence.length, nNodeType, vItem; nIndex < nLength; nIndex++) { + vItem = oSequence[nIndex]; + // Node types + if (cItemType == cXTNode || cItemType.prototype instanceof cXTNode) { + // Check if is node + if (!oContext.DOMAdapter.isNode(vItem)) + throw new cException("XPTY0004" + + ); + + // Check node type + if (cItemType != cXTNode) { + nNodeType = oContext.DOMAdapter.getProperty(vItem, "nodeType"); + if ([null, cXTElement, cXTAttribute, cXTText, cXTText, null, null, cXTProcessingInstruction, cXTComment, cXTDocument, null, null, null][nNodeType] != cItemType) + throw new cException("XPTY0004" + + ); + } + } + else + // Atomic types + if (cItemType == cXSAnyAtomicType || cItemType.prototype instanceof cXSAnyAtomicType) { + // Atomize item + vItem = fFunction_sequence_atomize([vItem], oContext)[0]; + // Convert type if necessary + if (cItemType != cXSAnyAtomicType) { + // Cast item to expected type if it's type is xs:untypedAtomic + if (vItem instanceof cXSUntypedAtomic) + vItem = cItemType.cast(vItem); + // Cast item to xs:string if it's type is xs:anyURI + else + if (cItemType == cXSString/* || cItemType.prototype instanceof cXSString*/) { + if (vItem instanceof cXSAnyURI) + vItem = cXSString.cast(vItem); + } + else + if (cItemType == cXSDouble/* || cItemType.prototype instanceof cXSDouble*/) { + if (fXSAnyAtomicType_isNumeric(vItem)) + vItem = cItemType.cast(vItem); + } + } + // Check type + if (!(vItem instanceof cItemType)) + throw new cException("XPTY0004" + + ); + // Write value back to sequence + oSequence[nIndex] = vItem; + } + } +}; + +function fFunctionCall_assertSequenceCardinality(oContext, oSequence, sCardinality + + ) { + var nLength = oSequence.length; + // Check cardinality + if (sCardinality == '?') { // =0 or 1 + if (nLength > 1) + throw new cException("XPTY0004" + + ); + } + else + if (sCardinality == '+') { // =1+ + if (nLength < 1) + throw new cException("XPTY0004" + + ); + } + else + if (sCardinality != '*') { // =1 ('*' =0+) + if (nLength != 1) + throw new cException("XPTY0004" + + ); + } +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cIntersectExceptExpr(oExpr) { + this.left = oExpr; + this.items = []; +}; + +cIntersectExceptExpr.prototype.left = null; +cIntersectExceptExpr.prototype.items = null; + +// Static members +function fIntersectExceptExpr_parse (oLexer, oStaticContext) { + var oExpr, + sOperator; + if (oLexer.eof() ||!(oExpr = fInstanceofExpr_parse(oLexer, oStaticContext))) + return; + if (!((sOperator = oLexer.peek()) == "intersect" || sOperator == "except")) + return oExpr; + + // IntersectExcept expression + var oIntersectExceptExpr = new cIntersectExceptExpr(oExpr); + while ((sOperator = oLexer.peek()) == "intersect" || sOperator == "except") { + oLexer.next(); + if (oLexer.eof() ||!(oExpr = fInstanceofExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + oIntersectExceptExpr.items.push([sOperator, oExpr]); + } + return oIntersectExceptExpr; +}; + +// Public members +cIntersectExceptExpr.prototype.evaluate = function (oContext) { + var oSequence = this.left.evaluate(oContext); + for (var nIndex = 0, nLength = this.items.length, oItem; nIndex < nLength; nIndex++) + oSequence = hStaticContext_operators[(oItem = this.items[nIndex])[0]].call(oContext, oSequence, oItem[1].evaluate(oContext)); + return oSequence; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cRangeExpr(oLeft, oRight) { + this.left = oLeft; + this.right = oRight; +}; + +cRangeExpr.prototype.left = null; +cRangeExpr.prototype.right = null; + +// Static members +function fRangeExpr_parse (oLexer, oStaticContext) { + var oExpr, + oRight; + if (oLexer.eof() ||!(oExpr = fAdditiveExpr_parse(oLexer, oStaticContext))) + return; + if (oLexer.peek() != "to") + return oExpr; + + // Range expression + oLexer.next(); + if (oLexer.eof() ||!(oRight = fAdditiveExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + return new cRangeExpr(oExpr, oRight); +}; + +// Public members +cRangeExpr.prototype.evaluate = function (oContext) { + // + var oLeft = this.left.evaluate(oContext); + if (!oLeft.length) + return []; + // + + + fFunctionCall_assertSequenceCardinality(oContext, oLeft, '?' + + ); + fFunctionCall_assertSequenceItemType(oContext, oLeft, cXSInteger + + ); + + var oRight = this.right.evaluate(oContext); + if (!oRight.length) + return []; + + + + fFunctionCall_assertSequenceCardinality(oContext, oRight, '?' + + ); + fFunctionCall_assertSequenceItemType(oContext, oRight, cXSInteger + + ); + + return hStaticContext_operators["to"].call(oContext, oLeft[0], oRight[0]); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cUnionExpr(oExpr) { + this.left = oExpr; + this.items = []; +}; + +cUnionExpr.prototype.left = null; +cUnionExpr.prototype.items = null; + +// Static members +function fUnionExpr_parse (oLexer, oStaticContext) { + var oExpr, + sOperator; + if (oLexer.eof() ||!(oExpr = fIntersectExceptExpr_parse(oLexer, oStaticContext))) + return; + if (!((sOperator = oLexer.peek()) == '|' || sOperator == "union")) + return oExpr; + + // Union expression + var oUnionExpr = new cUnionExpr(oExpr); + while ((sOperator = oLexer.peek()) == '|' || sOperator == "union") { + oLexer.next(); + if (oLexer.eof() ||!(oExpr = fIntersectExceptExpr_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + oUnionExpr.items.push(oExpr); + } + return oUnionExpr; +}; + +// Public members +cUnionExpr.prototype.evaluate = function (oContext) { + var oSequence = this.left.evaluate(oContext); + for (var nIndex = 0, nLength = this.items.length; nIndex < nLength; nIndex++) + oSequence = hStaticContext_operators["union"].call(oContext, oSequence, this.items[nIndex].evaluate(oContext)); + return oSequence; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cInstanceofExpr(oExpr, oType) { + this.expression = oExpr; + this.type = oType; +}; + +cInstanceofExpr.prototype.expression = null; +cInstanceofExpr.prototype.type = null; + +function fInstanceofExpr_parse (oLexer, oStaticContext) { + var oExpr, + oType; + if (oLexer.eof() ||!(oExpr = fTreatExpr_parse(oLexer, oStaticContext))) + return; + + if (!(oLexer.peek() == "instance" && oLexer.peek(1) == "of")) + return oExpr; + + oLexer.next(2); + if (oLexer.eof() ||!(oType = fSequenceType_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + + return new cInstanceofExpr(oExpr, oType); +}; + +cInstanceofExpr.prototype.evaluate = function(oContext) { + var oSequence1 = this.expression.evaluate(oContext), + oItemType = this.type.itemType, + sOccurence = this.type.occurence; + // Validate empty-sequence() + if (!oItemType) + return [new cXSBoolean(!oSequence1.length)]; + // Validate cardinality + if (!oSequence1.length) + return [new cXSBoolean(sOccurence == '?' || sOccurence == '*')]; + if (oSequence1.length != 1) + if (!(sOccurence == '+' || sOccurence == '*')) + return [new cXSBoolean(false)]; + + // Validate type + if (!oItemType.test) // item() + return [new cXSBoolean(true)]; + + var bValue = true; + for (var nIndex = 0, nLength = oSequence1.length; (nIndex < nLength) && bValue; nIndex++) + bValue = oItemType.test.test(oSequence1[nIndex], oContext); + // + return [new cXSBoolean(bValue)]; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cTreatExpr(oExpr, oType) { + this.expression = oExpr; + this.type = oType; +}; + +cTreatExpr.prototype.expression = null; +cTreatExpr.prototype.type = null; + +function fTreatExpr_parse (oLexer, oStaticContext) { + var oExpr, + oType; + if (oLexer.eof() ||!(oExpr = fCastableExpr_parse(oLexer, oStaticContext))) + return; + + if (!(oLexer.peek() == "treat" && oLexer.peek(1) == "as")) + return oExpr; + + oLexer.next(2); + if (oLexer.eof() ||!(oType = fSequenceType_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + + return new cTreatExpr(oExpr, oType); +}; + +cTreatExpr.prototype.evaluate = function(oContext) { + var oSequence1 = this.expression.evaluate(oContext), + oItemType = this.type.itemType, + sOccurence = this.type.occurence; + // Validate empty-sequence() + if (!oItemType) { + if (oSequence1.length) + throw new cException("XPDY0050" + + ); + return oSequence1; + } + + // Validate cardinality + if (!(sOccurence == '?' || sOccurence == '*')) + if (!oSequence1.length) + throw new cException("XPDY0050" + + ); + + if (!(sOccurence == '+' || sOccurence == '*')) + if (oSequence1.length != 1) + throw new cException("XPDY0050" + + ); + + // Validate type + if (!oItemType.test) // item() + return oSequence1; + + for (var nIndex = 0, nLength = oSequence1.length; nIndex < nLength; nIndex++) + if (!oItemType.test.test(oSequence1[nIndex], oContext)) + throw new cException("XPDY0050" + + ); + + // + return oSequence1; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cCastableExpr(oExpr, oType) { + this.expression = oExpr; + this.type = oType; +}; + +cCastableExpr.prototype.expression = null; +cCastableExpr.prototype.type = null; + +function fCastableExpr_parse (oLexer, oStaticContext) { + var oExpr, + oType; + if (oLexer.eof() ||!(oExpr = fCastExpr_parse(oLexer, oStaticContext))) + return; + + if (!(oLexer.peek() == "castable" && oLexer.peek(1) == "as")) + return oExpr; + + oLexer.next(2); + if (oLexer.eof() ||!(oType = fSingleType_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + + return new cCastableExpr(oExpr, oType); +}; + +cCastableExpr.prototype.evaluate = function(oContext) { + var oSequence1 = this.expression.evaluate(oContext), + oItemType = this.type.itemType, + sOccurence = this.type.occurence; + + if (oSequence1.length > 1) + return [new cXSBoolean(false)]; + else + if (!oSequence1.length) + return [new cXSBoolean(sOccurence == '?')]; + + // Try casting + try { + oItemType.cast(fFunction_sequence_atomize(oSequence1, oContext)[0]); + } + catch (e) { + if (e.code == "XPST0051") + throw e; + if (e.code == "XPST0017") + throw new cException("XPST0080" + + ); + // + return [new cXSBoolean(false)]; + } + + return [new cXSBoolean(true)]; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cCastExpr(oExpr, oType) { + this.expression = oExpr; + this.type = oType; +}; + +cCastExpr.prototype.expression = null; +cCastExpr.prototype.type = null; + +function fCastExpr_parse (oLexer, oStaticContext) { + var oExpr, + oType; + if (oLexer.eof() ||!(oExpr = fUnaryExpr_parse(oLexer, oStaticContext))) + return; + + if (!(oLexer.peek() == "cast" && oLexer.peek(1) == "as")) + return oExpr; + + oLexer.next(2); + if (oLexer.eof() ||!(oType = fSingleType_parse(oLexer, oStaticContext))) + throw new cException("XPST0003" + + ); + + return new cCastExpr(oExpr, oType); +}; + +cCastExpr.prototype.evaluate = function(oContext) { + var oSequence1 = this.expression.evaluate(oContext); + // Validate cardinality + fFunctionCall_assertSequenceCardinality(oContext, oSequence1, this.type.occurence + + ); + // + if (!oSequence1.length) + return []; + // + return [this.type.itemType.cast(fFunction_sequence_atomize(oSequence1, oContext)[0], oContext)]; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cAtomicType(sPrefix, sLocalName, sNameSpaceURI) { + this.prefix = sPrefix; + this.localName = sLocalName; + this.namespaceURI = sNameSpaceURI; +}; + +cAtomicType.prototype.prefix = null; +cAtomicType.prototype.localName = null; +cAtomicType.prototype.namespaceURI = null; + +function fAtomicType_parse (oLexer, oStaticContext) { + var aMatch = oLexer.peek().match(rNameTest); + if (aMatch) { + if (aMatch[1] == '*' || aMatch[2] == '*') + throw new cException("XPST0003" + + ); + oLexer.next(); + return new cAtomicType(aMatch[1] || null, aMatch[2], aMatch[1] ? oStaticContext.getURIForPrefix(aMatch[1]) : null); + } +}; + +cAtomicType.prototype.test = function(vItem, oContext) { + // Test + var sUri = (this.namespaceURI ? '{' + this.namespaceURI + '}' : '') + this.localName, + cType = this.namespaceURI == sNS_XSD ? hStaticContext_dataTypes[this.localName] : oContext.staticContext.getDataType(sUri); + if (cType) + return vItem instanceof cType; + // + throw new cException("XPST0051" + + ); +}; + +cAtomicType.prototype.cast = function(vItem, oContext) { + // Cast + var sUri = (this.namespaceURI ? '{' + this.namespaceURI + '}' : '') + this.localName, + cType = this.namespaceURI == sNS_XSD ? hStaticContext_dataTypes[this.localName] : oContext.staticContext.getDataType(sUri); + if (cType) + return cType.cast(vItem); + // + throw new cException("XPST0051" + + ); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cItemType(oTest) { + this.test = oTest; +}; + +cItemType.prototype.test = null; + +function fItemType_parse (oLexer, oStaticContext) { + if (oLexer.eof()) + return; + + var oExpr; + if (oLexer.peek() == "item" && oLexer.peek(1) == '(') { + oLexer.next(2); + if (oLexer.peek() != ')') + throw new cException("XPST0003" + + ); + oLexer.next(); + return new cItemType; + } + // Note! Following step should have been before previous as per spec + if (oExpr = fKindTest_parse(oLexer, oStaticContext)) + return new cItemType(oExpr); + if (oExpr = fAtomicType_parse(oLexer, oStaticContext)) + return new cItemType(oExpr); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cSequenceType(oItemType, sOccurence) { + this.itemType = oItemType || null; + this.occurence = sOccurence|| null; +}; + +cSequenceType.prototype.itemType = null; +cSequenceType.prototype.occurence = null; + +function fSequenceType_parse (oLexer, oStaticContext) { + if (oLexer.eof()) + return; + + if (oLexer.peek() == "empty-sequence" && oLexer.peek(1) == '(') { + oLexer.next(2); + if (oLexer.peek() != ')') + throw new cException("XPST0003" + + ); + oLexer.next(); + return new cSequenceType; // empty sequence + } + + var oExpr, + sOccurence; + if (!oLexer.eof() && (oExpr = fItemType_parse(oLexer, oStaticContext))) { + sOccurence = oLexer.peek(); + if (sOccurence == '?' || sOccurence == '*' || sOccurence == '+') + oLexer.next(); + else + sOccurence = null; + + return new cSequenceType(oExpr, sOccurence); + } +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cSingleType(oItemType, sOccurence) { + this.itemType = oItemType || null; + this.occurence = sOccurence|| null; +}; + +cSingleType.prototype.itemType = null; +cSingleType.prototype.occurence = null; + +function fSingleType_parse (oLexer, oStaticContext) { + var oExpr, + sOccurence; + if (!oLexer.eof() && (oExpr = fAtomicType_parse(oLexer, oStaticContext))) { + sOccurence = oLexer.peek(); + if (sOccurence == '?') + oLexer.next(); + else + sOccurence = null; + + return new cSingleType(oExpr, sOccurence); + } +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSAnyType() { + +}; + +cXSAnyType.prototype.builtInKind = cXSConstants.ANYTYPE_DT; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSAnySimpleType() { + +}; + +cXSAnySimpleType.prototype = new cXSAnyType; + +cXSAnySimpleType.prototype.builtInKind = cXSConstants.ANYSIMPLETYPE_DT; +cXSAnySimpleType.prototype.primitiveKind= null; + +cXSAnySimpleType.PRIMITIVE_ANYURI = "anyURI"; //18; +cXSAnySimpleType.PRIMITIVE_BASE64BINARY = "base64Binary"; // 17; +cXSAnySimpleType.PRIMITIVE_BOOLEAN = "boolean"; // 3; +cXSAnySimpleType.PRIMITIVE_DATE = "date"; // 10; +cXSAnySimpleType.PRIMITIVE_DATETIME = "dateTime"; // 8; +cXSAnySimpleType.PRIMITIVE_DECIMAL = "decimal"; // 4; +cXSAnySimpleType.PRIMITIVE_DOUBLE = "double"; // 6; +cXSAnySimpleType.PRIMITIVE_DURATION = "duration"; // 7; +cXSAnySimpleType.PRIMITIVE_FLOAT = "float"; // 5; +cXSAnySimpleType.PRIMITIVE_GDAY = "gDay"; // 14; +cXSAnySimpleType.PRIMITIVE_GMONTH = "gMonth"; // 15; +cXSAnySimpleType.PRIMITIVE_GMONTHDAY = "gMonthDay"; // 13; +cXSAnySimpleType.PRIMITIVE_GYEAR = "gYear"; // 12; +cXSAnySimpleType.PRIMITIVE_GYEARMONTH = "gYearMonth"; // 11; +cXSAnySimpleType.PRIMITIVE_HEXBINARY = "hexBinary"; // 16; +cXSAnySimpleType.PRIMITIVE_NOTATION = "NOTATION"; // 20; +cXSAnySimpleType.PRIMITIVE_QNAME = "QName"; // 19; +cXSAnySimpleType.PRIMITIVE_STRING = "string"; // 2; +cXSAnySimpleType.PRIMITIVE_TIME = "time"; // 9; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSAnyAtomicType() { + +}; + +cXSAnyAtomicType.prototype = new cXSAnySimpleType; +cXSAnyAtomicType.prototype.builtInKind = cXSConstants.ANYATOMICTYPE_DT; + +cXSAnyAtomicType.cast = function(vValue) { + throw new cException("XPST0017" + + ); // {http://www.w3.org/2001/XMLSchema}anyAtomicType +}; + +function fXSAnyAtomicType_isNumeric(vItem) { + return vItem instanceof cXSFloat || vItem instanceof cXSDouble || vItem instanceof cXSDecimal; +}; + +// +fStaticContext_defineSystemDataType("anyAtomicType", cXSAnyAtomicType); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSAnyURI(sScheme, sAuthority, sPath, sQuery, sFragment) { + this.scheme = sScheme; + this.authority = sAuthority; + this.path = sPath; + this.query = sQuery; + this.fragment = sFragment; +}; + +cXSAnyURI.prototype = new cXSAnyAtomicType; +cXSAnyURI.prototype.builtInKind = cXSConstants.ANYURI_DT; +cXSAnyURI.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_ANYURI; + +cXSAnyURI.prototype.scheme = null; +cXSAnyURI.prototype.authority = null; +cXSAnyURI.prototype.path = null; +cXSAnyURI.prototype.query = null; +cXSAnyURI.prototype.fragment = null; + +cXSAnyURI.prototype.toString = function() { + return (this.scheme ? this.scheme + ':' : '') + + (this.authority ? '/' + '/' + this.authority : '') + + (this.path ? this.path : '') + + (this.query ? '?' + this.query : '') + + (this.fragment ? '#' + this.fragment : ''); +}; + +var rXSAnyURI = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; // http://tools.ietf.org/html/rfc3986 +cXSAnyURI.cast = function(vValue) { + if (vValue instanceof cXSAnyURI) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch; + if (aMatch = fString_trim(vValue).match(rXSAnyURI)) + return new cXSAnyURI(aMatch[2], aMatch[4], aMatch[5], aMatch[7], aMatch[9]); + throw new cException("FORG0001"); + } + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("anyURI", cXSAnyURI); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSBase64Binary(sValue) { + this.value = sValue; +}; + +cXSBase64Binary.prototype = new cXSAnyAtomicType; +cXSBase64Binary.prototype.builtInKind = cXSConstants.BASE64BINARY_DT; +cXSBase64Binary.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_BASE64BINARY; + +cXSBase64Binary.prototype.value = null; + +cXSBase64Binary.prototype.valueOf = function() { + return this.value; +}; + +cXSBase64Binary.prototype.toString = function() { + return this.value; +}; + +var rXSBase64Binary = /^((([A-Za-z0-9+\/]\s*){4})*(([A-Za-z0-9+\/]\s*){3}[A-Za-z0-9+\/]|([A-Za-z0-9+\/]\s*){2}[AEIMQUYcgkosw048]\s*=|[A-Za-z0-9+\/]\s*[AQgw]\s*=\s*=))?$/; +cXSBase64Binary.cast = function(vValue) { + if (vValue instanceof cXSBase64Binary) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSBase64Binary); + if (aMatch) + return new cXSBase64Binary(aMatch[0]); + throw new cException("FORG0001"); + } + if (vValue instanceof cXSHexBinary) { + var aMatch = vValue.valueOf().match(/.{2}/g), + aValue = []; + for (var nIndex = 0, nLength = aMatch.length; nIndex < nLength; nIndex++) + aValue.push(cString.fromCharCode(fWindow_parseInt(aMatch[nIndex], 16))); + return new cXSBase64Binary(fWindow_btoa(aValue.join(''))); + } + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("base64Binary", cXSBase64Binary); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSBoolean(bValue) { + this.value = bValue; +}; + +cXSBoolean.prototype = new cXSAnyAtomicType; +cXSBoolean.prototype.builtInKind = cXSConstants.BOOLEAN_DT; +cXSBoolean.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_BOOLEAN; + +cXSBoolean.prototype.value = null; + +cXSBoolean.prototype.valueOf = function() { + return this.value; +}; + +cXSBoolean.prototype.toString = function() { + return cString(this.value); +}; + +var rXSBoolean = /^(0|1|true|false)$/; +cXSBoolean.cast = function(vValue) { + if (vValue instanceof cXSBoolean) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch; + if (aMatch = fString_trim(vValue).match(rXSBoolean)) + return new cXSBoolean(aMatch[1] == '1' || aMatch[1] == "true"); + throw new cException("FORG0001"); + } + if (fXSAnyAtomicType_isNumeric(vValue)) + return new cXSBoolean(vValue != 0); + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("boolean", cXSBoolean); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSDate(nYear, nMonth, nDay, nTimezone, bNegative) { + this.year = nYear; + this.month = nMonth; + this.day = nDay; + this.timezone = nTimezone; + this.negative = bNegative; +}; + +cXSDate.prototype = new cXSAnyAtomicType; +cXSDate.prototype.builtInKind = cXSConstants.DATE_DT; +cXSDate.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_DATE; + +cXSDate.prototype.year = null; +cXSDate.prototype.month = null; +cXSDate.prototype.day = null; +cXSDate.prototype.timezone = null; +cXSDate.prototype.negative = null; + +cXSDate.prototype.toString = function() { + return fXSDateTime_getDateComponent(this) + + fXSDateTime_getTZComponent(this); +}; + +var rXSDate = /^(-?)([1-9]\d\d\d+|0\d\d\d)-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])(Z|([+\-])(0\d|1[0-4]):([0-5]\d))?$/; +cXSDate.cast = function(vValue) { + if (vValue instanceof cXSDate) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSDate); + if (aMatch) { + var nYear = +aMatch[2], + nMonth = +aMatch[3], + nDay = +aMatch[4]; + if (nDay - 1 < fXSDate_getDaysForYearMonth(nYear, nMonth)) + return new cXSDate( nYear, + nMonth, + nDay, + aMatch[5] ? aMatch[5] == 'Z' ? 0 : (aMatch[6] == '-' ? -1 : 1) * (aMatch[7] * 60 + aMatch[8] * 1) : null, + aMatch[1] == '-' + ); + // + throw new cException("FORG0001" + + ); + } + throw new cException("FORG0001"); + } + if (vValue instanceof cXSDateTime) + return new cXSDate(vValue.year, vValue.month, vValue.day, vValue.timezone, vValue.negative); + // + throw new cException("XPTY0004" + + ); +}; + +// Utilities +var aXSDate_days = [31,28,31,30,31,30,31,31,30,31,30,31]; +function fXSDate_getDaysForYearMonth(nYear, nMonth) { + return nMonth == 2 && (nYear % 400 == 0 || nYear % 100 != 0 && nYear % 4 == 0) ? 29 : aXSDate_days[nMonth - 1]; +}; + +function fXSDate_normalize(oValue, bDay) { + // Adjust day for month/year + if (!bDay) { + var nDay = fXSDate_getDaysForYearMonth(oValue.year, oValue.month); + if (oValue.day > nDay) { + while (oValue.day > nDay) { + oValue.month += 1; + if (oValue.month > 12) { + oValue.year += 1; + if (oValue.year == 0) + oValue.year = 1; + oValue.month = 1; + } + oValue.day -= nDay; + nDay = fXSDate_getDaysForYearMonth(oValue.year, oValue.month); + } + } + else + if (oValue.day < 1) { + while (oValue.day < 1) { + oValue.month -= 1; + if (oValue.month < 1) { + oValue.year -= 1; + if (oValue.year == 0) + oValue.year =-1; + oValue.month = 12; + } + nDay = fXSDate_getDaysForYearMonth(oValue.year, oValue.month); + oValue.day += nDay; + } + } + } +//? else + // Adjust month + if (oValue.month > 12) { + oValue.year += ~~(oValue.month / 12); + if (oValue.year == 0) + oValue.year = 1; + oValue.month = oValue.month % 12; + } + else + if (oValue.month < 1) { + oValue.year += ~~(oValue.month / 12) - 1; + if (oValue.year == 0) + oValue.year =-1; + oValue.month = oValue.month % 12 + 12; + } + + return oValue; +}; + +// +fStaticContext_defineSystemDataType("date", cXSDate); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSDateTime(nYear, nMonth, nDay, nHours, nMinutes, nSeconds, nTimezone, bNegative) { + this.year = nYear; + this.month = nMonth; + this.day = nDay; + this.hours = nHours; + this.minutes = nMinutes; + this.seconds = nSeconds; + this.timezone = nTimezone; + this.negative = bNegative; +}; + +cXSDateTime.prototype = new cXSAnyAtomicType; +cXSDateTime.prototype.builtInKind = cXSConstants.DATETIME_DT; +cXSDateTime.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_DATETIME; + +cXSDateTime.prototype.year = null; +cXSDateTime.prototype.month = null; +cXSDateTime.prototype.day = null; +cXSDateTime.prototype.hours = null; +cXSDateTime.prototype.minutes = null; +cXSDateTime.prototype.seconds = null; +cXSDateTime.prototype.timezone = null; +cXSDateTime.prototype.negative = null; + +cXSDateTime.prototype.toString = function() { + return fXSDateTime_getDateComponent(this) + + 'T' + + fXSDateTime_getTimeComponent(this) + + fXSDateTime_getTZComponent(this); +}; + +var rXSDateTime = /^(-?)([1-9]\d\d\d+|0\d\d\d)-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T(([01]\d|2[0-3]):([0-5]\d):([0-5]\d)(?:\.(\d+))?|(24:00:00)(?:\.(0+))?)(Z|([+\-])(0\d|1[0-4]):([0-5]\d))?$/; +cXSDateTime.cast = function(vValue) { + if (vValue instanceof cXSDateTime) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSDateTime); + if (aMatch) { + var nYear = +aMatch[2], + nMonth = +aMatch[3], + nDay = +aMatch[4], + bValue = !!aMatch[10]; + if (nDay - 1 < fXSDate_getDaysForYearMonth(nYear, nMonth)) + return fXSDateTime_normalize(new cXSDateTime( nYear, + nMonth, + nDay, + bValue ? 24 : +aMatch[6], + bValue ? 0 : +aMatch[7], + cNumber((bValue ? 0 : aMatch[8]) + '.' + (bValue ? 0 : aMatch[9] || 0)), + aMatch[12] ? aMatch[12] == 'Z' ? 0 : (aMatch[13] == '-' ? -1 : 1) * (aMatch[14] * 60 + aMatch[15] * 1) : null, + aMatch[1] == '-' + )); + // + throw new cException("FORG0001" + + ); + } + throw new cException("FORG0001"); + } + if (vValue instanceof cXSDate) + return new cXSDateTime(vValue.year, vValue.month, vValue.day, 0, 0, 0, vValue.timezone, vValue.negative); + // + throw new cException("XPTY0004" + + ); +}; + +// Utilities +function fXSDateTime_pad(vValue, nLength) { + var sValue = cString(vValue); + if (arguments.length < 2) + nLength = 2; + return (sValue.length < nLength + 1 ? new cArray(nLength + 1 - sValue.length).join('0') : '') + sValue; +}; + +function fXSDateTime_getTZComponent(oDateTime) { + var nTimezone = oDateTime.timezone; + return nTimezone == null + ? '' + : nTimezone + ? (nTimezone > 0 ? '+' : '-') + + fXSDateTime_pad(cMath.abs(~~(nTimezone / 60))) + + ':' + + fXSDateTime_pad(cMath.abs(nTimezone % 60)) + : 'Z'; +}; + +function fXSDateTime_getDateComponent(oDateTime) { + return (oDateTime.negative ? '-' : '') + + fXSDateTime_pad(oDateTime.year, 4) + + '-' + fXSDateTime_pad(oDateTime.month) + + '-' + fXSDateTime_pad(oDateTime.day); +}; + +function fXSDateTime_getTimeComponent(oDateTime) { + var aValue = cString(oDateTime.seconds).split('.'); + return fXSDateTime_pad(oDateTime.hours) + + ':' + fXSDateTime_pad(oDateTime.minutes) + + ':' + fXSDateTime_pad(aValue[0]) + + (aValue.length > 1 ? '.' + aValue[1] : ''); +}; + +function fXSDateTime_normalize(oValue) { + return fXSDate_normalize(fXSTime_normalize(oValue)); +}; + +// +fStaticContext_defineSystemDataType("dateTime", cXSDateTime); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSDecimal(nValue) { + this.value = nValue; +}; + +cXSDecimal.prototype = new cXSAnyAtomicType; +cXSDecimal.prototype.builtInKind = cXSConstants.DECIMAL_DT; +cXSDecimal.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_DECIMAL; + +cXSDecimal.prototype.value = null; + +cXSDecimal.prototype.valueOf = function() { + return this.value; +}; + +cXSDecimal.prototype.toString = function() { + return cString(this.value); +}; + +var rXSDecimal = /^[+\-]?((\d+(\.\d*)?)|(\.\d+))$/; +cXSDecimal.cast = function(vValue) { + if (vValue instanceof cXSDecimal) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSDecimal); + if (aMatch) + return new cXSDecimal(+vValue); + throw new cException("FORG0001"); + } + if (vValue instanceof cXSBoolean) + return new cXSDecimal(vValue * 1); + if (fXSAnyAtomicType_isNumeric(vValue)) { + if (!fIsNaN(vValue) && fIsFinite(vValue)) + return new cXSDecimal(+vValue); + throw new cException("FOCA0002" + + ); + } + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("decimal", cXSDecimal); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSDouble(nValue) { + this.value = nValue; +}; + +cXSDouble.prototype = new cXSAnyAtomicType; +cXSDouble.prototype.builtInKind = cXSConstants.DOUBLE_DT; +cXSDouble.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_DOUBLE; + +cXSDouble.prototype.value = null; + +cXSDouble.prototype.valueOf = function() { + return this.value; +}; + +cXSDouble.prototype.toString = function() { + return cString(this.value); +}; + +var rXSDouble = /^([+\-]?((\d+(\.\d*)?)|(\.\d+))([eE][+\-]?\d+)?|(-?INF)|NaN)$/; +cXSDouble.cast = function(vValue) { + if (vValue instanceof cXSDouble) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSDouble); + if (aMatch) + return new cXSDouble(aMatch[7] ? +aMatch[7].replace("INF", "Infinity") : +vValue); + throw new cException("FORG0001"); + } + if (vValue instanceof cXSBoolean) + return new cXSDouble(vValue * 1); + if (fXSAnyAtomicType_isNumeric(vValue)) + return new cXSDouble(vValue.value); + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("double", cXSDouble); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSDuration(nYear, nMonth, nDay, nHours, nMinutes, nSeconds, bNegative) { + this.year = nYear; + this.month = nMonth; + this.day = nDay; + this.hours = nHours; + this.minutes = nMinutes; + this.seconds = nSeconds; + this.negative = bNegative; +}; + +cXSDuration.prototype = new cXSAnyAtomicType; +cXSDuration.prototype.builtInKind = cXSConstants.DURATION_DT; +cXSDuration.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_DURATION; + +cXSDuration.prototype.year = null; +cXSDuration.prototype.month = null; +cXSDuration.prototype.day = null; +cXSDuration.prototype.hours = null; +cXSDuration.prototype.minutes = null; +cXSDuration.prototype.seconds = null; +cXSDuration.prototype.negative = null; + +cXSDuration.prototype.toString = function() { + return (this.negative ? '-' : '') + 'P' + + ((fXSDuration_getYearMonthComponent(this) + fXSDuration_getDayTimeComponent(this)) || 'T0S'); +}; + +var rXSDuration = /^(-)?P(?:([0-9]+)Y)?(?:([0-9]+)M)?(?:([0-9]+)D)?(?:T(?:([0-9]+)H)?(?:([0-9]+)M)?(?:((?:(?:[0-9]+(?:.[0-9]*)?)|(?:.[0-9]+)))S)?)?$/; +cXSDuration.cast = function(vValue) { + if (vValue instanceof cXSDuration) + return vValue; + if (vValue instanceof cXSYearMonthDuration) + return new cXSDuration(vValue.year, vValue.month, 0, 0, 0, 0, vValue.negative); + if (vValue instanceof cXSDayTimeDuration) + return new cXSDuration(0, 0, vValue.day, vValue.hours, vValue.minutes, vValue.seconds, vValue.negative); + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSDuration); + if (aMatch) + return fXSDuration_normalize(new cXSDuration(+aMatch[2] || 0, +aMatch[3] || 0, +aMatch[4] || 0, +aMatch[5] || 0, +aMatch[6] || 0, +aMatch[7] || 0, aMatch[1] == '-')); + throw new cException("FORG0001"); + } + // + throw new cException("XPTY0004" + + ); +}; + +// Utilities +function fXSDuration_getYearMonthComponent(oDuration) { + return (oDuration.year ? oDuration.year + 'Y' : '') + + (oDuration.month ? oDuration.month + 'M' : ''); +}; + +function fXSDuration_getDayTimeComponent(oDuration) { + return (oDuration.day ? oDuration.day + 'D' : '') + + (oDuration.hours || oDuration.minutes || oDuration.seconds + ? 'T' + + (oDuration.hours ? oDuration.hours + 'H' : '') + + (oDuration.minutes ? oDuration.minutes + 'M' : '') + + (oDuration.seconds ? oDuration.seconds + 'S' : '') + : ''); +}; + +function fXSDuration_normalize(oDuration) { + return fXSYearMonthDuration_normalize(fXSDayTimeDuration_normalize(oDuration)); +}; + +// +fStaticContext_defineSystemDataType("duration", cXSDuration); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSFloat(nValue) { + this.value = nValue; +}; + +cXSFloat.prototype = new cXSAnyAtomicType; +cXSFloat.prototype.builtInKind = cXSConstants.FLOAT_DT; +cXSFloat.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_FLOAT; + +cXSFloat.prototype.value = null; + +cXSFloat.prototype.valueOf = function() { + return this.value; +}; + +cXSFloat.prototype.toString = function() { + return cString(this.value); +}; + +var rXSFloat = /^([+\-]?((\d+(\.\d*)?)|(\.\d+))([eE][+\-]?\d+)?|(-?INF)|NaN)$/; +cXSFloat.cast = function(vValue) { + if (vValue instanceof cXSFloat) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSFloat); + if (aMatch) + return new cXSFloat(aMatch[7] ? +aMatch[7].replace("INF", "Infinity") : +vValue); + throw new cException("FORG0001"); + } + if (vValue instanceof cXSBoolean) + return new cXSFloat(vValue * 1); + if (fXSAnyAtomicType_isNumeric(vValue)) + return new cXSFloat(vValue.value); + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("float", cXSFloat); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSGDay(nDay, nTimezone) { + this.day = nDay; + this.timezone = nTimezone; +}; + +cXSGDay.prototype = new cXSAnyAtomicType; +cXSGDay.prototype.builtInKind = cXSConstants.GDAY_DT; +cXSGDay.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_GDAY; + +cXSGDay.prototype.day = null; +cXSGDay.prototype.timezone = null; + +cXSGDay.prototype.toString = function() { + return '-' + + '-' + + '-' + fXSDateTime_pad(this.day) + + fXSDateTime_getTZComponent(this); +}; + +var rXSGDay = /^---(0[1-9]|[12]\d|3[01])(Z|([+\-])(0\d|1[0-4]):([0-5]\d))?$/; +cXSGDay.cast = function(vValue) { + if (vValue instanceof cXSGDay) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSGDay); + if (aMatch) { + var nDay = +aMatch[1]; + return new cXSGDay( nDay, + aMatch[2] ? aMatch[2] == 'Z' ? 0 : (aMatch[3] == '-' ? -1 : 1) * (aMatch[4] * 60 + aMatch[5] * 1) : null + ); + } + throw new cException("FORG0001"); + } + if (vValue instanceof cXSDate || vValue instanceof cXSDateTime) + return new cXSGDay(vValue.day, vValue.timezone); + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("gDay", cXSGDay); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSGMonth(nMonth, nTimezone) { + this.month = nMonth; + this.timezone = nTimezone; +}; + +cXSGMonth.prototype = new cXSAnyAtomicType; +cXSGMonth.prototype.builtInKind = cXSConstants.GMONTH_DT; +cXSGMonth.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_GMONTH; + +cXSGMonth.prototype.month = null; +cXSGMonth.prototype.timezone = null; + +cXSGMonth.prototype.toString = function() { + return '-' + + '-' + fXSDateTime_pad(this.month) + + fXSDateTime_getTZComponent(this); +}; + +var rXSGMonth = /^--(0[1-9]|1[0-2])(Z|([+\-])(0\d|1[0-4]):([0-5]\d))?$/; +cXSGMonth.cast = function(vValue) { + if (vValue instanceof cXSGMonth) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSGMonth); + if (aMatch) { + var nMonth = +aMatch[1]; + return new cXSGMonth( nMonth, + aMatch[2] ? aMatch[2] == 'Z' ? 0 : (aMatch[3] == '-' ? -1 : 1) * (aMatch[4] * 60 + aMatch[5] * 1) : null + ); + } + throw new cException("FORG0001"); + } + if (vValue instanceof cXSDate || vValue instanceof cXSDateTime) + return new cXSGMonth(vValue.month, vValue.timezone); + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("gMonth", cXSGMonth); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSGMonthDay(nMonth, nDay, nTimezone) { + this.month = nMonth; + this.day = nDay; + this.timezone = nTimezone; +}; + +cXSGMonthDay.prototype = new cXSAnyAtomicType; +cXSGMonthDay.prototype.builtInKind = cXSConstants.GMONTHDAY_DT; +cXSGMonthDay.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_GMONTHDAY; + +cXSGMonthDay.prototype.month = null; +cXSGMonthDay.prototype.day = null; +cXSGMonthDay.prototype.timezone = null; + +cXSGMonthDay.prototype.toString = function() { + return '-' + + '-' + fXSDateTime_pad(this.month) + + '-' + fXSDateTime_pad(this.day) + + fXSDateTime_getTZComponent(this); +}; + +var rXSGMonthDay = /^--(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])(Z|([+\-])(0\d|1[0-4]):([0-5]\d))?$/; +cXSGMonthDay.cast = function(vValue) { + if (vValue instanceof cXSGMonthDay) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSGMonthDay); + if (aMatch) { + var nMonth = +aMatch[1], + nDay = +aMatch[2]; + if (nDay - 1 < fXSDate_getDaysForYearMonth(1976, nMonth)) + return new cXSGMonthDay( nMonth, + nDay, + aMatch[3] ? aMatch[3] == 'Z' ? 0 : (aMatch[4] == '-' ? -1 : 1) * (aMatch[5] * 60 + aMatch[6] * 1) : null + ); + // + throw new cException("FORG0001" + + ); + } + throw new cException("FORG0001"); + } + if (vValue instanceof cXSDate || vValue instanceof cXSDateTime) + return new cXSGMonthDay(vValue.month, vValue.day, vValue.timezone); + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("gMonthDay", cXSGMonthDay); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSGYear(nYear, nTimezone) { + this.year = nYear; + this.timezone = nTimezone; +}; + +cXSGYear.prototype = new cXSAnyAtomicType; +cXSGYear.prototype.builtInKind = cXSConstants.GYEAR_DT; +cXSGYear.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_GYEAR; + +cXSGYear.prototype.year = null; +cXSGYear.prototype.timezone = null; + +cXSGYear.prototype.toString = function() { + return fXSDateTime_pad(this.year) + + fXSDateTime_getTZComponent(this); +}; + +var rXSGYear = /^-?([1-9]\d\d\d+|0\d\d\d)(Z|([+\-])(0\d|1[0-4]):([0-5]\d))?$/; +cXSGYear.cast = function(vValue) { + if (vValue instanceof cXSGYear) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSGYear); + if (aMatch) { + var nYear = +aMatch[1]; + return new cXSGYear( nYear, + aMatch[2] ? aMatch[2] == 'Z' ? 0 : (aMatch[3] == '-' ? -1 : 1) * (aMatch[4] * 60 + aMatch[5] * 1) : null + ); + } + throw new cException("FORG0001"); + } + if (vValue instanceof cXSDate || vValue instanceof cXSDateTime) + return new cXSGYear(vValue.year, vValue.timezone); + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("gYear", cXSGYear); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSGYearMonth(nYear, nMonth, nTimezone) { + this.year = nYear; + this.month = nMonth; + this.timezone = nTimezone; +}; + +cXSGYearMonth.prototype = new cXSAnyAtomicType; +cXSGYearMonth.prototype.builtInKind = cXSConstants.GYEARMONTH_DT; +cXSGYearMonth.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_GYEARMONTH; + +cXSGYearMonth.prototype.year = null; +cXSGYearMonth.prototype.month = null; +cXSGYearMonth.prototype.timezone= null; + +cXSGYearMonth.prototype.toString = function() { + return fXSDateTime_pad(this.year) + + '-' + fXSDateTime_pad(this.month) + + fXSDateTime_getTZComponent(this); +}; + +var rXSGYearMonth = /^-?([1-9]\d\d\d+|0\d\d\d)-(0[1-9]|1[0-2])(Z|([+\-])(0\d|1[0-4]):([0-5]\d))?$/; +cXSGYearMonth.cast = function(vValue) { + if (vValue instanceof cXSGYearMonth) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSGYearMonth); + if (aMatch) { + var nYear = +aMatch[1], + nMonth = +aMatch[2]; + return new cXSGYearMonth( nYear, + nMonth, + aMatch[3] ? aMatch[3] == 'Z' ? 0 : (aMatch[4] == '-' ? -1 : 1) * (aMatch[5] * 60 + aMatch[6] * 1) : null + ); + } + throw new cException("FORG0001"); + } + if (vValue instanceof cXSDate || vValue instanceof cXSDateTime) + return new cXSGYearMonth(vValue.year, vValue.month, vValue.timezone); + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("gYearMonth", cXSGYearMonth); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSHexBinary(sValue) { + this.value = sValue; +}; + +cXSHexBinary.prototype = new cXSAnyAtomicType; +cXSHexBinary.prototype.builtInKind = cXSConstants.HEXBINARY_DT; +cXSHexBinary.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_HEXBINARY; + +cXSHexBinary.prototype.value = null; + +cXSHexBinary.prototype.valueOf = function() { + return this.value; +}; + +cXSHexBinary.prototype.toString = function() { + return this.value; +}; + +var rXSHexBinary = /^([0-9a-fA-F]{2})*$/; +cXSHexBinary.cast = function(vValue) { + if (vValue instanceof cXSHexBinary) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSHexBinary); + if (aMatch) + return new cXSHexBinary(aMatch[0].toUpperCase()); + throw new cException("FORG0001"); + } + if (vValue instanceof cXSBase64Binary) { + var sValue = fWindow_atob(vValue.valueOf()), + aValue = []; + for (var nIndex = 0, nLength = sValue.length, sLetter; nIndex < nLength; nIndex++) { + sLetter = sValue.charCodeAt(nIndex).toString(16); + aValue.push(new cArray(3 - sLetter.length).join('0') + sLetter); + } + return new cXSHexBinary(aValue.join('')); + } + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("hexBinary", cXSHexBinary); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSNOTATION() { + +}; + +cXSNOTATION.prototype = new cXSAnyAtomicType; +cXSNOTATION.prototype.builtInKind = cXSConstants.NOTATION_DT; +cXSNOTATION.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_NOTATION; + +cXSNOTATION.cast = function(vValue) { + throw new cException("XPST0017" + + ); // {http://www.w3.org/2001/XMLSchema}NOTATION +}; + +// +fStaticContext_defineSystemDataType("NOTATION", cXSNOTATION); + + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSQName(sPrefix, sLocalName, sNameSpaceURI) { + this.prefix = sPrefix; + this.localName = sLocalName; + this.namespaceURI = sNameSpaceURI; +}; + +cXSQName.prototype = new cXSAnyAtomicType; +cXSQName.prototype.builtInKind = cXSConstants.QNAME_DT; +cXSQName.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_QNAME; + +cXSQName.prototype.prefix = null; +cXSQName.prototype.localName = null; +cXSQName.prototype.namespaceURI = null; + +cXSQName.prototype.toString = function() { + return (this.prefix ? this.prefix + ':' : '') + this.localName; +}; + +var rXSQName = /^(?:(?![0-9-])(\w[\w.-]*)\:)?(?![0-9-])(\w[\w.-]*)$/; +cXSQName.cast = function(vValue) { + if (vValue instanceof cXSQName) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSQName); + if (aMatch) + return new cXSQName(aMatch[1] || null, aMatch[2], null); + throw new cException("FORG0001"); + } + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("QName", cXSQName); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSString(sValue) { + this.value = sValue; +}; + +cXSString.prototype = new cXSAnyAtomicType; + +cXSString.prototype.value = null; +cXSString.prototype.builtInKind = cXSConstants.STRING_DT; +cXSString.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_STRING; + +cXSString.prototype.valueOf = function() { + return this.value; +}; + +cXSString.prototype.toString = function() { + return this.value; +}; + +cXSString.cast = function(vValue) { + return new cXSString(cString(vValue)); + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("string", cXSString); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSTime(nHours, nMinutes, nSeconds, nTimezone) { + this.hours = nHours; + this.minutes = nMinutes; + this.seconds = nSeconds; + this.timezone = nTimezone; +}; + +cXSTime.prototype = new cXSAnyAtomicType; +cXSTime.prototype.builtInKind = cXSConstants.TIME_DT; +cXSTime.prototype.primitiveKind = cXSAnySimpleType.PRIMITIVE_TIME; + +cXSTime.prototype.hours = null; +cXSTime.prototype.minutes = null; +cXSTime.prototype.seconds = null; +cXSTime.prototype.timezone = null; + +cXSTime.prototype.toString = function() { + return fXSDateTime_getTimeComponent(this) + + fXSDateTime_getTZComponent(this); +}; + +var rXSTime = /^(([01]\d|2[0-3]):([0-5]\d):([0-5]\d)(?:\.(\d+))?|(24:00:00)(?:\.(0+))?)(Z|([+\-])(0\d|1[0-4]):([0-5]\d))?$/; +cXSTime.cast = function(vValue) { + if (vValue instanceof cXSTime) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSTime); + if (aMatch) { + var bValue = !!aMatch[6]; + return new cXSTime(bValue ? 0 : +aMatch[2], + bValue ? 0 : +aMatch[3], + cNumber((bValue ? 0 : aMatch[4]) + '.' + (bValue ? 0 : aMatch[5] || 0)), + aMatch[8] ? aMatch[8] == 'Z' ? 0 : (aMatch[9] == '-' ? -1 : 1) * (aMatch[10] * 60 + aMatch[11] * 1) : null + ); + } + throw new cException("FORG0001"); + } + if (vValue instanceof cXSDateTime) + return new cXSTime(vValue.hours, vValue.minutes, vValue.seconds, vValue.timezone); + // + throw new cException("XPTY0004" + + ); +}; + +// +function fXSTime_normalize(oValue) { + // + if (oValue.seconds >= 60 || oValue.seconds < 0) { + oValue.minutes += ~~(oValue.seconds / 60) - (oValue.seconds < 0 && oValue.seconds % 60 ? 1 : 0); + oValue.seconds = oValue.seconds % 60 + (oValue.seconds < 0 && oValue.seconds % 60 ? 60 : 0); + } + // + if (oValue.minutes >= 60 || oValue.minutes < 0) { + oValue.hours += ~~(oValue.minutes / 60) - (oValue.minutes < 0 && oValue.minutes % 60 ? 1 : 0); + oValue.minutes = oValue.minutes % 60 + (oValue.minutes < 0 && oValue.minutes % 60 ? 60 : 0); + } + // + if (oValue.hours >= 24 || oValue.hours < 0) { + if (oValue instanceof cXSDateTime) + oValue.day += ~~(oValue.hours / 24) - (oValue.hours < 0 && oValue.hours % 24 ? 1 : 0); + oValue.hours = oValue.hours % 24 + (oValue.hours < 0 && oValue.hours % 24 ? 24 : 0); + } + // + return oValue; +}; + +// +fStaticContext_defineSystemDataType("time", cXSTime); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSUntypedAtomic(sValue) { + this.value = sValue; +}; + +cXSUntypedAtomic.prototype = new cXSAnyAtomicType; +cXSUntypedAtomic.prototype.builtInKind = cXSConstants.XT_UNTYPEDATOMIC_DT; + +cXSUntypedAtomic.prototype.toString = function() { + return cString(this.value); +}; + +cXSUntypedAtomic.cast = function(vValue) { + if (vValue instanceof cXSUntypedAtomic) + return vValue; + + return new cXSUntypedAtomic(cString(vValue)); + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("untypedAtomic", cXSUntypedAtomic); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSYearMonthDuration(nYear, nMonth, bNegative) { + cXSDuration.call(this, nYear, nMonth, 0, 0, 0, 0, bNegative); +}; + +cXSYearMonthDuration.prototype = new cXSDuration; +cXSYearMonthDuration.prototype.builtInKind = cXSConstants.XT_YEARMONTHDURATION_DT; + +cXSYearMonthDuration.prototype.toString = function() { + return (this.negative ? '-' : '') + 'P' + + (fXSDuration_getYearMonthComponent(this) || '0M'); +}; + +var rXSYearMonthDuration = /^(-)?P(?:([0-9]+)Y)?(?:([0-9]+)M)?$/; +cXSYearMonthDuration.cast = function(vValue) { + if (vValue instanceof cXSYearMonthDuration) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSYearMonthDuration); + if (aMatch) + return fXSYearMonthDuration_normalize(new cXSYearMonthDuration(+aMatch[2] || 0, +aMatch[3] || 0, aMatch[1] == '-')); + throw new cException("FORG0001"); + } + if (vValue instanceof cXSDayTimeDuration) + return new cXSYearMonthDuration(0, 0); + if (vValue instanceof cXSDuration) + return new cXSYearMonthDuration(vValue.year, vValue.month, vValue.negative); + // + throw new cException("XPTY0004" + + ); +}; + +// +function fXSYearMonthDuration_normalize(oDuration) { + if (oDuration.month >= 12) { + oDuration.year += ~~(oDuration.month / 12); + oDuration.month %= 12; + } + return oDuration; +}; + +// +fStaticContext_defineSystemDataType("yearMonthDuration", cXSYearMonthDuration); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSDayTimeDuration(nDay, nHours, nMinutes, nSeconds, bNegative) { + cXSDuration.call(this, 0, 0, nDay, nHours, nMinutes, nSeconds, bNegative); +}; + +cXSDayTimeDuration.prototype = new cXSDuration; +cXSDayTimeDuration.prototype.builtInKind = cXSConstants.DAYTIMEDURATION_DT; + +cXSDayTimeDuration.prototype.toString = function() { + return (this.negative ? '-' : '') + 'P' + + (fXSDuration_getDayTimeComponent(this) || 'T0S'); +}; + +var rXSDayTimeDuration = /^(-)?P(?:([0-9]+)D)?(?:T(?:([0-9]+)H)?(?:([0-9]+)M)?(?:((?:(?:[0-9]+(?:.[0-9]*)?)|(?:.[0-9]+)))S)?)?$/; +cXSDayTimeDuration.cast = function(vValue) { + if (vValue instanceof cXSDayTimeDuration) + return vValue; + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSDayTimeDuration); + if (aMatch) + return fXSDayTimeDuration_normalize(new cXSDayTimeDuration(+aMatch[2] || 0, +aMatch[3] || 0, +aMatch[4] || 0, +aMatch[5] || 0, aMatch[1] == '-')); + throw new cException("FORG0001"); + } + if (vValue instanceof cXSYearMonthDuration) + return new cXSDayTimeDuration(0, 0, 0, 0); + if (vValue instanceof cXSDuration) + return new cXSDayTimeDuration(vValue.day, vValue.hours, vValue.minutes, vValue.seconds, vValue.negative); + // + throw new cException("XPTY0004" + + ); +}; + +// Utilities +function fXSDayTimeDuration_normalize(oDuration) { + if (oDuration.seconds >= 60) { + oDuration.minutes += ~~(oDuration.seconds / 60); + oDuration.seconds %= 60; + } + if (oDuration.minutes >= 60) { + oDuration.hours += ~~(oDuration.minutes / 60); + oDuration.minutes %= 60; + } + if (oDuration.hours >= 24) { + oDuration.day += ~~(oDuration.hours / 24); + oDuration.hours %= 24; + } + return oDuration; +}; + +// +fStaticContext_defineSystemDataType("dayTimeDuration", cXSDayTimeDuration); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSInteger(nValue) { + this.value = nValue; +}; + +cXSInteger.prototype = new cXSDecimal; +cXSInteger.prototype.builtInKind = cXSConstants.INTEGER_DT; + +var rXSInteger = /^[-+]?[0-9]+$/; +cXSInteger.cast = function(vValue) { + if (vValue instanceof cXSInteger) + return new cXSInteger(vValue.value); + if (vValue instanceof cXSString || vValue instanceof cXSUntypedAtomic) { + var aMatch = fString_trim(vValue).match(rXSInteger); + if (aMatch) + return new cXSInteger(+vValue); + throw new cException("FORG0001"); + } + if (vValue instanceof cXSBoolean) + return new cXSInteger(vValue * 1); + if (fXSAnyAtomicType_isNumeric(vValue)) { + if (!fIsNaN(vValue) && fIsFinite(vValue)) + return new cXSInteger(+vValue); + throw new cException("FOCA0002" + + ); + } + // + throw new cException("XPTY0004" + + ); +}; + +// +fStaticContext_defineSystemDataType("integer", cXSInteger); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSNonPositiveInteger(nValue) { + this.value = nValue; +}; + +cXSNonPositiveInteger.prototype = new cXSInteger; +cXSNonPositiveInteger.prototype.builtInKind = cXSConstants.NONPOSITIVEINTEGER_DT; + +cXSNonPositiveInteger.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value <= 0) + return new cXSNonPositiveInteger(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("nonPositiveInteger", cXSNonPositiveInteger); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSNegativeInteger(nValue) { + this.value = nValue; +}; + +cXSNegativeInteger.prototype = new cXSNonPositiveInteger; +cXSNegativeInteger.prototype.builtInKind = cXSConstants.NEGATIVEINTEGER_DT; + +cXSNegativeInteger.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value <= -1) + return new cXSNegativeInteger(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("negativeInteger", cXSNegativeInteger); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSLong(nValue) { + this.value = nValue; +}; + +cXSLong.prototype = new cXSInteger; +cXSLong.prototype.builtInKind = cXSConstants.LONG_DT; + +cXSLong.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value <= 9223372036854775807 && oValue.value >= -9223372036854775808) + return new cXSLong(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("long", cXSLong); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSInt(nValue) { + this.value = nValue; +}; + +cXSInt.prototype = new cXSLong; +cXSInt.prototype.builtInKind = cXSConstants.INT_DT; + +cXSInt.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value <= 2147483647 && oValue.value >= -2147483648) + return new cXSInt(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("int", cXSInt); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSShort(nValue) { + this.value = nValue; +}; + +cXSShort.prototype = new cXSInt; +cXSShort.prototype.builtInKind = cXSConstants.SHORT_DT; + +cXSShort.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value <= 32767 && oValue.value >= -32768) + return new cXSShort(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("short", cXSShort); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSByte(nValue) { + this.value = nValue; +}; + +cXSByte.prototype = new cXSShort; +cXSByte.prototype.builtInKind = cXSConstants.BYTE_DT; + +cXSByte.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value <= 127 && oValue.value >= -128) + return new cXSByte(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("byte", cXSByte); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSNonNegativeInteger(nValue) { + this.value = nValue; +}; + +cXSNonNegativeInteger.prototype = new cXSInteger; +cXSNonNegativeInteger.prototype.builtInKind = cXSConstants.NONNEGATIVEINTEGER_DT; + +cXSNonNegativeInteger.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value >= 0) + return new cXSNonNegativeInteger(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("nonNegativeInteger", cXSNonNegativeInteger); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSPositiveInteger(nValue) { + this.value = nValue; +}; + +cXSPositiveInteger.prototype = new cXSNonNegativeInteger; +cXSPositiveInteger.prototype.builtInKind = cXSConstants.POSITIVEINTEGER_DT; + +cXSPositiveInteger.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value >= 1) + return new cXSPositiveInteger(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("positiveInteger", cXSPositiveInteger); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSUnsignedLong(nValue) { + this.value = nValue; +}; + +cXSUnsignedLong.prototype = new cXSNonNegativeInteger; +cXSUnsignedLong.prototype.builtInKind = cXSConstants.UNSIGNEDLONG_DT; + +cXSUnsignedLong.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value >= 1 && oValue.value <= 18446744073709551615) + return new cXSUnsignedLong(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("unsignedLong", cXSUnsignedLong); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSUnsignedInt(nValue) { + this.value = nValue; +}; + +cXSUnsignedInt.prototype = new cXSNonNegativeInteger; +cXSUnsignedInt.prototype.builtInKind = cXSConstants.UNSIGNEDINT_DT; + +cXSUnsignedInt.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value >= 1 && oValue.value <= 4294967295) + return new cXSUnsignedInt(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("unsignedInt", cXSUnsignedInt); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSUnsignedShort(nValue) { + this.value = nValue; +}; + +cXSUnsignedShort.prototype = new cXSUnsignedInt; +cXSUnsignedShort.prototype.builtInKind = cXSConstants.UNSIGNEDSHORT_DT; + +cXSUnsignedShort.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value >= 1 && oValue.value <= 65535) + return new cXSUnsignedShort(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("unsignedShort", cXSUnsignedShort); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSUnsignedByte(nValue) { + this.value = nValue; +}; + +cXSUnsignedByte.prototype = new cXSUnsignedShort; +cXSUnsignedByte.prototype.builtInKind = cXSConstants.UNSIGNEDBYTE_DT; + +cXSUnsignedByte.cast = function(vValue) { + var oValue; + try { + oValue = cXSInteger.cast(vValue); + } + catch (oError) { + throw oError; + } + // facet validation + if (oValue.value >= 1 && oValue.value <= 255) + return new cXSUnsignedByte(oValue.value); + // + throw new cException("FORG0001"); +}; + +// +fStaticContext_defineSystemDataType("unsignedByte", cXSUnsignedByte); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSNormalizedString(sValue) { + this.value = sValue; +}; + +cXSNormalizedString.prototype = new cXSString; +cXSNormalizedString.prototype.builtInKind = cXSConstants.NORMALIZEDSTRING_DT; + +cXSNormalizedString.cast = function(vValue) { + return new cXSNormalizedString(cString(vValue)); +}; + +// +fStaticContext_defineSystemDataType("normalizedString", cXSNormalizedString); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSToken(sValue) { + this.value = sValue; +}; + +cXSToken.prototype = new cXSNormalizedString; +cXSToken.prototype.builtInKind = cXSConstants.TOKEN_DT; + +cXSToken.cast = function(vValue) { + return new cXSToken(cString(vValue)); +}; + +// +fStaticContext_defineSystemDataType("token", cXSToken); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSName(sValue) { + this.value = sValue; +}; + +cXSName.prototype = new cXSToken; +cXSName.prototype.builtInKind = cXSConstants.NAME_DT; + +cXSName.cast = function(vValue) { + return new cXSName(cString(vValue)); +}; + +// +fStaticContext_defineSystemDataType("Name", cXSName); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSNCName(sValue) { + this.value = sValue; +}; + +cXSNCName.prototype = new cXSName; +cXSNCName.prototype.builtInKind = cXSConstants.NCNAME_DT; + +cXSNCName.cast = function(vValue) { + return new cXSNCName(cString(vValue)); +}; + +// +fStaticContext_defineSystemDataType("NCName", cXSNCName); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSENTITY(sValue) { + this.value = sValue; +}; + +cXSENTITY.prototype = new cXSNCName; +cXSENTITY.prototype.builtInKind = cXSConstants.ENTITY_DT; + +cXSENTITY.cast = function(vValue) { + return new cXSENTITY(cString(vValue)); +}; + +// +fStaticContext_defineSystemDataType("ENTITY", cXSENTITY); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSID(sValue) { + this.value = sValue; +}; + +cXSID.prototype = new cXSNCName; +cXSID.prototype.builtInKind = cXSConstants.ID_DT; + +cXSID.cast = function(vValue) { + return new cXSID(cString(vValue)); +}; + +// +fStaticContext_defineSystemDataType("ID", cXSID); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSIDREF(sValue) { + this.value = sValue; +}; + +cXSIDREF.prototype = new cXSNCName; +cXSIDREF.prototype.builtInKind = cXSConstants.IDREF_DT; + +cXSIDREF.cast = function(vValue) { + return new cXSIDREF(cString(vValue)); +}; + +// +fStaticContext_defineSystemDataType("IDREF", cXSIDREF); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSLanguage(sValue) { + this.value = sValue; +}; + +cXSLanguage.prototype = new cXSToken; +cXSLanguage.prototype.builtInKind = cXSConstants.LANGUAGE_DT; + +cXSLanguage.cast = function(vValue) { + return new cXSLanguage(cString(vValue)); +}; + +// +fStaticContext_defineSystemDataType("language", cXSLanguage); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXSNMTOKEN(sValue) { + this.value = sValue; +}; + +cXSNMTOKEN.prototype = new cXSToken; +cXSNMTOKEN.prototype.builtInKind = cXSConstants.NMTOKEN_DT; + +cXSNMTOKEN.cast = function(vValue) { + return new cXSNMTOKEN(cString(vValue)); +}; + +// +fStaticContext_defineSystemDataType("NMTOKEN", cXSNMTOKEN); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXTItem() { + +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXTNode() { + +}; + +cXTNode.prototype = new cXTItem; + + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXTAttribute() { + +}; + +cXTAttribute.prototype = new cXTNode; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXTComment() { + +}; + +cXTComment.prototype = new cXTNode; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXTDocument() { + +}; + +cXTDocument.prototype = new cXTNode; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXTElement() { + +}; + +cXTElement.prototype = new cXTNode; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXTProcessingInstruction() { + +}; + +cXTProcessingInstruction.prototype = new cXTNode; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +function cXTText() { + +}; + +cXTText.prototype = new cXTNode; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 12.1 Comparisons of base64Binary and hexBinary Values + op:hexBinary-equal + op:base64Binary-equal +*/ +hStaticContext_operators["hexBinary-equal"] = function(oLeft, oRight) { + return new cXSBoolean(oLeft.valueOf() == oRight.valueOf()); +}; + +hStaticContext_operators["base64Binary-equal"] = function(oLeft, oRight) { + return new cXSBoolean(oLeft.valueOf() == oRight.valueOf()); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 9.2 Operators on Boolean Values + op:boolean-equal + op:boolean-less-than + op:boolean-greater-than +*/ + +// 9.2 Operators on Boolean Values +// op:boolean-equal($value1 as xs:boolean, $value2 as xs:boolean) as xs:boolean +hStaticContext_operators["boolean-equal"] = function(oLeft, oRight) { + return new cXSBoolean(oLeft.valueOf() == oRight.valueOf()); +}; + +// op:boolean-less-than($arg1 as xs:boolean, $arg2 as xs:boolean) as xs:boolean +hStaticContext_operators["boolean-less-than"] = function(oLeft, oRight) { + return new cXSBoolean(oLeft.valueOf() < oRight.valueOf()); +}; + +// op:boolean-greater-than($arg1 as xs:boolean, $arg2 as xs:boolean) as xs:boolean +hStaticContext_operators["boolean-greater-than"] = function(oLeft, oRight) { + return new cXSBoolean(oLeft.valueOf() > oRight.valueOf()); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 10.4 Comparison Operators on Duration, Date and Time Values + op:yearMonthDuration-less-than + op:yearMonthDuration-greater-than + op:dayTimeDuration-less-than + op:dayTimeDuration-greater-than + op:duration-equal + op:dateTime-equal + op:dateTime-less-than + op:dateTime-greater-than + op:date-equal + op:date-less-than + op:date-greater-than + op:time-equal + op:time-less-than + op:time-greater-than + op:gYearMonth-equal + op:gYear-equal + op:gMonthDay-equal + op:gMonth-equal + op:gDay-equal + + 10.6 Arithmetic Operators on Durations + op:add-yearMonthDurations + op:subtract-yearMonthDurations + op:multiply-yearMonthDuration + op:divide-yearMonthDuration + op:divide-yearMonthDuration-by-yearMonthDuration + op:add-dayTimeDurations + op:subtract-dayTimeDurations + op:multiply-dayTimeDuration + op:divide-dayTimeDuration + op:divide-dayTimeDuration-by-dayTimeDuration + + + 10.8 Arithmetic Operators on Durations, Dates and Times + op:subtract-dateTimes + op:subtract-dates + op:subtract-times + op:add-yearMonthDuration-to-dateTime + op:add-dayTimeDuration-to-dateTime + op:subtract-yearMonthDuration-from-dateTime + op:subtract-dayTimeDuration-from-dateTime + op:add-yearMonthDuration-to-date + op:add-dayTimeDuration-to-date + op:subtract-yearMonthDuration-from-date + op:subtract-dayTimeDuration-from-date + op:add-dayTimeDuration-to-time + op:subtract-dayTimeDuration-from-time + +*/ + +// 10.4 Comparison Operators on Duration, Date and Time Values +// op:yearMonthDuration-less-than($arg1 as xs:yearMonthDuration, $arg2 as xs:yearMonthDuration) as xs:boolean +hStaticContext_operators["yearMonthDuration-less-than"] = function(oLeft, oRight) { + return new cXSBoolean(fOperator_yearMonthDuration_toMonths(oLeft) < fOperator_yearMonthDuration_toMonths(oRight)); +}; + +// op:yearMonthDuration-greater-than($arg1 as xs:yearMonthDuration, $arg2 as xs:yearMonthDuration) as xs:boolean +hStaticContext_operators["yearMonthDuration-greater-than"] = function(oLeft, oRight) { + return new cXSBoolean(fOperator_yearMonthDuration_toMonths(oLeft) > fOperator_yearMonthDuration_toMonths(oRight)); +}; + +// op:dayTimeDuration-less-than($arg1 as dayTimeDuration, $arg2 as dayTimeDuration) as xs:boolean +hStaticContext_operators["dayTimeDuration-less-than"] = function(oLeft, oRight) { + return new cXSBoolean(fOperator_dayTimeDuration_toSeconds(oLeft) < fOperator_dayTimeDuration_toSeconds(oRight)); +}; + +// op:dayTimeDuration-greater-than($arg1 as dayTimeDuration, $arg2 as dayTimeDuration) as xs:boolean +hStaticContext_operators["dayTimeDuration-greater-than"] = function(oLeft, oRight) { + return new cXSBoolean(fOperator_dayTimeDuration_toSeconds(oLeft) > fOperator_dayTimeDuration_toSeconds(oRight)); +}; + +// op:duration-equal($arg1 as xs:duration, $arg2 as xs:duration) as xs:boolean +hStaticContext_operators["duration-equal"] = function(oLeft, oRight) { + return new cXSBoolean(oLeft.negative == oRight.negative + && fOperator_yearMonthDuration_toMonths(oLeft) == fOperator_yearMonthDuration_toMonths(oRight) + && fOperator_dayTimeDuration_toSeconds(oLeft) == fOperator_dayTimeDuration_toSeconds(oRight)); +}; + +// op:dateTime-equal($arg1 as xs:dateTime, $arg2 as xs:dateTime) as xs:boolean +hStaticContext_operators["dateTime-equal"] = function(oLeft, oRight) { + return fOperator_compareDateTimes(oLeft, oRight, 'eq'); +}; + +// op:dateTime-less-than($arg1 as xs:dateTime, $arg2 as xs:dateTime) as xs:boolean +hStaticContext_operators["dateTime-less-than"] = function(oLeft, oRight) { + return fOperator_compareDateTimes(oLeft, oRight, 'lt'); +}; + +//op:dateTime-greater-than($arg1 as xs:dateTime, $arg2 as xs:dateTime) as xs:boolean +hStaticContext_operators["dateTime-greater-than"] = function(oLeft, oRight) { + return fOperator_compareDateTimes(oLeft, oRight, 'gt'); +}; + +// op:date-equal($arg1 as xs:date, $arg2 as xs:date) as xs:boolean +hStaticContext_operators["date-equal"] = function(oLeft, oRight) { + return fOperator_compareDates(oLeft, oRight, 'eq'); +}; + +// op:date-less-than($arg1 as xs:date, $arg2 as xs:date) as xs:boolean +hStaticContext_operators["date-less-than"] = function(oLeft, oRight) { + return fOperator_compareDates(oLeft, oRight, 'lt'); +}; + +// op:date-greater-than($arg1 as xs:date, $arg2 as xs:date) as xs:boolean +hStaticContext_operators["date-greater-than"] = function(oLeft, oRight) { + return fOperator_compareDates(oLeft, oRight, 'gt'); +}; + +// op:time-equal($arg1 as xs:time, $arg2 as xs:time) as xs:boolean +hStaticContext_operators["time-equal"] = function(oLeft, oRight) { + return fOperator_compareTimes(oLeft, oRight, 'eq'); +}; + +// op:time-less-than($arg1 as xs:time, $arg2 as xs:time) as xs:boolean +hStaticContext_operators["time-less-than"] = function(oLeft, oRight) { + return fOperator_compareTimes(oLeft, oRight, 'lt'); +}; + +// op:time-greater-than($arg1 as xs:time, $arg2 as xs:time) as xs:boolean +hStaticContext_operators["time-greater-than"] = function(oLeft, oRight) { + return fOperator_compareTimes(oLeft, oRight, 'gt'); +}; + +// op:gYearMonth-equal($arg1 as xs:gYearMonth, $arg2 as xs:gYearMonth) as xs:boolean +hStaticContext_operators["gYearMonth-equal"] = function(oLeft, oRight) { + return fOperator_compareDateTimes( + new cXSDateTime(oLeft.year, oLeft.month, fXSDate_getDaysForYearMonth(oLeft.year, oLeft.month), 0, 0, 0, oLeft.timezone == null ? this.timezone : oLeft.timezone), + new cXSDateTime(oRight.year, oRight.month, fXSDate_getDaysForYearMonth(oRight.year, oRight.month), 0, 0, 0, oRight.timezone == null ? this.timezone : oRight.timezone), + 'eq' + ); +}; + +// op:gYear-equal($arg1 as xs:gYear, $arg2 as xs:gYear) as xs:boolean +hStaticContext_operators["gYear-equal"] = function(oLeft, oRight) { + return fOperator_compareDateTimes( + new cXSDateTime(oLeft.year, 1, 1, 0, 0, 0, oLeft.timezone == null ? this.timezone : oLeft.timezone), + new cXSDateTime(oRight.year, 1, 1, 0, 0, 0, oRight.timezone == null ? this.timezone : oRight.timezone), + 'eq' + ); +}; + +// op:gMonthDay-equal($arg1 as xs:gMonthDay, $arg2 as xs:gMonthDay) as xs:boolean +hStaticContext_operators["gMonthDay-equal"] = function(oLeft, oRight) { + return fOperator_compareDateTimes( + new cXSDateTime(1972, oLeft.month, oLeft.day, 0, 0, 0, oLeft.timezone == null ? this.timezone : oLeft.timezone), + new cXSDateTime(1972, oRight.month, oRight.day, 0, 0, 0, oRight.timezone == null ? this.timezone : oRight.timezone), + 'eq' + ); +}; + +// op:gMonth-equal($arg1 as xs:gMonth, $arg2 as xs:gMonth) as xs:boolean +hStaticContext_operators["gMonth-equal"] = function(oLeft, oRight) { + return fOperator_compareDateTimes( + new cXSDateTime(1972, oLeft.month, fXSDate_getDaysForYearMonth(1972, oRight.month), 0, 0, 0, oLeft.timezone == null ? this.timezone : oLeft.timezone), + new cXSDateTime(1972, oRight.month, fXSDate_getDaysForYearMonth(1972, oRight.month), 0, 0, 0, oRight.timezone == null ? this.timezone : oRight.timezone), + 'eq' + ); +}; + +// op:gDay-equal($arg1 as xs:gDay, $arg2 as xs:gDay) as xs:boolean +hStaticContext_operators["gDay-equal"] = function(oLeft, oRight) { + return fOperator_compareDateTimes( + new cXSDateTime(1972, 12, oLeft.day, 0, 0, 0, oLeft.timezone == null ? this.timezone : oLeft.timezone), + new cXSDateTime(1972, 12, oRight.day, 0, 0, 0, oRight.timezone == null ? this.timezone : oRight.timezone), + 'eq' + ); +}; + +// 10.6 Arithmetic Operators on Durations +// op:add-yearMonthDurations($arg1 as xs:yearMonthDuration, $arg2 as xs:yearMonthDuration) as xs:yearMonthDuration +hStaticContext_operators["add-yearMonthDurations"] = function(oLeft, oRight) { + return fOperator_yearMonthDuration_fromMonths(fOperator_yearMonthDuration_toMonths(oLeft) + fOperator_yearMonthDuration_toMonths(oRight)); +}; + +// op:subtract-yearMonthDurations($arg1 as xs:yearMonthDuration, $arg2 as xs:yearMonthDuration) as xs:yearMonthDuration +hStaticContext_operators["subtract-yearMonthDurations"] = function(oLeft, oRight) { + return fOperator_yearMonthDuration_fromMonths(fOperator_yearMonthDuration_toMonths(oLeft) - fOperator_yearMonthDuration_toMonths(oRight)); +}; + +// op:multiply-yearMonthDuration($arg1 as xs:yearMonthDuration, $arg2 as xs:double) as xs:yearMonthDuration +hStaticContext_operators["multiply-yearMonthDuration"] = function(oLeft, oRight) { + return fOperator_yearMonthDuration_fromMonths(fOperator_yearMonthDuration_toMonths(oLeft) * oRight); +}; + +// op:divide-yearMonthDuration($arg1 as xs:yearMonthDuration, $arg2 as xs:double) as xs:yearMonthDuration +hStaticContext_operators["divide-yearMonthDuration"] = function(oLeft, oRight) { + return fOperator_yearMonthDuration_fromMonths(fOperator_yearMonthDuration_toMonths(oLeft) / oRight); +}; + +// op:divide-yearMonthDuration-by-yearMonthDuration($arg1 as xs:yearMonthDuration, $arg2 as xs:yearMonthDuration) as xs:decimal +hStaticContext_operators["divide-yearMonthDuration-by-yearMonthDuration"] = function(oLeft, oRight) { + return new cXSDecimal(fOperator_yearMonthDuration_toMonths(oLeft) / fOperator_yearMonthDuration_toMonths(oRight)); +}; + +// op:add-dayTimeDurations($arg1 as xs:dayTimeDuration, $arg2 as xs:dayTimeDuration) as xs:dayTimeDuration +hStaticContext_operators["add-dayTimeDurations"] = function(oLeft, oRight) { + return fOperator_dayTimeDuration_fromSeconds(fOperator_dayTimeDuration_toSeconds(oLeft) + fOperator_dayTimeDuration_toSeconds(oRight)); +}; + +// op:subtract-dayTimeDurations($arg1 as xs:dayTimeDuration, $arg2 as xs:dayTimeDuration) as xs:dayTimeDuration +hStaticContext_operators["subtract-dayTimeDurations"] = function(oLeft, oRight) { + return fOperator_dayTimeDuration_fromSeconds(fOperator_dayTimeDuration_toSeconds(oLeft) - fOperator_dayTimeDuration_toSeconds(oRight)); +}; + +// op:multiply-dayTimeDurations($arg1 as xs:dayTimeDuration, $arg2 as xs:double) as xs:dayTimeDuration +hStaticContext_operators["multiply-dayTimeDuration"] = function(oLeft, oRight) { + return fOperator_dayTimeDuration_fromSeconds(fOperator_dayTimeDuration_toSeconds(oLeft) * oRight); +}; + +// op:divide-dayTimeDurations($arg1 as xs:dayTimeDuration, $arg2 as xs:double) as xs:dayTimeDuration +hStaticContext_operators["divide-dayTimeDuration"] = function(oLeft, oRight) { + return fOperator_dayTimeDuration_fromSeconds(fOperator_dayTimeDuration_toSeconds(oLeft) / oRight); +}; + +// op:divide-dayTimeDuration-by-dayTimeDuration($arg1 as xs:dayTimeDuration, $arg2 as xs:dayTimeDuration) as xs:decimal +hStaticContext_operators["divide-dayTimeDuration-by-dayTimeDuration"] = function(oLeft, oRight) { + return new cXSDecimal(fOperator_dayTimeDuration_toSeconds(oLeft) / fOperator_dayTimeDuration_toSeconds(oRight)); +}; + +// 10.8 Arithmetic Operators on Durations, Dates and Times +// op:subtract-dateTimes($arg1 as xs:dateTime, $arg2 as xs:dateTime) as xs:dayTimeDuration +hStaticContext_operators["subtract-dateTimes"] = function(oLeft, oRight) { + return fOperator_dayTimeDuration_fromSeconds(fOperator_dateTime_toSeconds(oLeft) - fOperator_dateTime_toSeconds(oRight)); +}; + +// op:subtract-dates($arg1 as xs:date, $arg2 as xs:date) as xs:dayTimeDuration +hStaticContext_operators["subtract-dates"] = function(oLeft, oRight) { + return fOperator_dayTimeDuration_fromSeconds(fOperator_dateTime_toSeconds(oLeft) - fOperator_dateTime_toSeconds(oRight)); +}; + +// op:subtract-times($arg1 as xs:time, $arg2 as xs:time) as xs:dayTimeDuration +hStaticContext_operators["subtract-times"] = function(oLeft, oRight) { + return fOperator_dayTimeDuration_fromSeconds(fOperator_time_toSeconds(oLeft) - fOperator_time_toSeconds(oRight)); +}; + +// op:add-yearMonthDuration-to-dateTime($arg1 as xs:dateTime, $arg2 as xs:yearMonthDuration) as xs:dateTime +hStaticContext_operators["add-yearMonthDuration-to-dateTime"] = function(oLeft, oRight) { + return fOperator_addYearMonthDuration2DateTime(oLeft, oRight, '+'); +}; + +// op:add-dayTimeDuration-to-dateTime($arg1 as xs:dateTime, $arg2 as xs:dayTimeDuration) as xs:dateTime +hStaticContext_operators["add-dayTimeDuration-to-dateTime"] = function(oLeft, oRight) { + return fOperator_addDayTimeDuration2DateTime(oLeft, oRight, '+'); +}; + +// op:subtract-yearMonthDuration-from-dateTime($arg1 as xs:dateTime, $arg2 as xs:yearMonthDuration) as xs:dateTime +hStaticContext_operators["subtract-yearMonthDuration-from-dateTime"] = function(oLeft, oRight) { + return fOperator_addYearMonthDuration2DateTime(oLeft, oRight, '-'); +}; + +// op:subtract-dayTimeDuration-from-dateTime($arg1 as xs:dateTime, $arg2 as xs:dayTimeDuration) as xs:dateTime +hStaticContext_operators["subtract-dayTimeDuration-from-dateTime"] = function(oLeft, oRight) { + return fOperator_addDayTimeDuration2DateTime(oLeft, oRight, '-'); +}; + +// op:add-yearMonthDuration-to-date($arg1 as xs:date, $arg2 as xs:yearMonthDuration) as xs:date +hStaticContext_operators["add-yearMonthDuration-to-date"] = function(oLeft, oRight) { + return fOperator_addYearMonthDuration2DateTime(oLeft, oRight, '+'); +}; + +// op:add-dayTimeDuration-to-date($arg1 as xs:date, $arg2 as xs:dayTimeDuration) as xs:date +hStaticContext_operators["add-dayTimeDuration-to-date"] = function(oLeft, oRight) { + return fOperator_addDayTimeDuration2DateTime(oLeft, oRight, '+'); +}; + +// op:subtract-yearMonthDuration-from-date($arg1 as xs:date, $arg2 as xs:yearMonthDuration) as xs:date +hStaticContext_operators["subtract-yearMonthDuration-from-date"] = function(oLeft, oRight) { + return fOperator_addYearMonthDuration2DateTime(oLeft, oRight, '-'); +}; + +// op:subtract-dayTimeDuration-from-date($arg1 as xs:date, $arg2 as xs:dayTimeDuration) as xs:date +hStaticContext_operators["subtract-dayTimeDuration-from-date"] = function(oLeft, oRight) { + return fOperator_addDayTimeDuration2DateTime(oLeft, oRight, '-'); +}; + +// op:add-dayTimeDuration-to-time($arg1 as xs:time, $arg2 as xs:dayTimeDuration) as xs:time +hStaticContext_operators["add-dayTimeDuration-to-time"] = function(oLeft, oRight) { + var oValue = new cXSTime(oLeft.hours, oLeft.minutes, oLeft.seconds, oLeft.timezone); + oValue.hours += oRight.hours; + oValue.minutes += oRight.minutes; + oValue.seconds += oRight.seconds; + // + return fXSTime_normalize(oValue); +}; + +// op:subtract-dayTimeDuration-from-time($arg1 as xs:time, $arg2 as xs:dayTimeDuration) as xs:time +hStaticContext_operators["subtract-dayTimeDuration-from-time"] = function(oLeft, oRight) { + var oValue = new cXSTime(oLeft.hours, oLeft.minutes, oLeft.seconds, oLeft.timezone); + oValue.hours -= oRight.hours; + oValue.minutes -= oRight.minutes; + oValue.seconds -= oRight.seconds; + // + return fXSTime_normalize(oValue); +}; + +function fOperator_compareTimes(oLeft, oRight, sComparator) { + var nLeft = fOperator_time_toSeconds(oLeft), + nRight = fOperator_time_toSeconds(oRight); + return new cXSBoolean(sComparator == 'lt' ? nLeft < nRight : sComparator == 'gt' ? nLeft > nRight : nLeft == nRight); +}; + +function fOperator_compareDates(oLeft, oRight, sComparator) { + return fOperator_compareDateTimes(cXSDateTime.cast(oLeft), cXSDateTime.cast(oRight), sComparator); +}; + +function fOperator_compareDateTimes(oLeft, oRight, sComparator) { + // Adjust object time zone to Z and compare as strings + var oTimezone = new cXSDayTimeDuration(0, 0, 0, 0), + sLeft = fFunction_dateTime_adjustTimezone(oLeft, oTimezone).toString(), + sRight = fFunction_dateTime_adjustTimezone(oRight, oTimezone).toString(); + return new cXSBoolean(sComparator == 'lt' ? sLeft < sRight : sComparator == 'gt' ? sLeft > sRight : sLeft == sRight); +}; + +function fOperator_addYearMonthDuration2DateTime(oLeft, oRight, sOperator) { + var oValue; + if (oLeft instanceof cXSDate) + oValue = new cXSDate(oLeft.year, oLeft.month, oLeft.day, oLeft.timezone, oLeft.negative); + else + if (oLeft instanceof cXSDateTime) + oValue = new cXSDateTime(oLeft.year, oLeft.month, oLeft.day, oLeft.hours, oLeft.minutes, oLeft.seconds, oLeft.timezone, oLeft.negative); + // + oValue.year = oValue.year + oRight.year * (sOperator == '-' ?-1 : 1); + oValue.month = oValue.month + oRight.month * (sOperator == '-' ?-1 : 1); + // + fXSDate_normalize(oValue, true); + // Correct day if out of month range + var nDay = fXSDate_getDaysForYearMonth(oValue.year, oValue.month); + if (oValue.day > nDay) + oValue.day = nDay; + // + return oValue; +}; + +function fOperator_addDayTimeDuration2DateTime(oLeft, oRight, sOperator) { + var oValue; + if (oLeft instanceof cXSDate) { + var nValue = (oRight.hours * 60 + oRight.minutes) * 60 + oRight.seconds; + oValue = new cXSDate(oLeft.year, oLeft.month, oLeft.day, oLeft.timezone, oLeft.negative); + oValue.day = oValue.day + oRight.day * (sOperator == '-' ?-1 : 1) - 1 * (nValue && sOperator == '-'); + // + fXSDate_normalize(oValue); + } + else + if (oLeft instanceof cXSDateTime) { + oValue = new cXSDateTime(oLeft.year, oLeft.month, oLeft.day, oLeft.hours, oLeft.minutes, oLeft.seconds, oLeft.timezone, oLeft.negative); + oValue.seconds = oValue.seconds + oRight.seconds * (sOperator == '-' ?-1 : 1); + oValue.minutes = oValue.minutes + oRight.minutes * (sOperator == '-' ?-1 : 1); + oValue.hours = oValue.hours + oRight.hours * (sOperator == '-' ?-1 : 1); + oValue.day = oValue.day + oRight.day * (sOperator == '-' ?-1 : 1); + // + fXSDateTime_normalize(oValue); + } + return oValue; +}; + +// xs:dayTimeDuration to/from seconds +function fOperator_dayTimeDuration_toSeconds(oDuration) { + return (((oDuration.day * 24 + oDuration.hours) * 60 + oDuration.minutes) * 60 + oDuration.seconds) * (oDuration.negative ? -1 : 1); +}; + +function fOperator_dayTimeDuration_fromSeconds(nValue) { + var bNegative =(nValue = cMath.round(nValue)) < 0, + nDays = ~~((nValue = cMath.abs(nValue)) / 86400), + nHours = ~~((nValue -= nDays * 3600 * 24) / 3600), + nMinutes= ~~((nValue -= nHours * 3600) / 60), + nSeconds = nValue -= nMinutes * 60; + return new cXSDayTimeDuration(nDays, nHours, nMinutes, nSeconds, bNegative); +}; + +// xs:yearMonthDuration to/from months +function fOperator_yearMonthDuration_toMonths(oDuration) { + return (oDuration.year * 12 + oDuration.month) * (oDuration.negative ? -1 : 1); +}; + +function fOperator_yearMonthDuration_fromMonths(nValue) { + var nNegative =(nValue = cMath.round(nValue)) < 0, + nYears = ~~((nValue = cMath.abs(nValue)) / 12), + nMonths = nValue -= nYears * 12; + return new cXSYearMonthDuration(nYears, nMonths, nNegative); +}; + +// xs:time to seconds +function fOperator_time_toSeconds(oTime) { + return oTime.seconds + (oTime.minutes - (oTime.timezone != null ? oTime.timezone % 60 : 0) + (oTime.hours - (oTime.timezone != null ? ~~(oTime.timezone / 60) : 0)) * 60) * 60; +}; + +// This function unlike all other date-related functions rely on interpretor's dateTime handling +function fOperator_dateTime_toSeconds(oValue) { + var oDate = new cDate((oValue.negative ? -1 : 1) * oValue.year, oValue.month, oValue.day, 0, 0, 0, 0); + if (oValue instanceof cXSDateTime) { + oDate.setHours(oValue.hours); + oDate.setMinutes(oValue.minutes); + oDate.setSeconds(oValue.seconds); + } + if (oValue.timezone != null) + oDate.setMinutes(oDate.getMinutes() - oValue.timezone); + return oDate.getTime() / 1000; +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 14 Functions and Operators on Nodes + op:is-same-node + op:node-before + op:node-after +*/ + +// 14 Operators on Nodes +// op:is-same-node($parameter1 as node(), $parameter2 as node()) as xs:boolean +hStaticContext_operators["is-same-node"] = function(oLeft, oRight) { + return new cXSBoolean(this.DOMAdapter.isSameNode(oLeft, oRight)); +}; + +// op:node-before($parameter1 as node(), $parameter2 as node()) as xs:boolean +hStaticContext_operators["node-before"] = function(oLeft, oRight) { + return new cXSBoolean(!!(this.DOMAdapter.compareDocumentPosition(oLeft, oRight) & 4)); +}; + +// op:node-after($parameter1 as node(), $parameter2 as node()) as xs:boolean +hStaticContext_operators["node-after"] = function(oLeft, oRight) { + return new cXSBoolean(!!(this.DOMAdapter.compareDocumentPosition(oLeft, oRight) & 2)); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 13.1 Operators on NOTATION + op:NOTATION-equal +*/ +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 6.2 Operators on Numeric Values + op:numeric-add + op:numeric-subtract + op:numeric-multiply + op:numeric-divide + op:numeric-integer-divide + op:numeric-mod + op:numeric-unary-plus + op:numeric-unary-minus + + 6.3 Comparison Operators on Numeric Values + op:numeric-equal + op:numeric-less-than + op:numeric-greater-than +*/ + +// 6.2 Operators on Numeric Values +function fFunctionCall_numeric_getPower(oLeft, oRight) { + if (fIsNaN(oLeft) || (cMath.abs(oLeft) == nInfinity) || fIsNaN(oRight) || (cMath.abs(oRight) == nInfinity)) + return 0; + var aLeft = cString(oLeft).match(rNumericLiteral), + aRight = cString(oRight).match(rNumericLiteral), + nPower = cMath.max(1, (aLeft[2] || aLeft[3] || '').length + (aLeft[5] || 0) * (aLeft[4] == '+' ?-1 : 1), (aRight[2] || aRight[3] || '').length + (aRight[5] || 0) * (aRight[4] == '+' ?-1 : 1)); + return nPower + (nPower % 2 ? 0 : 1); +}; + +// op:numeric-add($arg1 as numeric, $arg2 as numeric) as numeric +hStaticContext_operators["numeric-add"] = function(oLeft, oRight) { + var nLeft = oLeft.valueOf(), + nRight = oRight.valueOf(), + nPower = cMath.pow(10, fFunctionCall_numeric_getPower(nLeft, nRight)); + return fOperator_numeric_getResultOfType(oLeft, oRight, ((nLeft * nPower) + (nRight * nPower))/nPower); +}; + +// op:numeric-subtract($arg1 as numeric, $arg2 as numeric) as numeric +hStaticContext_operators["numeric-subtract"] = function(oLeft, oRight) { + var nLeft = oLeft.valueOf(), + nRight = oRight.valueOf(), + nPower = cMath.pow(10, fFunctionCall_numeric_getPower(nLeft, nRight)); + return fOperator_numeric_getResultOfType(oLeft, oRight, ((nLeft * nPower) - (nRight * nPower))/nPower); +}; + +// op:numeric-multiply($arg1 as numeric, $arg2 as numeric) as numeric +hStaticContext_operators["numeric-multiply"] = function(oLeft, oRight) { + var nLeft = oLeft.valueOf(), + nRight = oRight.valueOf(), + nPower = cMath.pow(10, fFunctionCall_numeric_getPower(nLeft, nRight)); + return fOperator_numeric_getResultOfType(oLeft, oRight, ((nLeft * nPower) * (nRight * nPower))/(nPower * nPower)); +}; + +// op:numeric-divide($arg1 as numeric, $arg2 as numeric) as numeric +hStaticContext_operators["numeric-divide"] = function(oLeft, oRight) { + var nLeft = oLeft.valueOf(), + nRight = oRight.valueOf(), + nPower = cMath.pow(10, fFunctionCall_numeric_getPower(nLeft, nRight)); + return fOperator_numeric_getResultOfType(oLeft, oRight, (oLeft * nPower) / (oRight * nPower)); +}; + +// op:numeric-integer-divide($arg1 as numeric, $arg2 as numeric) as xs:integer +hStaticContext_operators["numeric-integer-divide"] = function(oLeft, oRight) { + var oValue = oLeft / oRight; + return new cXSInteger(cMath.floor(oValue) + (oValue < 0)); +}; + +// op:numeric-mod($arg1 as numeric, $arg2 as numeric) as numeric +hStaticContext_operators["numeric-mod"] = function(oLeft, oRight) { + var nLeft = oLeft.valueOf(), + nRight = oRight.valueOf(), + nPower = cMath.pow(10, fFunctionCall_numeric_getPower(nLeft, nRight)); + return fOperator_numeric_getResultOfType(oLeft, oRight, ((nLeft * nPower) % (nRight * nPower)) / nPower); +}; + +// op:numeric-unary-plus($arg as numeric) as numeric +hStaticContext_operators["numeric-unary-plus"] = function(oRight) { + return oRight; +}; + +// op:numeric-unary-minus($arg as numeric) as numeric +hStaticContext_operators["numeric-unary-minus"] = function(oRight) { + oRight.value *=-1; + return oRight; +}; + + +// 6.3 Comparison Operators on Numeric Values +// op:numeric-equal($arg1 as numeric, $arg2 as numeric) as xs:boolean +hStaticContext_operators["numeric-equal"] = function(oLeft, oRight) { + return new cXSBoolean(oLeft.valueOf() == oRight.valueOf()); +}; + +// op:numeric-less-than($arg1 as numeric, $arg2 as numeric) as xs:boolean +hStaticContext_operators["numeric-less-than"] = function(oLeft, oRight) { + return new cXSBoolean(oLeft.valueOf() < oRight.valueOf()); +}; + +// op:numeric-greater-than($arg1 as numeric, $arg2 as numeric) as xs:boolean +hStaticContext_operators["numeric-greater-than"] = function(oLeft, oRight) { + return new cXSBoolean(oLeft.valueOf() > oRight.valueOf()); +}; + +function fOperator_numeric_getResultOfType(oLeft, oRight, nResult) { + return new (oLeft instanceof cXSInteger && oRight instanceof cXSInteger && nResult == cMath.round(nResult) ? cXSInteger : cXSDecimal)(nResult); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 11.2 Functions and Operators Related to QNames + op:QName-equal + +*/ + +// 11.2 Operators Related to QNames +// op:QName-equal($arg1 as xs:QName, $arg2 as xs:QName) as xs:boolean +hStaticContext_operators["QName-equal"] = function(oLeft, oRight) { + return new cXSBoolean(oLeft.localName == oRight.localName && oLeft.namespaceURI == oRight.namespaceURI); +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 15.1 General Functions and Operators on Sequences + op:concatenate + + 15.3 Equals, Union, Intersection and Except + op:union + op:intersect + op:except + + 15.5 Functions and Operators that Generate Sequences + op:to + +*/ + +// 15.1 General Functions and Operators on Sequences +// op:concatenate($seq1 as item()*, $seq2 as item()*) as item()* +hStaticContext_operators["concatenate"] = function(oSequence1, oSequence2) { + return oSequence1.concat(oSequence2); +}; + +// 15.3 Equals, Union, Intersection and Except +// op:union($parameter1 as node()*, $parameter2 as node()*) as node()* +hStaticContext_operators["union"] = function(oSequence1, oSequence2) { + var oSequence = []; + // Process first collection + for (var nIndex = 0, nLength = oSequence1.length, oItem; nIndex < nLength; nIndex++) { + if (!this.DOMAdapter.isNode(oItem = oSequence1[nIndex])) + throw new cException("XPTY0004" + + ); // Required item type of second operand of 'intersect' is node(); supplied value has item type xs:integer + // + if (fArray_indexOf(oSequence, oItem) ==-1) + oSequence.push(oItem); + } + // Process second collection + for (var nIndex = 0, nLength = oSequence2.length, oItem; nIndex < nLength; nIndex++) { + if (!this.DOMAdapter.isNode(oItem = oSequence2[nIndex])) + throw new cException("XPTY0004" + + ); // Required item type of second operand of 'intersect' is node(); supplied value has item type xs:integer + // + if (fArray_indexOf(oSequence, oItem) ==-1) + oSequence.push(oItem); + } + return fFunction_sequence_order(oSequence, this); +}; + +// op:intersect($parameter1 as node()*, $parameter2 as node()*) as node()* +hStaticContext_operators["intersect"] = function(oSequence1, oSequence2) { + var oSequence = []; + for (var nIndex = 0, nLength = oSequence1.length, oItem, bFound; nIndex < nLength; nIndex++) { + if (!this.DOMAdapter.isNode(oItem = oSequence1[nIndex])) + throw new cException("XPTY0004" + + ); // Required item type of second operand of 'intersect' is node(); supplied value has item type xs:integer + // + bFound = false; + for (var nRightIndex = 0, nRightLength = oSequence2.length;(nRightIndex < nRightLength) && !bFound; nRightIndex++) { + if (!this.DOMAdapter.isNode(oSequence2[nRightIndex])) + throw new cException("XPTY0004" + + ); + bFound = this.DOMAdapter.isSameNode(oSequence2[nRightIndex], oItem); + } + // + if (bFound && fArray_indexOf(oSequence, oItem) ==-1) + oSequence.push(oItem); + } + return fFunction_sequence_order(oSequence, this); +}; + +// op:except($parameter1 as node()*, $parameter2 as node()*) as node()* +hStaticContext_operators["except"] = function(oSequence1, oSequence2) { + var oSequence = []; + for (var nIndex = 0, nLength = oSequence1.length, oItem, bFound; nIndex < nLength; nIndex++) { + if (!this.DOMAdapter.isNode(oItem = oSequence1[nIndex])) + throw new cException("XPTY0004" + + ); // Required item type of second operand of 'intersect' is node(); supplied value has item type xs:integer + // + bFound = false; + for (var nRightIndex = 0, nRightLength = oSequence2.length;(nRightIndex < nRightLength) && !bFound; nRightIndex++) { + if (!this.DOMAdapter.isNode(oSequence2[nRightIndex])) + throw new cException("XPTY0004" + + ); + bFound = this.DOMAdapter.isSameNode(oSequence2[nRightIndex], oItem); + } + // + if (!bFound && fArray_indexOf(oSequence, oItem) ==-1) + oSequence.push(oItem); + } + return fFunction_sequence_order(oSequence, this); +}; + +// 15.5 Functions and Operators that Generate Sequences +// op:to($firstval as xs:integer, $lastval as xs:integer) as xs:integer* +hStaticContext_operators["to"] = function(oLeft, oRight) { + var oSequence = []; + for (var nIndex = oLeft.valueOf(), nLength = oRight.valueOf(); nIndex <= nLength; nIndex++) + oSequence.push(new cXSInteger(nIndex)); + // + return oSequence; +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 2 Accessors + node-name + nilled + string + data + base-uri + document-uri + +*/ + +// fn:node-name($arg as node()?) as xs:QName? +fStaticContext_defineSystemFunction("node-name", [[cXTNode, '?']], function(oNode) { + if (oNode != null) { + var fGetProperty = this.DOMAdapter.getProperty; + switch (fGetProperty(oNode, "nodeType")) { + case 1: // ELEMENT_NAME + case 2: // ATTRIBUTE_NODE + return new cXSQName(fGetProperty(oNode, "prefix"), fGetProperty(oNode, "localName"), fGetProperty(oNode, "namespaceURI")); + case 5: // ENTITY_REFERENCE_NODE + throw "Not implemented"; + case 6: // ENTITY_NODE + throw "Not implemented"; + case 7: // PROCESSING_INSTRUCTION_NODE + return new cXSQName(null, fGetProperty(oNode, "target"), null); + case 10: // DOCUMENT_TYPE_NODE + return new cXSQName(null, fGetProperty(oNode, "name"), null); + } + } + // + return null; +}); + +// fn:nilled($arg as node()?) as xs:boolean? +fStaticContext_defineSystemFunction("nilled", [[cXTNode, '?']], function(oNode) { + if (oNode != null) { + if (this.DOMAdapter.getProperty(oNode, "nodeType") == 1) + return new cXSBoolean(false); // TODO: Determine if node is nilled + } + // + return null; +}); + +// fn:string() as xs:string +// fn:string($arg as item()?) as xs:string +fStaticContext_defineSystemFunction("string", [[cXTItem, '?', true]], function(/*[*/oItem/*]*/) { + if (!arguments.length) { + if (!this.item) + throw new cException("XPDY0002"); + oItem = this.item; + } + return oItem == null ? new cXSString('') : cXSString.cast(fFunction_sequence_atomize([oItem], this)[0]); +}); + +// fn:data($arg as item()*) as xs:anyAtomicType* +fStaticContext_defineSystemFunction("data", [[cXTItem, '*']], function(oSequence1) { + return fFunction_sequence_atomize(oSequence1, this); +}); + +// fn:base-uri() as xs:anyURI? +// fn:base-uri($arg as node()?) as xs:anyURI? +fStaticContext_defineSystemFunction("base-uri", [[cXTNode, '?', true]], function(oNode) { + if (!arguments.length) { + if (!this.DOMAdapter.isNode(this.item)) + throw new cException("XPTY0004" + + ); + oNode = this.item; + } + // + return cXSAnyURI.cast(new cXSString(this.DOMAdapter.getProperty(oNode, "baseURI") || '')); +}); + +// fn:document-uri($arg as node()?) as xs:anyURI? +fStaticContext_defineSystemFunction("document-uri", [[cXTNode, '?']], function(oNode) { + if (oNode != null) { + var fGetProperty = this.DOMAdapter.getProperty; + if (fGetProperty(oNode, "nodeType") == 9) + return cXSAnyURI.cast(new cXSString(fGetProperty(oNode, "documentURI") || '')); + } + // + return null; +}); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 8 Functions on anyURI + resolve-uri +*/ + +// fn:resolve-uri($relative as xs:string?) as xs:anyURI? +// fn:resolve-uri($relative as xs:string?, $base as xs:string) as xs:anyURI? +fStaticContext_defineSystemFunction("resolve-uri", [[cXSString, '?'], [cXSString, '', true]], function(sUri, sBaseUri) { + if (arguments.length < 2) { + if (!this.DOMAdapter.isNode(this.item)) + throw new cException("XPTY0004" + + ); + sBaseUri = new cXSString(this.DOMAdapter.getProperty(this.item, "baseURI") || ''); + } + + if (sUri == null) + return null; + + // + if (sUri.valueOf() == '' || sUri.valueOf().charAt(0) == '#') + return cXSAnyURI.cast(sBaseUri); + + var oUri = cXSAnyURI.cast(sUri); + if (oUri.scheme) + return oUri; + + var oBaseUri = cXSAnyURI.cast(sBaseUri); + oUri.scheme = oBaseUri.scheme; + + if (!oUri.authority) { + // authority + oUri.authority = oBaseUri.authority; + + // path + if (oUri.path.charAt(0) != '/') { + var aUriSegments = oUri.path.split('/'), + aBaseUriSegments = oBaseUri.path.split('/'); + aBaseUriSegments.pop(); + + var nBaseUriStart = aBaseUriSegments[0] == '' ? 1 : 0; + for (var nIndex = 0, nLength = aUriSegments.length; nIndex < nLength; nIndex++) { + if (aUriSegments[nIndex] == '..') { + if (aBaseUriSegments.length > nBaseUriStart) + aBaseUriSegments.pop(); + else { + aBaseUriSegments.push(aUriSegments[nIndex]); + nBaseUriStart++; + } + } + else + if (aUriSegments[nIndex] != '.') + aBaseUriSegments.push(aUriSegments[nIndex]); + } + if (aUriSegments[--nIndex] == '..' || aUriSegments[nIndex] == '.') + aBaseUriSegments.push(''); + // + oUri.path = aBaseUriSegments.join('/'); + } + } + + return oUri; +}); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 9.1 Additional Boolean Constructor Functions + true + false + + 9.3 Functions on Boolean Values + not +*/ + +// 9.1 Additional Boolean Constructor Functions +// fn:true() as xs:boolean +fStaticContext_defineSystemFunction("true", [], function() { + return new cXSBoolean(true); +}); + +// fn:false() as xs:boolean +fStaticContext_defineSystemFunction("false", [], function() { + return new cXSBoolean(false); +}); + +// 9.3 Functions on Boolean Values +// fn:not($arg as item()*) as xs:boolean +fStaticContext_defineSystemFunction("not", [[cXTItem, '*']], function(oSequence1) { + return new cXSBoolean(!fFunction_sequence_toEBV(oSequence1, this)); +}); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 16 Context Functions + position + last + current-dateTime + current-date + current-time + implicit-timezone + default-collation + static-base-uri + +*/ +// fn:position() as xs:integer +fStaticContext_defineSystemFunction("position", [], function() { + return new cXSInteger(this.position); +}); + +// fn:last() as xs:integer +fStaticContext_defineSystemFunction("last", [], function() { + return new cXSInteger(this.size); +}); + +// fn:current-dateTime() as xs:dateTime (2004-05-12T18:17:15.125Z) +fStaticContext_defineSystemFunction("current-dateTime", [], function() { + return this.dateTime; +}); + +// fn:current-date() as xs:date (2004-05-12+01:00) +fStaticContext_defineSystemFunction("current-date", [], function() { + return cXSDate.cast(this.dateTime); +}); + +// fn:current-time() as xs:time (23:17:00.000-05:00) +fStaticContext_defineSystemFunction("current-time", [], function() { + return cXSTime.cast(this.dateTime); +}); + +// fn:implicit-timezone() as xs:dayTimeDuration +fStaticContext_defineSystemFunction("implicit-timezone", [], function() { + return this.timezone; +}); + +// fn:default-collation() as xs:string +fStaticContext_defineSystemFunction("default-collation", [], function() { + return new cXSString(this.staticContext.defaultCollationName); +}); + +// fn:static-base-uri() as xs:anyURI? +fStaticContext_defineSystemFunction("static-base-uri", [], function() { + return cXSAnyURI.cast(new cXSString(this.staticContext.baseURI || '')); +}); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 10.5 Component Extraction Functions on Durations, Dates and Times + years-from-duration + months-from-duration + days-from-duration + hours-from-duration + minutes-from-duration + seconds-from-duration + year-from-dateTime + month-from-dateTime + day-from-dateTime + hours-from-dateTime + minutes-from-dateTime + seconds-from-dateTime + timezone-from-dateTime + year-from-date + month-from-date + day-from-date + timezone-from-date + hours-from-time + minutes-from-time + seconds-from-time + timezone-from-time + + 10.7 Timezone Adjustment Functions on Dates and Time Values + adjust-dateTime-to-timezone + adjust-date-to-timezone + adjust-time-to-timezone +*/ + +// 10.5 Component Extraction Functions on Durations, Dates and Times +// functions on duration +// fn:years-from-duration($arg as xs:duration?) as xs:integer? +fStaticContext_defineSystemFunction("years-from-duration", [[cXSDuration, '?']], function(oDuration) { + return fFunction_duration_getComponent(oDuration, "year"); +}); + +// fn:months-from-duration($arg as xs:duration?) as xs:integer? +fStaticContext_defineSystemFunction("months-from-duration", [[cXSDuration, '?']], function(oDuration) { + return fFunction_duration_getComponent(oDuration, "month"); +}); + +// fn:days-from-duration($arg as xs:duration?) as xs:integer? +fStaticContext_defineSystemFunction("days-from-duration", [[cXSDuration, '?']], function(oDuration) { + return fFunction_duration_getComponent(oDuration, "day"); +}); + +// fn:hours-from-duration($arg as xs:duration?) as xs:integer? +fStaticContext_defineSystemFunction("hours-from-duration", [[cXSDuration, '?']], function(oDuration) { + return fFunction_duration_getComponent(oDuration, "hours"); +}); + +// fn:minutes-from-duration($arg as xs:duration?) as xs:integer? +fStaticContext_defineSystemFunction("minutes-from-duration", [[cXSDuration, '?']], function(oDuration) { + return fFunction_duration_getComponent(oDuration, "minutes"); +}); + +// fn:seconds-from-duration($arg as xs:duration?) as xs:decimal? +fStaticContext_defineSystemFunction("seconds-from-duration", [[cXSDuration, '?']], function(oDuration) { + return fFunction_duration_getComponent(oDuration, "seconds"); +}); + +// functions on dateTime +// fn:year-from-dateTime($arg as xs:dateTime?) as xs:integer? +fStaticContext_defineSystemFunction("year-from-dateTime", [[cXSDateTime, '?']], function(oDateTime) { + return fFunction_dateTime_getComponent(oDateTime, "year"); +}); + +// fn:month-from-dateTime($arg as xs:dateTime?) as xs:integer? +fStaticContext_defineSystemFunction("month-from-dateTime", [[cXSDateTime, '?']], function(oDateTime) { + return fFunction_dateTime_getComponent(oDateTime, "month"); +}); + +// fn:day-from-dateTime($arg as xs:dateTime?) as xs:integer? +fStaticContext_defineSystemFunction("day-from-dateTime", [[cXSDateTime, '?']], function(oDateTime) { + return fFunction_dateTime_getComponent(oDateTime, "day"); +}); + +// fn:hours-from-dateTime($arg as xs:dateTime?) as xs:integer? +fStaticContext_defineSystemFunction("hours-from-dateTime", [[cXSDateTime, '?']], function(oDateTime) { + return fFunction_dateTime_getComponent(oDateTime, "hours"); +}); + +// fn:minutes-from-dateTime($arg as xs:dateTime?) as xs:integer? +fStaticContext_defineSystemFunction("minutes-from-dateTime", [[cXSDateTime, '?']], function(oDateTime) { + return fFunction_dateTime_getComponent(oDateTime, "minutes"); +}); + +// fn:seconds-from-dateTime($arg as xs:dateTime?) as xs:decimal? +fStaticContext_defineSystemFunction("seconds-from-dateTime", [[cXSDateTime, '?']], function(oDateTime) { + return fFunction_dateTime_getComponent(oDateTime, "seconds"); +}); + +// fn:timezone-from-dateTime($arg as xs:dateTime?) as xs:dayTimeDuration? +fStaticContext_defineSystemFunction("timezone-from-dateTime", [[cXSDateTime, '?']], function(oDateTime) { + return fFunction_dateTime_getComponent(oDateTime, "timezone"); +}); + +// functions on date +// fn:year-from-date($arg as xs:date?) as xs:integer? +fStaticContext_defineSystemFunction("year-from-date", [[cXSDate, '?']], function(oDate) { + return fFunction_dateTime_getComponent(oDate, "year"); +}); + +// fn:month-from-date($arg as xs:date?) as xs:integer? +fStaticContext_defineSystemFunction("month-from-date", [[cXSDate, '?']], function(oDate) { + return fFunction_dateTime_getComponent(oDate, "month"); +}); + +// fn:day-from-date($arg as xs:date?) as xs:integer? +fStaticContext_defineSystemFunction("day-from-date", [[cXSDate, '?']], function(oDate) { + return fFunction_dateTime_getComponent(oDate, "day"); +}); + +// fn:timezone-from-date($arg as xs:date?) as xs:dayTimeDuration? +fStaticContext_defineSystemFunction("timezone-from-date", [[cXSDate, '?']], function(oDate) { + return fFunction_dateTime_getComponent(oDate, "timezone"); +}); + +// functions on time +// fn:hours-from-time($arg as xs:time?) as xs:integer? +fStaticContext_defineSystemFunction("hours-from-time", [[cXSTime, '?']], function(oTime) { + return fFunction_dateTime_getComponent(oTime, "hours"); +}); + +// fn:minutes-from-time($arg as xs:time?) as xs:integer? +fStaticContext_defineSystemFunction("minutes-from-time", [[cXSTime, '?']], function(oTime) { + return fFunction_dateTime_getComponent(oTime, "minutes"); +}); + +// fn:seconds-from-time($arg as xs:time?) as xs:decimal? +fStaticContext_defineSystemFunction("seconds-from-time", [[cXSTime, '?']], function(oTime) { + return fFunction_dateTime_getComponent(oTime, "seconds"); +}); + +// fn:timezone-from-time($arg as xs:time?) as xs:dayTimeDuration? +fStaticContext_defineSystemFunction("timezone-from-time", [[cXSTime, '?']], function(oTime) { + return fFunction_dateTime_getComponent(oTime, "timezone"); +}); + + +// 10.7 Timezone Adjustment Functions on Dates and Time Values +// fn:adjust-dateTime-to-timezone($arg as xs:dateTime?) as xs:dateTime? +// fn:adjust-dateTime-to-timezone($arg as xs:dateTime?, $timezone as xs:dayTimeDuration?) as xs:dateTime? +fStaticContext_defineSystemFunction("adjust-dateTime-to-timezone", [[cXSDateTime, '?'], [cXSDayTimeDuration, '?', true]], function(oDateTime, oDayTimeDuration) { + return fFunction_dateTime_adjustTimezone(oDateTime, arguments.length > 1 && oDayTimeDuration != null ? arguments.length > 1 ? oDayTimeDuration : this.timezone : null); +}); + +// fn:adjust-date-to-timezone($arg as xs:date?) as xs:date? +// fn:adjust-date-to-timezone($arg as xs:date?, $timezone as xs:dayTimeDuration?) as xs:date? +fStaticContext_defineSystemFunction("adjust-date-to-timezone", [[cXSDate, '?'], [cXSDayTimeDuration, '?', true]], function(oDate, oDayTimeDuration) { + return fFunction_dateTime_adjustTimezone(oDate, arguments.length > 1 && oDayTimeDuration != null ? arguments.length > 1 ? oDayTimeDuration : this.timezone : null); +}); + +// fn:adjust-time-to-timezone($arg as xs:time?) as xs:time? +// fn:adjust-time-to-timezone($arg as xs:time?, $timezone as xs:dayTimeDuration?) as xs:time? +fStaticContext_defineSystemFunction("adjust-time-to-timezone", [[cXSTime, '?'], [cXSDayTimeDuration, '?', true]], function(oTime, oDayTimeDuration) { + return fFunction_dateTime_adjustTimezone(oTime, arguments.length > 1 && oDayTimeDuration != null ? arguments.length > 1 ? oDayTimeDuration : this.timezone : null); +}); + +// +function fFunction_duration_getComponent(oDuration, sName) { + if (oDuration == null) + return null; + + var nValue = oDuration[sName] * (oDuration.negative ?-1 : 1); + return sName == "seconds" ? new cXSDecimal(nValue) : new cXSInteger(nValue); +}; + +// +function fFunction_dateTime_getComponent(oDateTime, sName) { + if (oDateTime == null) + return null; + + if (sName == "timezone") { + var nTimezone = oDateTime.timezone; + if (nTimezone == null) + return null; + return new cXSDayTimeDuration(0, cMath.abs(~~(nTimezone / 60)), cMath.abs(nTimezone % 60), 0, nTimezone < 0); + } + else { + var nValue = oDateTime[sName]; + if (!(oDateTime instanceof cXSDate)) { + if (sName == "hours") + if (nValue == 24) + nValue = 0; + } + if (!(oDateTime instanceof cXSTime)) + nValue *= oDateTime.negative ?-1 : 1; + return sName == "seconds" ? new cXSDecimal(nValue) : new cXSInteger(nValue); + } +}; + +// +function fFunction_dateTime_adjustTimezone(oDateTime, oTimezone) { + if (oDateTime == null) + return null; + + // Create a copy + var oValue; + if (oDateTime instanceof cXSDate) + oValue = new cXSDate(oDateTime.year, oDateTime.month, oDateTime.day, oDateTime.timezone, oDateTime.negative); + else + if (oDateTime instanceof cXSTime) + oValue = new cXSTime(oDateTime.hours, oDateTime.minutes, oDateTime.seconds, oDateTime.timezone, oDateTime.negative); + else + oValue = new cXSDateTime(oDateTime.year, oDateTime.month, oDateTime.day, oDateTime.hours, oDateTime.minutes, oDateTime.seconds, oDateTime.timezone, oDateTime.negative); + + // + if (oTimezone == null) + oValue.timezone = null; + else { + var nTimezone = fOperator_dayTimeDuration_toSeconds(oTimezone) / 60; + if (oDateTime.timezone != null) { + var nDiff = nTimezone - oDateTime.timezone; + if (oDateTime instanceof cXSDate) { + if (nDiff < 0) + oValue.day--; + } + else { + oValue.minutes += nDiff % 60; + oValue.hours += ~~(nDiff / 60); + } + // + fXSDateTime_normalize(oValue); + } + oValue.timezone = nTimezone; + } + return oValue; +}; +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 14 Functions and Operators on Nodes + name + local-name + namespace-uri + number + lang + root + +*/ + +// 14 Functions on Nodes +// fn:name() as xs:string +// fn:name($arg as node()?) as xs:string +fStaticContext_defineSystemFunction("name", [[cXTNode, '?', true]], function(oNode) { + if (!arguments.length) { + if (!this.DOMAdapter.isNode(this.item)) + throw new cException("XPTY0004" + + ); + oNode = this.item; + } + else + if (oNode == null) + return new cXSString(''); + // + var vValue = hStaticContext_functions["node-name"].call(this, oNode); + return new cXSString(vValue == null ? '' : vValue.toString()); +}); + +// fn:local-name() as xs:string +// fn:local-name($arg as node()?) as xs:string +fStaticContext_defineSystemFunction("local-name", [[cXTNode, '?', true]], function(oNode) { + if (!arguments.length) { + if (!this.DOMAdapter.isNode(this.item)) + throw new cException("XPTY0004" + + ); + oNode = this.item; + } + else + if (oNode == null) + return new cXSString(''); + // + return new cXSString(this.DOMAdapter.getProperty(oNode, "localName") || ''); +}); + +// fn:namespace-uri() as xs:anyURI +// fn:namespace-uri($arg as node()?) as xs:anyURI +fStaticContext_defineSystemFunction("namespace-uri", [[cXTNode, '?', true]], function(oNode) { + if (!arguments.length) { + if (!this.DOMAdapter.isNode(this.item)) + throw new cException("XPTY0004" + + ); + oNode = this.item; + } + else + if (oNode == null) + return cXSAnyURI.cast(new cXSString('')); + // + return cXSAnyURI.cast(new cXSString(this.DOMAdapter.getProperty(oNode, "namespaceURI") || '')); +}); + +// fn:number() as xs:double +// fn:number($arg as xs:anyAtomicType?) as xs:double +fStaticContext_defineSystemFunction("number", [[cXSAnyAtomicType, '?', true]], function(/*[*/oItem/*]*/) { + if (!arguments.length) { + if (!this.item) + throw new cException("XPDY0002"); + oItem = fFunction_sequence_atomize([this.item], this)[0]; + } + + // If input item cannot be cast to xs:decimal, a NaN should be returned + var vValue = new cXSDouble(nNaN); + if (oItem != null) { + try { + vValue = cXSDouble.cast(oItem); + } + catch (e) { + + } + } + return vValue; +}); + +// fn:lang($testlang as xs:string?) as xs:boolean +// fn:lang($testlang as xs:string?, $node as node()) as xs:boolean +fStaticContext_defineSystemFunction("lang", [[cXSString, '?'], [cXTNode, '', true]], function(sLang, oNode) { + if (arguments.length < 2) { + if (!this.DOMAdapter.isNode(this.item)) + throw new cException("XPTY0004" + + ); + oNode = this.item; + } + + var fGetProperty = this.DOMAdapter.getProperty; + if (fGetProperty(oNode, "nodeType") == 2) + oNode = fGetProperty(oNode, "ownerElement"); + + // walk up the tree looking for xml:lang attribute + for (var aAttributes; oNode; oNode = fGetProperty(oNode, "parentNode")) + if (aAttributes = fGetProperty(oNode, "attributes")) + for (var nIndex = 0, nLength = aAttributes.length; nIndex < nLength; nIndex++) + if (fGetProperty(aAttributes[nIndex], "nodeName") == "xml:lang") + return new cXSBoolean(fGetProperty(aAttributes[nIndex], "value").replace(/-.+/, '').toLowerCase() == sLang.valueOf().replace(/-.+/, '').toLowerCase()); + // + return new cXSBoolean(false); +}); + +// fn:root() as node() +// fn:root($arg as node()?) as node()? +fStaticContext_defineSystemFunction("root", [[cXTNode, '?', true]], function(oNode) { + if (!arguments.length) { + if (!this.DOMAdapter.isNode(this.item)) + throw new cException("XPTY0004" + + ); + oNode = this.item; + } + else + if (oNode == null) + return null; + + var fGetProperty = this.DOMAdapter.getProperty; + + // If context node is Attribute + if (fGetProperty(oNode, "nodeType") == 2) + oNode = fGetProperty(oNode, "ownerElement"); + + for (var oParent = oNode; oParent; oParent = fGetProperty(oNode, "parentNode")) + oNode = oParent; + + return oNode; +}); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 6.4 Functions on Numeric Values + abs + ceiling + floor + round + round-half-to-even +*/ + +// 6.4 Functions on Numeric Values +// fn:abs($arg as numeric?) as numeric? +fStaticContext_defineSystemFunction("abs", [[cXSDouble, '?']], function(oValue) { + return new cXSDecimal(cMath.abs(oValue)); +}); + +// fn:ceiling($arg as numeric?) as numeric? +fStaticContext_defineSystemFunction("ceiling", [[cXSDouble, '?']], function(oValue) { + return new cXSDecimal(cMath.ceil(oValue)); +}); + +// fn:floor($arg as numeric?) as numeric? +fStaticContext_defineSystemFunction("floor", [[cXSDouble, '?']], function(oValue) { + return new cXSDecimal(cMath.floor(oValue)); +}); + +// fn:round($arg as numeric?) as numeric? +fStaticContext_defineSystemFunction("round", [[cXSDouble, '?']], function(oValue) { + return new cXSDecimal(cMath.round(oValue)); +}); + +// fn:round-half-to-even($arg as numeric?) as numeric? +// fn:round-half-to-even($arg as numeric?, $precision as xs:integer) as numeric? +fStaticContext_defineSystemFunction("round-half-to-even", [[cXSDouble, '?'], [cXSInteger, '', true]], function(oValue, oPrecision) { + var nPrecision = arguments.length > 1 ? oPrecision.valueOf() : 0; + + // + if (nPrecision < 0) { + var oPower = new cXSInteger(cMath.pow(10,-nPrecision)), + nRounded= cMath.round(hStaticContext_operators["numeric-divide"].call(this, oValue, oPower)), + oRounded= new cXSInteger(nRounded); + nDecimal= cMath.abs(hStaticContext_operators["numeric-subtract"].call(this, oRounded, hStaticContext_operators["numeric-divide"].call(this, oValue, oPower))); + return hStaticContext_operators["numeric-multiply"].call(this, hStaticContext_operators["numeric-add"].call(this, oRounded, new cXSDecimal(nDecimal == 0.5 && nRounded % 2 ?-1 : 0)), oPower); + } + else { + var oPower = new cXSInteger(cMath.pow(10, nPrecision)), + nRounded= cMath.round(hStaticContext_operators["numeric-multiply"].call(this, oValue, oPower)), + oRounded= new cXSInteger(nRounded); + nDecimal= cMath.abs(hStaticContext_operators["numeric-subtract"].call(this, oRounded, hStaticContext_operators["numeric-multiply"].call(this, oValue, oPower))); + return hStaticContext_operators["numeric-divide"].call(this, hStaticContext_operators["numeric-add"].call(this, oRounded, new cXSDecimal(nDecimal == 0.5 && nRounded % 2 ?-1 : 0)), oPower); + } +}); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 11.1 Additional Constructor Functions for QNames + resolve-QName + QName + + 11.2 Functions and Operators Related to QNames + prefix-from-QName + local-name-from-QName + namespace-uri-from-QName + namespace-uri-for-prefix + in-scope-prefixes + +*/ + +// 11.1 Additional Constructor Functions for QNames +// fn:resolve-QName($qname as xs:string?, $element as element()) as xs:QName? +fStaticContext_defineSystemFunction("resolve-QName", [[cXSString, '?'], [cXTElement]], function(oQName, oElement) { + if (oQName == null) + return null; + + var sQName = oQName.valueOf(), + aMatch = sQName.match(rXSQName); + if (!aMatch) + throw new cException("FOCA0002" + + ); + + var sPrefix = aMatch[1] || null, + sLocalName = aMatch[2], + sNameSpaceURI = this.DOMAdapter.lookupNamespaceURI(oElement, sPrefix); + // + if (sPrefix != null &&!sNameSpaceURI) + throw new cException("FONS0004" + + ); + + return new cXSQName(sPrefix, sLocalName, sNameSpaceURI || null); +}); + +// fn:QName($paramURI as xs:string?, $paramQName as xs:string) as xs:QName +fStaticContext_defineSystemFunction("QName", [[cXSString, '?'], [cXSString]], function(oUri, oQName) { + var sQName = oQName.valueOf(), + aMatch = sQName.match(rXSQName); + + if (!aMatch) + throw new cException("FOCA0002" + + ); + + return new cXSQName(aMatch[1] || null, aMatch[2] || null, oUri == null ? '' : oUri.valueOf()); +}); + +// 11.2 Functions Related to QNames +// fn:prefix-from-QName($arg as xs:QName?) as xs:NCName? +fStaticContext_defineSystemFunction("prefix-from-QName", [[cXSQName, '?']], function(oQName) { + if (oQName != null) { + if (oQName.prefix) + return new cXSNCName(oQName.prefix); + } + // + return null; +}); + +// fn:local-name-from-QName($arg as xs:QName?) as xs:NCName? +fStaticContext_defineSystemFunction("local-name-from-QName", [[cXSQName, '?']], function(oQName) { + if (oQName == null) + return null; + + return new cXSNCName(oQName.localName); +}); + +// fn:namespace-uri-from-QName($arg as xs:QName?) as xs:anyURI? +fStaticContext_defineSystemFunction("namespace-uri-from-QName", [[cXSQName, '?']], function(oQName) { + if (oQName == null) + return null; + + return cXSAnyURI.cast(new cXSString(oQName.namespaceURI || '')); +}); + +// fn:namespace-uri-for-prefix($prefix as xs:string?, $element as element()) as xs:anyURI? +fStaticContext_defineSystemFunction("namespace-uri-for-prefix", [[cXSString, '?'], [cXTElement]], function(oPrefix, oElement) { + var sPrefix = oPrefix == null ? '' : oPrefix.valueOf(), + sNameSpaceURI = this.DOMAdapter.lookupNamespaceURI(oElement, sPrefix || null); + + return sNameSpaceURI == null ? null : cXSAnyURI.cast(new cXSString(sNameSpaceURI)); +}); + +// fn:in-scope-prefixes($element as element()) as xs:string* +fStaticContext_defineSystemFunction("in-scope-prefixes", [[cXTElement]], function(oElement) { + throw "Function '" + "in-scope-prefixes" + "' not implemented"; +}); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 15.1 General Functions and Operators on Sequences + boolean + index-of + empty + exists + distinct-values + insert-before + remove + reverse + subsequence + unordered + + 15.2 Functions That Test the Cardinality of Sequences + zero-or-one + one-or-more + exactly-one + + 15.3 Equals, Union, Intersection and Except + deep-equal + + 15.4 Aggregate Functions + count + avg + max + min + sum + + 15.5 Functions and Operators that Generate Sequences + id + idref + doc + doc-available + collection + element-with-id + +*/ + +// 15.1 General Functions and Operators on Sequences +// fn:boolean($arg as item()*) as xs:boolean +fStaticContext_defineSystemFunction("boolean", [[cXTItem, '*']], function(oSequence1) { + return new cXSBoolean(fFunction_sequence_toEBV(oSequence1, this)); +}); + +// fn:index-of($seqParam as xs:anyAtomicType*, $srchParam as xs:anyAtomicType) as xs:integer* +// fn:index-of($seqParam as xs:anyAtomicType*, $srchParam as xs:anyAtomicType, $collation as xs:string) as xs:integer* +fStaticContext_defineSystemFunction("index-of", [[cXSAnyAtomicType, '*'], [cXSAnyAtomicType], [cXSString, '', true]], function(oSequence1, oSearch, oCollation) { + if (!oSequence1.length || oSearch == null) + return []; + + // TODO: Implement collation + + var vLeft = oSearch; + // Cast to XSString if Untyped + if (vLeft instanceof cXSUntypedAtomic) + vLeft = cXSString.cast(vLeft); + + var oSequence = []; + for (var nIndex = 0, nLength = oSequence1.length, vRight; nIndex < nLength; nIndex++) { + vRight = oSequence1[nIndex]; + // Cast to XSString if Untyped + if (vRight instanceof cXSUntypedAtomic) + vRight = cXSString.cast(vRight); + // + if (vRight.valueOf() === vLeft.valueOf()) + oSequence.push(new cXSInteger(nIndex + 1)); + } + + return oSequence; +}); + +// fn:empty($arg as item()*) as xs:boolean +fStaticContext_defineSystemFunction("empty", [[cXTItem, '*']], function(oSequence1) { + return new cXSBoolean(!oSequence1.length); +}); + +// fn:exists($arg as item()*) as xs:boolean +fStaticContext_defineSystemFunction("exists", [[cXTItem, '*']], function(oSequence1) { + return new cXSBoolean(!!oSequence1.length); +}); + +// fn:distinct-values($arg as xs:anyAtomicType*) as xs:anyAtomicType* +// fn:distinct-values($arg as xs:anyAtomicType*, $collation as xs:string) as xs:anyAtomicType* +fStaticContext_defineSystemFunction("distinct-values", [[cXSAnyAtomicType, '*'], [cXSString, '', true]], function(oSequence1, oCollation) { + if (arguments.length > 1) + throw "Collation parameter in function '" + "distinct-values" + "' is not implemented"; + + if (!oSequence1.length) + return null; + + var oSequence = []; + for (var nIndex = 0, nLength = oSequence1.length, vLeft; nIndex < nLength; nIndex++) { + vLeft = oSequence1[nIndex]; + // Cast to XSString if Untyped + if (vLeft instanceof cXSUntypedAtomic) + vLeft = cXSString.cast(vLeft); + for (var nRightIndex = 0, nRightLength = oSequence.length, vRight, bFound = false; (nRightIndex < nRightLength) &&!bFound; nRightIndex++) { + vRight = oSequence[nRightIndex]; + // Cast to XSString if Untyped + if (vRight instanceof cXSUntypedAtomic) + vRight = cXSString.cast(vRight); + // + if (vRight.valueOf() === vLeft.valueOf()) + bFound = true; + } + if (!bFound) + oSequence.push(oSequence1[nIndex]); + } + + return oSequence; +}); + +// fn:insert-before($target as item()*, $position as xs:integer, $inserts as item()*) as item()* +fStaticContext_defineSystemFunction("insert-before", [[cXTItem, '*'], [cXSInteger], [cXTItem, '*']], function(oSequence1, oPosition, oSequence3) { + if (!oSequence1.length) + return oSequence3; + if (!oSequence3.length) + return oSequence1; + + var nLength = oSequence1.length, + nPosition = oPosition.valueOf(); + if (nPosition < 1) + nPosition = 1; + else + if (nPosition > nLength) + nPosition = nLength + 1; + + var oSequence = []; + for (var nIndex = 0; nIndex < nLength; nIndex++) { + if (nPosition == nIndex + 1) + oSequence = oSequence.concat(oSequence3); + oSequence.push(oSequence1[nIndex]); + } + if (nPosition == nIndex + 1) + oSequence = oSequence.concat(oSequence3); + + return oSequence; +}); + +// fn:remove($target as item()*, $position as xs:integer) as item()* +fStaticContext_defineSystemFunction("remove", [[cXTItem, '*'], [cXSInteger]], function(oSequence1, oPosition) { + if (!oSequence1.length) + return []; + + var nLength = oSequence1.length, + nPosition = oPosition.valueOf(); + + if (nPosition < 1 || nPosition > nLength) + return oSequence1; + + var oSequence = []; + for (var nIndex = 0; nIndex < nLength; nIndex++) + if (nPosition != nIndex + 1) + oSequence.push(oSequence1[nIndex]); + + return oSequence; +}); + +// fn:reverse($arg as item()*) as item()* +fStaticContext_defineSystemFunction("reverse", [[cXTItem, '*']], function(oSequence1) { + oSequence1.reverse(); + + return oSequence1; +}); + +// fn:subsequence($sourceSeq as item()*, $startingLoc as xs:double) as item()* +// fn:subsequence($sourceSeq as item()*, $startingLoc as xs:double, $length as xs:double) as item()* +fStaticContext_defineSystemFunction("subsequence", [[cXTItem, '*'], [cXSDouble, ''], [cXSDouble, '', true]], function(oSequence1, oStart, oLength) { + var nPosition = cMath.round(oStart), + nLength = arguments.length > 2 ? cMath.round(oLength) : oSequence1.length - nPosition + 1; + + // TODO: Handle out-of-range position and length values + return oSequence1.slice(nPosition - 1, nPosition - 1 + nLength); +}); + +// fn:unordered($sourceSeq as item()*) as item()* +fStaticContext_defineSystemFunction("unordered", [[cXTItem, '*']], function(oSequence1) { + return oSequence1; +}); + + +// 15.2 Functions That Test the Cardinality of Sequences +// fn:zero-or-one($arg as item()*) as item()? +fStaticContext_defineSystemFunction("zero-or-one", [[cXTItem, '*']], function(oSequence1) { + if (oSequence1.length > 1) + throw new cException("FORG0003"); + + return oSequence1; +}); + +// fn:one-or-more($arg as item()*) as item()+ +fStaticContext_defineSystemFunction("one-or-more", [[cXTItem, '*']], function(oSequence1) { + if (!oSequence1.length) + throw new cException("FORG0004"); + + return oSequence1; +}); + +// fn:exactly-one($arg as item()*) as item() +fStaticContext_defineSystemFunction("exactly-one", [[cXTItem, '*']], function(oSequence1) { + if (oSequence1.length != 1) + throw new cException("FORG0005"); + + return oSequence1; +}); + + +// 15.3 Equals, Union, Intersection and Except +// fn:deep-equal($parameter1 as item()*, $parameter2 as item()*) as xs:boolean +// fn:deep-equal($parameter1 as item()*, $parameter2 as item()*, $collation as string) as xs:boolean +fStaticContext_defineSystemFunction("deep-equal", [[cXTItem, '*'], [cXTItem, '*'], [cXSString, '', true]], function(oSequence1, oSequence2, oCollation) { + throw "Function '" + "deep-equal" + "' not implemented"; +}); + + +// 15.4 Aggregate Functions +// fn:count($arg as item()*) as xs:integer +fStaticContext_defineSystemFunction("count", [[cXTItem, '*']], function(oSequence1) { + return new cXSInteger(oSequence1.length); +}); + +// fn:avg($arg as xs:anyAtomicType*) as xs:anyAtomicType? +fStaticContext_defineSystemFunction("avg", [[cXSAnyAtomicType, '*']], function(oSequence1) { + if (!oSequence1.length) + return null; + + // + try { + var vValue = oSequence1[0]; + if (vValue instanceof cXSUntypedAtomic) + vValue = cXSDouble.cast(vValue); + for (var nIndex = 1, nLength = oSequence1.length, vRight; nIndex < nLength; nIndex++) { + vRight = oSequence1[nIndex]; + if (vRight instanceof cXSUntypedAtomic) + vRight = cXSDouble.cast(vRight); + vValue = hAdditiveExpr_operators['+'](vValue, vRight, this); + } + return hMultiplicativeExpr_operators['div'](vValue, new cXSInteger(nLength), this); + } + catch (e) { + // XPTY0004: Arithmetic operator is not defined for provided arguments + throw e.code != "XPTY0004" ? e : new cException("FORG0006" + + ); + } +}); + +// fn:max($arg as xs:anyAtomicType*) as xs:anyAtomicType? +// fn:max($arg as xs:anyAtomicType*, $collation as string) as xs:anyAtomicType? +fStaticContext_defineSystemFunction("max", [[cXSAnyAtomicType, '*'], [cXSString, '', true]], function(oSequence1, oCollation) { + if (!oSequence1.length) + return null; + + // TODO: Implement collation + + // + try { + var vValue = oSequence1[0]; + if (vValue instanceof cXSUntypedAtomic) + vValue = cXSDouble.cast(vValue); + for (var nIndex = 1, nLength = oSequence1.length, vRight; nIndex < nLength; nIndex++) { + vRight = oSequence1[nIndex]; + if (vRight instanceof cXSUntypedAtomic) + vRight = cXSDouble.cast(vRight); + if (hComparisonExpr_ValueComp_operators['ge'](vRight, vValue, this).valueOf()) + vValue = vRight; + } + return vValue; + } + catch (e) { + // XPTY0004: Cannot compare {type1} with {type2} + throw e.code != "XPTY0004" ? e : new cException("FORG0006" + + ); + } +}); + +// fn:min($arg as xs:anyAtomicType*) as xs:anyAtomicType? +// fn:min($arg as xs:anyAtomicType*, $collation as string) as xs:anyAtomicType? +fStaticContext_defineSystemFunction("min", [[cXSAnyAtomicType, '*'], [cXSString, '', true]], function(oSequence1, oCollation) { + if (!oSequence1.length) + return null; + + // TODO: Implement collation + + // + try { + var vValue = oSequence1[0]; + if (vValue instanceof cXSUntypedAtomic) + vValue = cXSDouble.cast(vValue); + for (var nIndex = 1, nLength = oSequence1.length, vRight; nIndex < nLength; nIndex++) { + vRight = oSequence1[nIndex]; + if (vRight instanceof cXSUntypedAtomic) + vRight = cXSDouble.cast(vRight); + if (hComparisonExpr_ValueComp_operators['le'](vRight, vValue, this).valueOf()) + vValue = vRight; + } + return vValue; + } + catch (e) { + // Cannot compare {type1} with {type2} + throw e.code != "XPTY0004" ? e : new cException("FORG0006" + + ); + } +}); + +// fn:sum($arg as xs:anyAtomicType*) as xs:anyAtomicType +// fn:sum($arg as xs:anyAtomicType*, $zero as xs:anyAtomicType?) as xs:anyAtomicType? +fStaticContext_defineSystemFunction("sum", [[cXSAnyAtomicType, '*'], [cXSAnyAtomicType, '?', true]], function(oSequence1, oZero) { + if (!oSequence1.length) { + if (arguments.length > 1) + return oZero; + else + return new cXSDouble(0); + + return null; + } + + // TODO: Implement collation + + // + try { + var vValue = oSequence1[0]; + if (vValue instanceof cXSUntypedAtomic) + vValue = cXSDouble.cast(vValue); + for (var nIndex = 1, nLength = oSequence1.length, vRight; nIndex < nLength; nIndex++) { + vRight = oSequence1[nIndex]; + if (vRight instanceof cXSUntypedAtomic) + vRight = cXSDouble.cast(vRight); + vValue = hAdditiveExpr_operators['+'](vValue, vRight, this); + } + return vValue; + } + catch (e) { + // XPTY0004: Arithmetic operator is not defined for provided arguments + throw e.code != "XPTY0004" ? e : new cException("FORG0006" + + ); + } +}); + + +// 15.5 Functions and Operators that Generate Sequences +// fn:id($arg as xs:string*) as element()* +// fn:id($arg as xs:string*, $node as node()) as element()* +fStaticContext_defineSystemFunction("id", [[cXSString, '*'], [cXTNode, '', true]], function(oSequence1, oNode) { + if (arguments.length < 2) { + if (!this.DOMAdapter.isNode(this.item)) + throw new cException("XPTY0004" + + ); + oNode = this.item; + } + + // Get root node and check if it is Document + var oDocument = hStaticContext_functions["root"].call(this, oNode); + if (this.DOMAdapter.getProperty(oDocument, "nodeType") != 9) + throw new cException("FODC0001"); + + // Search for elements + var oSequence = []; + for (var nIndex = 0; nIndex < oSequence1.length; nIndex++) + for (var nRightIndex = 0, aValue = fString_trim(oSequence1[nIndex]).split(/\s+/), nRightLength = aValue.length; nRightIndex < nRightLength; nRightIndex++) + if ((oNode = this.DOMAdapter.getElementById(oDocument, aValue[nRightIndex])) && fArray_indexOf(oSequence, oNode) ==-1) + oSequence.push(oNode); + // + return fFunction_sequence_order(oSequence, this); +}); + +// fn:idref($arg as xs:string*) as node()* +// fn:idref($arg as xs:string*, $node as node()) as node()* +fStaticContext_defineSystemFunction("idref", [[cXSString, '*'], [cXTNode, '', true]], function(oSequence1, oNode) { + throw "Function '" + "idref" + "' not implemented"; +}); + +// fn:doc($uri as xs:string?) as document-node()? +fStaticContext_defineSystemFunction("doc", [[cXSString, '?', true]], function(oUri) { + throw "Function '" + "doc" + "' not implemented"; +}); + +// fn:doc-available($uri as xs:string?) as xs:boolean +fStaticContext_defineSystemFunction("doc-available", [[cXSString, '?', true]], function(oUri) { + throw "Function '" + "doc-available" + "' not implemented"; +}); + +// fn:collection() as node()* +// fn:collection($arg as xs:string?) as node()* +fStaticContext_defineSystemFunction("collection", [[cXSString, '?', true]], function(oUri) { + throw "Function '" + "collection" + "' not implemented"; +}); + +// fn:element-with-id($arg as xs:string*) as element()* +// fn:element-with-id($arg as xs:string*, $node as node()) as element()* +fStaticContext_defineSystemFunction("element-with-id", [[cXSString, '*'], [cXTNode, '', true]], function(oSequence1, oNode) { + throw "Function '" + "element-with-id" + "' not implemented"; +}); + +// EBV calculation +function fFunction_sequence_toEBV(oSequence1, oContext) { + if (!oSequence1.length) + return false; + + var oItem = oSequence1[0]; + if (oContext.DOMAdapter.isNode(oItem)) + return true; + + if (oSequence1.length == 1) { + if (oItem instanceof cXSBoolean) + return oItem.value.valueOf(); + if (oItem instanceof cXSString) + return !!oItem.valueOf().length; + if (fXSAnyAtomicType_isNumeric(oItem)) + return !(fIsNaN(oItem.valueOf()) || oItem.valueOf() == 0); + + throw new cException("FORG0006" + + ); + } + + throw new cException("FORG0006" + + ); +}; + +function fFunction_sequence_atomize(oSequence1, oContext) { + var oSequence = []; + for (var nIndex = 0, nLength = oSequence1.length, oItem, vItem; nIndex < nLength; nIndex++) { + oItem = oSequence1[nIndex]; + vItem = null; + // Untyped + if (oItem == null) + vItem = null; + // Node type + else + if (oContext.DOMAdapter.isNode(oItem)) { + var fGetProperty = oContext.DOMAdapter.getProperty; + switch (fGetProperty(oItem, "nodeType")) { + case 1: // ELEMENT_NODE + vItem = new cXSUntypedAtomic(fGetProperty(oItem, "textContent")); + break; + case 2: // ATTRIBUTE_NODE + vItem = new cXSUntypedAtomic(fGetProperty(oItem, "value")); + break; + case 3: // TEXT_NODE + case 4: // CDATA_SECTION_NODE + case 8: // COMMENT_NODE + vItem = new cXSUntypedAtomic(fGetProperty(oItem, "data")); + break; + case 7: // PROCESSING_INSTRUCTION_NODE + vItem = new cXSUntypedAtomic(fGetProperty(oItem, "data")); + break; + case 9: // DOCUMENT_NODE + var oNode = fGetProperty(oItem, "documentElement"); + vItem = new cXSUntypedAtomic(oNode ? fGetProperty(oNode, "textContent") : ''); + break; + } + } + // Base types + else + if (oItem instanceof cXSAnyAtomicType) + vItem = oItem; + + // + if (vItem != null) + oSequence.push(vItem); + } + + return oSequence; +}; + +// Orders items in sequence in document order +function fFunction_sequence_order(oSequence1, oContext) { + return oSequence1.sort(function(oNode, oNode2) { + var nPosition = oContext.DOMAdapter.compareDocumentPosition(oNode, oNode2); + return nPosition & 2 ? 1 : nPosition & 4 ?-1 : 0; + }); +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 7.2 Functions to Assemble and Disassemble Strings + codepoints-to-string + string-to-codepoints + + 7.3 Equality and Comparison of Strings + compare + codepoint-equal + + 7.4 Functions on String Values + concat + string-join + substring + string-length + normalize-space + normalize-unicode + upper-case + lower-case + translate + encode-for-uri + iri-to-uri + escape-html-uri + + 7.5 Functions Based on Substring Matching + contains + starts-with + ends-with + substring-before + substring-after + + 7.6 String Functions that Use Pattern Matching + matches + replace + tokenize +*/ + +// 7.2 Functions to Assemble and Disassemble Strings +// fn:codepoints-to-string($arg as xs:integer*) as xs:string +fStaticContext_defineSystemFunction("codepoints-to-string", [[cXSInteger, '*']], function(oSequence1) { + var aValue = []; + for (var nIndex = 0, nLength = oSequence1.length; nIndex < nLength; nIndex++) + aValue.push(cString.fromCharCode(oSequence1[nIndex])); + + return new cXSString(aValue.join('')); +}); + +// fn:string-to-codepoints($arg as xs:string?) as xs:integer* +fStaticContext_defineSystemFunction("string-to-codepoints", [[cXSString, '?']], function(oValue) { + if (oValue == null) + return null; + + var sValue = oValue.valueOf(); + if (sValue == '') + return []; + + var oSequence = []; + for (var nIndex = 0, nLength = sValue.length; nIndex < nLength; nIndex++) + oSequence.push(new cXSInteger(sValue.charCodeAt(nIndex))); + + return oSequence; +}); + +// 7.3 Equality and Comparison of Strings +// fn:compare($comparand1 as xs:string?, $comparand2 as xs:string?) as xs:integer? +// fn:compare($comparand1 as xs:string?, $comparand2 as xs:string?, $collation as xs:string) as xs:integer? +fStaticContext_defineSystemFunction("compare", [[cXSString, '?'], [cXSString, '?'], [cXSString, '', true]], function(oValue1, oValue2, oCollation) { + if (oValue1 == null || oValue2 == null) + return null; + + var sCollation = this.staticContext.defaultCollationName, + vCollation; + if (arguments.length > 2) + sCollation = oCollation.valueOf(); + + vCollation = sCollation == sNS_XPF + "/collation/codepoint" ? oCodepointStringCollator : this.staticContext.getCollation(sCollation); + if (!vCollation) + throw new cException("FOCH0002" + + ); + + return new cXSInteger(vCollation.compare(oValue1.valueOf(), oValue2.valueOf())); +}); + +// fn:codepoint-equal($comparand1 as xs:string?, $comparand2 as xs:string?) as xs:boolean? +fStaticContext_defineSystemFunction("codepoint-equal", [[cXSString, '?'], [cXSString, '?']], function(oValue1, oValue2) { + if (oValue1 == null || oValue2 == null) + return null; + + // TODO: Check if JS uses 'Unicode code point collation' here + + return new cXSBoolean(oValue1.valueOf() == oValue2.valueOf()); +}); + + +// 7.4 Functions on String Values +// fn:concat($arg1 as xs:anyAtomicType?, $arg2 as xs:anyAtomicType?, ...) as xs:string +fStaticContext_defineSystemFunction("concat", null, function() { + // check arguments length + if (arguments.length < 2) + throw new cException("XPST0017" + + ); + + var aValue = []; + for (var nIndex = 0, nLength = arguments.length, oSequence; nIndex < nLength; nIndex++) { + oSequence = arguments[nIndex]; + // Assert cardinality + fFunctionCall_assertSequenceCardinality(this, oSequence, '?' + + ); + // + if (oSequence.length) + aValue[aValue.length] = cXSString.cast(fFunction_sequence_atomize(oSequence, this)[0]).valueOf(); + } + + return new cXSString(aValue.join('')); +}); + +// fn:string-join($arg1 as xs:string*, $arg2 as xs:string) as xs:string +fStaticContext_defineSystemFunction("string-join", [[cXSString, '*'], [cXSString]], function(oSequence1, oValue) { + return new cXSString(oSequence1.join(oValue)); +}); + +// fn:substring($sourceString as xs:string?, $startingLoc as xs:double) as xs:string +// fn:substring($sourceString as xs:string?, $startingLoc as xs:double, $length as xs:double) as xs:string +fStaticContext_defineSystemFunction("substring", [[cXSString, '?'], [cXSDouble], [cXSDouble, '', true]], function(oValue, oStart, oLength) { + var sValue = oValue == null ? '' : oValue.valueOf(), + nStart = cMath.round(oStart) - 1, + nEnd = arguments.length > 2 ? nStart + cMath.round(oLength) : sValue.length; + + // TODO: start can be negative + return new cXSString(nEnd > nStart ? sValue.substring(nStart, nEnd) : ''); +}); + +// fn:string-length() as xs:integer +// fn:string-length($arg as xs:string?) as xs:integer +fStaticContext_defineSystemFunction("string-length", [[cXSString, '?', true]], function(oValue) { + if (!arguments.length) { + if (!this.item) + throw new cException("XPDY0002"); + oValue = cXSString.cast(fFunction_sequence_atomize([this.item], this)[0]); + } + return new cXSInteger(oValue == null ? 0 : oValue.valueOf().length); +}); + +// fn:normalize-space() as xs:string +// fn:normalize-space($arg as xs:string?) as xs:string +fStaticContext_defineSystemFunction("normalize-space", [[cXSString, '?', true]], function(oValue) { + if (!arguments.length) { + if (!this.item) + throw new cException("XPDY0002"); + oValue = cXSString.cast(fFunction_sequence_atomize([this.item], this)[0]); + } + return new cXSString(oValue == null ? '' : fString_trim(oValue).replace(/\s\s+/g, ' ')); +}); + +// fn:normalize-unicode($arg as xs:string?) as xs:string +// fn:normalize-unicode($arg as xs:string?, $normalizationForm as xs:string) as xs:string +fStaticContext_defineSystemFunction("normalize-unicode", [[cXSString, '?'], [cXSString, '', true]], function(oValue, oNormalization) { + throw "Function '" + "normalize-unicode" + "' not implemented"; +}); + +// fn:upper-case($arg as xs:string?) as xs:string +fStaticContext_defineSystemFunction("upper-case", [[cXSString, '?']], function(oValue) { + return new cXSString(oValue == null ? '' : oValue.valueOf().toUpperCase()); +}); + +// fn:lower-case($arg as xs:string?) as xs:string +fStaticContext_defineSystemFunction("lower-case", [[cXSString, '?']], function(oValue) { + return new cXSString(oValue == null ? '' : oValue.valueOf().toLowerCase()); +}); + +// fn:translate($arg as xs:string?, $mapString as xs:string, $transString as xs:string) as xs:string +fStaticContext_defineSystemFunction("translate", [[cXSString, '?'], [cXSString], [cXSString]], function(oValue, oMap, oTranslate) { + if (oValue == null) + return new cXSString(''); + + var aValue = oValue.valueOf().split(''), + aMap = oMap.valueOf().split(''), + aTranslate = oTranslate.valueOf().split(''), + nTranslateLength = aTranslate.length, + aReturn = []; + for (var nIndex = 0, nLength = aValue.length, nPosition; nIndex < nLength; nIndex++) + if ((nPosition = aMap.indexOf(aValue[nIndex])) ==-1) + aReturn[aReturn.length] = aValue[nIndex]; + else + if (nPosition < nTranslateLength) + aReturn[aReturn.length] = aTranslate[nPosition]; + + return new cXSString(aReturn.join('')); +}); + +// fn:encode-for-uri($uri-part as xs:string?) as xs:string +fStaticContext_defineSystemFunction("encode-for-uri", [[cXSString, '?']], function(oValue) { + return new cXSString(oValue == null ? '' : window.encodeURIComponent(oValue)); +}); + +// fn:iri-to-uri($iri as xs:string?) as xs:string +fStaticContext_defineSystemFunction("iri-to-uri", [[cXSString, '?']], function(oValue) { + return new cXSString(oValue == null ? '' : window.encodeURI(window.decodeURI(oValue))); +}); + +// fn:escape-html-uri($uri as xs:string?) as xs:string +fStaticContext_defineSystemFunction("escape-html-uri", [[cXSString, '?']], function(oValue) { + if (oValue == null || oValue.valueOf() == '') + return new cXSString(''); + // Encode + var aValue = oValue.valueOf().split(''); + for (var nIndex = 0, nLength = aValue.length, nCode; nIndex < nLength; nIndex++) + if ((nCode = aValue[nIndex].charCodeAt(0)) < 32 || nCode > 126) + aValue[nIndex] = window.encodeURIComponent(aValue[nIndex]); + return new cXSString(aValue.join('')); +}); + + +// 7.5 Functions Based on Substring Matching +// fn:contains($arg1 as xs:string?, $arg2 as xs:string?) as xs:boolean +// fn:contains($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:boolean +fStaticContext_defineSystemFunction("contains", [[cXSString, '?'], [cXSString, '?'], [cXSString, '', true]], function(oValue, oSearch, oCollation) { + if (arguments.length > 2) + throw "Collation parameter in function '" + "contains" + "' is not implemented"; + return new cXSBoolean((oValue == null ? '' : oValue.valueOf()).indexOf(oSearch == null ? '' : oSearch.valueOf()) >= 0); +}); + +// fn:starts-with($arg1 as xs:string?, $arg2 as xs:string?) as xs:boolean +// fn:starts-with($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:boolean +fStaticContext_defineSystemFunction("starts-with", [[cXSString, '?'], [cXSString, '?'], [cXSString, '', true]], function(oValue, oSearch, oCollation) { + if (arguments.length > 2) + throw "Collation parameter in function '" + "starts-with" + "' is not implemented"; + return new cXSBoolean((oValue == null ? '' : oValue.valueOf()).indexOf(oSearch == null ? '' : oSearch.valueOf()) == 0); +}); + +// fn:ends-with($arg1 as xs:string?, $arg2 as xs:string?) as xs:boolean +// fn:ends-with($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:boolean +fStaticContext_defineSystemFunction("ends-with", [[cXSString, '?'], [cXSString, '?'], [cXSString, '', true]], function(oValue, oSearch, oCollation) { + if (arguments.length > 2) + throw "Collation parameter in function '" + "ends-with" + "' is not implemented"; + var sValue = oValue == null ? '' : oValue.valueOf(), + sSearch = oSearch == null ? '' : oSearch.valueOf(); + + return new cXSBoolean(sValue.indexOf(sSearch) == sValue.length - sSearch.length); +}); + +// fn:substring-before($arg1 as xs:string?, $arg2 as xs:string?) as xs:string +// fn:substring-before($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:string +fStaticContext_defineSystemFunction("substring-before", [[cXSString, '?'], [cXSString, '?'], [cXSString, '', true]], function(oValue, oSearch, oCollation) { + if (arguments.length > 2) + throw "Collation parameter in function '" + "substring-before" + "' is not implemented"; + + var sValue = oValue == null ? '' : oValue.valueOf(), + sSearch = oSearch == null ? '' : oSearch.valueOf(), + nPosition; + + return new cXSString((nPosition = sValue.indexOf(sSearch)) >= 0 ? sValue.substring(0, nPosition) : ''); +}); + +// fn:substring-after($arg1 as xs:string?, $arg2 as xs:string?) as xs:string +// fn:substring-after($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:string +fStaticContext_defineSystemFunction("substring-after", [[cXSString, '?'], [cXSString, '?'], [cXSString, '', true]], function(oValue, oSearch, oCollation) { + if (arguments.length > 2) + throw "Collation parameter in function '" + "substring-after" + "' is not implemented"; + + var sValue = oValue == null ? '' : oValue.valueOf(), + sSearch = oSearch == null ? '' : oSearch.valueOf(), + nPosition; + + return new cXSString((nPosition = sValue.indexOf(sSearch)) >= 0 ? sValue.substring(nPosition + sSearch.length) : ''); +}); + + +// 7.6 String Functions that Use Pattern Matching +function fFunction_string_createRegExp(sValue, sFlags) { + var d1 = '\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF', + d2 = '\u0370-\u037D\u037F-\u1FFF\u200C-\u200D', + d3 = '\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD', + c = 'A-Z_a-z\\-.0-9\u00B7' + d1 + '\u0300-\u036F' + d2 + '\u203F-\u2040' + d3, + i = 'A-Z_a-z' + d1 + d2 + d3; + + sValue = sValue + .replace(/\[\\i-\[:\]\]/g, '[' + i + ']') + .replace(/\[\\c-\[:\]\]/g, '[' + c + ']') + .replace(/\\i/g, '[:' + i + ']') + .replace(/\\I/g, '[^:' + i + ']') + .replace(/\\c/g, '[:' + c + ']') + .replace(/\\C/g, '[^:' + c + ']'); + + // Check if all flags are legal + if (sFlags && !sFlags.match(/^[smix]+$/)) + throw new cException("FORX0001"); // Invalid character '{%0}' in regular expression flags + + var bFlagS = sFlags.indexOf('s') >= 0, + bFlagX = sFlags.indexOf('x') >= 0; + if (bFlagS || bFlagX) { + // Strip 's' and 'x' from flags + sFlags = sFlags.replace(/[sx]/g, ''); + var aValue = [], + rValue = /\s/; + for (var nIndex = 0, nLength = sValue.length, bValue = false, sCharCurr, sCharPrev = ''; nIndex < nLength; nIndex++) { + sCharCurr = sValue.charAt(nIndex); + if (sCharPrev != '\\') { + if (sCharCurr == '[') + bValue = true; + else + if (sCharCurr == ']') + bValue = false; + } + // Replace '\s' for flag 'x' if not in [] + if (bValue || !(bFlagX && rValue.test(sCharCurr))) { + // Replace '.' for flag 's' if not in [] + if (!bValue && (bFlagS && sCharCurr == '.' && sCharPrev != '\\')) + aValue[aValue.length] = '(?:.|\\s)'; + else + aValue[aValue.length] = sCharCurr; + } + sCharPrev = sCharCurr; + } + sValue = aValue.join(''); + } + + return new cRegExp(sValue, sFlags + 'g'); +}; + +// fn:matches($input as xs:string?, $pattern as xs:string) as xs:boolean +// fn:matches($input as xs:string?, $pattern as xs:string, $flags as xs:string) as xs:boolean +fStaticContext_defineSystemFunction("matches", [[cXSString, '?'], [cXSString], [cXSString, '', true]], function(oValue, oPattern, oFlags) { + var sValue = oValue == null ? '' : oValue.valueOf(), + rRegExp = fFunction_string_createRegExp(oPattern.valueOf(), arguments.length > 2 ? oFlags.valueOf() : ''); + + return new cXSBoolean(rRegExp.test(sValue)); +}); + +// fn:replace($input as xs:string?, $pattern as xs:string, $replacement as xs:string) as xs:string +// fn:replace($input as xs:string?, $pattern as xs:string, $replacement as xs:string, $flags as xs:string) as xs:string +fStaticContext_defineSystemFunction("replace", [[cXSString, '?'], [cXSString], [cXSString], [cXSString, '', true]], function(oValue, oPattern, oReplacement, oFlags) { + var sValue = oValue == null ? '' : oValue.valueOf(), + rRegExp = fFunction_string_createRegExp(oPattern.valueOf(), arguments.length > 3 ? oFlags.valueOf() : ''); + + return new cXSBoolean(sValue.replace(rRegExp, oReplacement.valueOf())); +}); + +// fn:tokenize($input as xs:string?, $pattern as xs:string) as xs:string* +// fn:tokenize($input as xs:string?, $pattern as xs:string, $flags as xs:string) as xs:string* +fStaticContext_defineSystemFunction("tokenize", [[cXSString, '?'], [cXSString], [cXSString, '', true]], function(oValue, oPattern, oFlags) { + var sValue = oValue == null ? '' : oValue.valueOf(), + rRegExp = fFunction_string_createRegExp(oPattern.valueOf(), arguments.length > 2 ? oFlags.valueOf() : ''); + + var oSequence = []; + for (var nIndex = 0, aValue = sValue.split(rRegExp), nLength = aValue.length; nIndex < nLength; nIndex++) + oSequence.push(new cXSString(aValue[nIndex])); + + return oSequence; +}); + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +/* + 4 The Trace Function + trace +*/ + +// fn:trace($value as item()*, $label as xs:string) as item()* +fStaticContext_defineSystemFunction("trace", [[cXTItem, '*'], [cXSString]], function(oSequence1, oLabel) { + var oConsole = window.console; + if (oConsole && oConsole.log) + oConsole.log(oLabel.valueOf(), oSequence1); + return oSequence1; +}); +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +var oCodepointStringCollator = new cStringCollator; + +oCodepointStringCollator.equals = function(sValue1, sValue2) { + return sValue1 == sValue2; +}; + +oCodepointStringCollator.compare = function(sValue1, sValue2) { + return sValue1 == sValue2 ? 0 : sValue1 > sValue2 ? 1 :-1; +}; +function cLXDOMAdapter() { + +}; + +cLXDOMAdapter.prototype = new cDOMAdapter; + +var oLXDOMAdapter_staticContext = new cStaticContext; + +cLXDOMAdapter.prototype.getProperty = function(oNode, sName) { + if (sName in oNode) + return oNode[sName]; + + if (sName == "baseURI") { + var sBaseURI = '', + fResolveUri = oLXDOMAdapter_staticContext.getFunction('{' + "http://www.w3.org/2005/xpath-functions" + '}' + "resolve-uri"), + cXSString = oLXDOMAdapter_staticContext.getDataType('{' + "http://www.w3.org/2001/XMLSchema" + '}' + "string"); + + for (var oParent = oNode, sUri; oParent; oParent = oParent.parentNode) + if (oParent.nodeType == 1 && (sUri = oParent.getAttribute("xml:base"))) + sBaseURI = fResolveUri(new cXSString(sUri), new cXSString(sBaseURI)).toString(); + return sBaseURI; + } + else + if (sName == "textContent") { + var aText = []; + (function(oNode) { + for (var nIndex = 0, oChild; oChild = oNode.childNodes[nIndex]; nIndex++) + if (oChild.nodeType == 3 || oChild.nodeType == 4 ) + aText.push(oChild.data); + else + if (oChild.nodeType == 1 && oChild.firstChild) + arguments.callee(oChild); + })(oNode); + return aText.join(''); + } +}; + +cLXDOMAdapter.prototype.compareDocumentPosition = function(oNode, oChild) { + if ("compareDocumentPosition" in oNode) + return oNode.compareDocumentPosition(oChild); + + if (oChild == oNode) + return 0; + + var oAttr1 = null, + oAttr2 = null, + aAttributes, + oAttr, oElement, nIndex, nLength; + if (oNode.nodeType == 2 ) { + oAttr1 = oNode; + oNode = this.getProperty(oAttr1, "ownerElement"); + } + if (oChild.nodeType == 2 ) { + oAttr2 = oChild; + oChild = this.getProperty(oAttr2, "ownerElement"); + } + + if (oAttr1 && oAttr2 && oNode && oNode == oChild) { + for (nIndex = 0, aAttributes = this.getProperty(oNode, "attributes"), nLength = aAttributes.length; nIndex < nLength; nIndex++) { + oAttr = aAttributes[nIndex]; + if (oAttr == oAttr1) + return 32 | 4 ; + if (oAttr == oAttr2) + return 32 | 2 ; + } + } + + var aChain1 = [], nLength1, oNode1, + aChain2 = [], nLength2, oNode2; + if (oAttr1) + aChain1.push(oAttr1); + for (oElement = oNode; oElement; oElement = oElement.parentNode) + aChain1.push(oElement); + if (oAttr2) + aChain2.push(oAttr2); + for (oElement = oChild; oElement; oElement = oElement.parentNode) + aChain2.push(oElement); + if (((oNode.ownerDocument || oNode) != (oChild.ownerDocument || oChild)) || (aChain1[aChain1.length - 1] != aChain2[aChain2.length - 1])) + return 32 | 1 ; + for (nIndex = cMath.min(nLength1 = aChain1.length, nLength2 = aChain2.length); nIndex; --nIndex) + if ((oNode1 = aChain1[--nLength1]) != (oNode2 = aChain2[--nLength2])) { + if (oNode1.nodeType == 2 ) + return 4 ; + if (oNode2.nodeType == 2 ) + return 2 ; + if (!oNode2.nextSibling) + return 4 ; + if (!oNode1.nextSibling) + return 2 ; + for (oElement = oNode2.previousSibling; oElement; oElement = oElement.previousSibling) + if (oElement == oNode1) + return 4 ; + return 2 ; + } + return nLength1 < nLength2 ? 4 | 16 : 2 | 8 ; +}; + +cLXDOMAdapter.prototype.lookupNamespaceURI = function(oNode, sPrefix) { + if ("lookupNamespaceURI" in oNode) + return oNode.lookupNamespaceURI(sPrefix); + + for (; oNode && oNode.nodeType != 9 ; oNode = oNode.parentNode) + if (sPrefix == this.getProperty(oChild, "prefix")) + return this.getProperty(oNode, "namespaceURI"); + else + if (oNode.nodeType == 1) for (var oAttributes = this.getProperty(oNode, "attributes"), nIndex = 0, nLength = oAttributes.length, sName = "xmlns" + ':' + sPrefix; nIndex < nLength; nIndex++) + if (this.getProperty(oAttributes[nIndex], "nodeName") == sName) + return this.getProperty(oAttributes[nIndex], "value"); + return null; +}; + +cLXDOMAdapter.prototype.getElementsByTagNameNS = function(oNode, sNameSpaceURI, sLocalName) { + if ("getElementsByTagNameNS" in oNode) + return oNode.getElementsByTagNameNS(sNameSpaceURI, sLocalName); + + var aElements = [], + bNameSpaceURI = '*' == sNameSpaceURI, + bLocalName = '*' == sLocalName; + (function(oNode) { + for (var nIndex = 0, oChild; oChild = oNode.childNodes[nIndex]; nIndex++) + if (oChild.nodeType == 1) { if ((bLocalName || sLocalName == this.getProperty(oChild, "localName")) && (bNameSpaceURI || sNameSpaceURI == this.getProperty(oChild, "namespaceURI"))) + aElements[aElements.length] = oChild; + if (oChild.firstChild) + arguments.callee(oChild); + } + })(oNode); + return aElements; +}; + +var oMSHTMLDOMAdapter = new cLXDOMAdapter; + +oMSHTMLDOMAdapter.getProperty = function(oNode, sName) { + if (sName == "localName") { + if (oNode.nodeType == 1) + return oNode.nodeName.toLowerCase(); + } + if (sName == "prefix") + return null; + if (sName == "namespaceURI") + return oNode.nodeType == 1 ? "http://www.w3.org/1999/xhtml" : null; + if (sName == "textContent") + return oNode.innerText; + if (sName == "attributes" && oNode.nodeType == 1) { + var aAttributes = []; + for (var nIndex = 0, oAttributes = oNode.attributes, nLength = oAttributes.length, oNode2, oAttribute; nIndex < nLength; nIndex++) { + oNode2 = oAttributes[nIndex]; + if (oNode2.specified) { + oAttribute = new cAttr; + oAttribute.ownerElement = oNode; + oAttribute.ownerDocument= oNode.ownerDocument; + oAttribute.specified = true; + oAttribute.value = + oAttribute.nodeValue = oNode2.nodeValue; + oAttribute.name = + oAttribute.nodeName = + oAttribute.localName = oNode2.nodeName.toLowerCase(); + aAttributes[aAttributes.length] = oAttribute; + } + } + return aAttributes; + } + return cLXDOMAdapter.prototype.getProperty.call(this, oNode, sName); +}; + + +var oMSXMLDOMAdapter = new cLXDOMAdapter; + +oMSXMLDOMAdapter.getProperty = function(oNode, sName) { + if (sName == "localName") { + if (oNode.nodeType == 7) + return null; + if (oNode.nodeType == 1) + return oNode.baseName; + } + if (sName == "prefix" || sName == "namespaceURI") + return oNode[sName] || null; + if (sName == "textContent") + return oNode.text; + if (sName == "attributes" && oNode.nodeType == 1) { + var aAttributes = []; + for (var nIndex = 0, oAttributes = oNode.attributes, nLength = oAttributes.length, oNode2, oAttribute; nIndex < nLength; nIndex++) { + oNode2 = oAttributes[nIndex]; + if (oNode2.specified) { + oAttribute = new cAttr; + oAttribute.nodeType = 2; + oAttribute.ownerElement = oNode; + oAttribute.ownerDocument= oNode.ownerDocument; + oAttribute.specified = true; + oAttribute.value = + oAttribute.nodeValue = oNode2.nodeValue; + oAttribute.name = + oAttribute.nodeName = oNode2.nodeName; + oAttribute.localName = oNode2.baseName; + oAttribute.prefix = oNode2.prefix || null; + oAttribute.namespaceURI = oNode2.namespaceURI || null; + aAttributes[aAttributes.length] = oAttribute; + } + } + return aAttributes; + } + return cLXDOMAdapter.prototype.getProperty.call(this, oNode, sName); +}; + +oMSXMLDOMAdapter.getElementById = function(oDocument, sId) { + return oDocument.nodeFromID(sId); +}; + +function cEvaluator() { + +}; + +cEvaluator.prototype.defaultOL2DOMAdapter = new cLXDOMAdapter; +cEvaluator.prototype.defaultOL2HTMLDOMAdapter = new cLXDOMAdapter; + +cEvaluator.prototype.defaultHTMLStaticContext = new cStaticContext; +cEvaluator.prototype.defaultHTMLStaticContext.baseURI = window.document.location.href; +cEvaluator.prototype.defaultHTMLStaticContext.defaultFunctionNamespace = "http://www.w3.org/2005/xpath-functions"; +cEvaluator.prototype.defaultHTMLStaticContext.defaultElementNamespace = "http://www.w3.org/1999/xhtml"; + +cEvaluator.prototype.defaultXMLStaticContext = new cStaticContext; +cEvaluator.prototype.defaultXMLStaticContext.defaultFunctionNamespace = "http://www.w3.org/2005/xpath-functions"; + +cEvaluator.prototype.bOldMS = !!window.document.namespaces && !window.document.createElementNS; +cEvaluator.prototype.bOldW3 = !cEvaluator.prototype.bOldMS && window.document.documentElement.namespaceURI != "http://www.w3.org/1999/xhtml"; + +cEvaluator.prototype.defaultDOMAdapter = new cDOMAdapter; + +cEvaluator.prototype.compile = function(sExpression, oStaticContext) { + return new cExpression(sExpression, oStaticContext); +}; + +cEvaluator.prototype.evaluate = function(oQuery, sExpression, fNSResolver) { + if (! (oQuery instanceof window.jQuery)) + oQuery = new window.jQuery(oQuery) + + if (typeof sExpression == "undefined" || sExpression === null) + sExpression = ''; + + var oNode = oQuery[0]; + if (typeof oNode == "undefined") + oNode = null; + + var oStaticContext = oNode && (oNode.nodeType == 9 ? oNode : oNode.ownerDocument).createElement("div").tagName == "DIV" ? this.defaultHTMLStaticContext : this.defaultXMLStaticContext; + + oStaticContext.namespaceResolver = fNSResolver; + + var oExpression = new cExpression(cString(sExpression), oStaticContext); + + oStaticContext.namespaceResolver = null; + + var aSequence, + oSequence = new window.jQuery, + oAdapter = this.defaultOL2DOMAdapter; + + if (this.bOldMS) + oAdapter = oStaticContext == this.defaultHTMLStaticContext ? oMSHTMLDOMAdapter : oMSXMLDOMAdapter; + else + if (this.bOldW3 && oStaticContext == this.defaultHTMLStaticContext) + oAdapter = this.defaultOL2HTMLDOMAdapter; + + aSequence = oExpression.evaluate(new cDynamicContext(oStaticContext, oNode, null, oAdapter)); + for (var nIndex = 0, nLength = aSequence.length, oItem; nIndex < nLength; nIndex++) + oSequence.push(oAdapter.isNode(oItem = aSequence[nIndex]) ? oItem : cStaticContext.xs2js(oItem)); + + return oSequence; +}; + +/* + * XPath.js - Pure JavaScript implementation of XPath 2.0 parser and evaluator + * + * Copyright (c) 2012 Sergey Ilinsky + * Dual licensed under the MIT and GPL licenses. + * + * + */ + +var oXPathEvaluator = new cEvaluator, + oXPathClasses = oXPathEvaluator.classes = {}; + +// +oXPathClasses.Exception = cException; +oXPathClasses.Expression = cExpression; +oXPathClasses.DOMAdapter = cDOMAdapter; +oXPathClasses.StaticContext = cStaticContext; +oXPathClasses.DynamicContext= cDynamicContext; +oXPathClasses.StringCollator= cStringCollator; + +// Publish object +window.xpath = oXPathEvaluator; + +})() \ No newline at end of file diff --git a/src/js/operations/Extract.js b/src/js/operations/Extract.js index 816c72ad..470b43c2 100755 --- a/src/js/operations/Extract.js +++ b/src/js/operations/Extract.js @@ -1,3 +1,5 @@ +/* globals xpath */ + /** * Identifier extraction operations. * @@ -10,7 +12,7 @@ var Extract = { /** - * Runs search operations across the input data using refular expressions. + * Runs search operations across the input data using regular expressions. * * @private * @param {string} input @@ -293,5 +295,118 @@ var Extract = { output += Extract.run_dates(input, []); return output; }, - + + /** + * @constant + * @default + */ + XPATH_INITIAL: "", + + /** + * @constant + * @default + */ + XPATH_DELIMITER: "\\n", + + /** + * Extract information (from an xml document) with an XPath query + * + * @author Mikescher (https://github.com/Mikescher | https://mikescher.com) + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run_xpath:function(input, args) { + const query = args[0]; + const delimiter = args[1]; + + var xml; + try { + xml = $.parseXML(input); + } catch (err) { + return "Invalid input XML."; + } + + var result; + try { + result = xpath.evaluate(xml, query); + } catch (err) { + return "Invalid XPath. Details:\n" + err.message; + } + + const serializer = new XMLSerializer(); + const nodeToString = function(node) { + switch (node.nodeType) { + case Node.ELEMENT_NODE: return serializer.serializeToString(node); + case Node.ATTRIBUTE_NODE: return node.value; + case Node.COMMENT_NODE: return node.data; + case Node.DOCUMENT_NODE: return serializer.serializeToString(node); + default: throw new Error("Unknown Node Type: " + node.nodeType); + } + }; + + return Object.values(result).slice(0, -1) // all values except last (length) + .map(nodeToString) + .join(delimiter); + }, + + + /** + * @constant + * @default + */ + SELECTOR_INITIAL: "", + /** + * @constant + * @default + */ + CSS_QUERY_DELIMITER: "\\n", + + /** + * Extract information (from an hmtl document) with an css selector + * + * @author Mikescher (https://github.com/Mikescher | https://mikescher.com) + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run_css_query: function(input, args) { + const query = args[0]; + const delimiter = args[1]; + + var html; + try { + html = $.parseHTML(input); + } catch (err) { + return "Invalid input HTML."; + } + + var result; + try { + result = $(html).find(query); + } catch (err) { + return "Invalid CSS Selector. Details:\n" + err.message; + } + + const nodeToString = function(node) { + switch (node.nodeType) { + case Node.ELEMENT_NODE: return node.outerHTML; + case Node.ATTRIBUTE_NODE: return node.value; + case Node.COMMENT_NODE: return node.data; + case Node.TEXT_NODE: return node.wholeText; + case Node.DOCUMENT_NODE: return node.outerHTML; + default: throw new Error("Unknown Node Type: " + node.nodeType); + } + }; + + return Array.apply(null, Array(result.length)) + .map(function(_, i) { + return result[i]; + }) + .map(nodeToString) + .join(delimiter); + }, + };