xpath-ts2
Version:
DOM 3 and 4 XPath 1.0 implementation for browser and Node.js environment with support for typescript 5.
325 lines • 11.7 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Functions = void 0;
const consts_1 = require("./consts");
const character_1 = require("./utils/character");
const types_1 = require("./utils/types");
const xml_1 = require("./utils/xml");
const xpath_types_1 = require("./xpath-types");
// tslint:disable:prefer-for-of
class Functions {
static last(c, ...args) {
checkArguments(0, args, 'last');
return new xpath_types_1.XNumber(c.contextSize);
}
static position(c, ...args) {
checkArguments(0, args, 'position');
return new xpath_types_1.XNumber(c.contextPosition);
}
static count(c, ...args) {
checkArguments(1, args, 'count');
const ns = args[0].evaluate(c);
if (!(ns instanceof xpath_types_1.XNodeSet)) {
throw new Error('Function count expects (node-set)');
}
return new xpath_types_1.XNumber(ns.size);
}
static id(c, ...args) {
checkArguments(1, args, 'id');
const eRes = args[0].evaluate(c);
let ids;
if (eRes instanceof xpath_types_1.XNodeSet) {
ids = eRes.toArray().map((node) => xpath_types_1.XNodeSet.prototype.stringForNode(node));
}
else {
const id = eRes.stringValue;
ids = id.split(/[\x0d\x0a\x09\x20]+/);
}
const ns = new xpath_types_1.XNodeSet();
const doc = (0, types_1.isDocument)(c.contextNode) ? c.contextNode : c.contextNode.ownerDocument;
for (let i = 0; i < ids.length; i++) {
let n;
if (doc.getElementById) {
n = doc.getElementById(ids[i]);
}
else {
n = (0, xml_1.getElementById)(doc, ids[i]);
}
if (n != null) {
ns.add(n);
}
}
return ns;
}
static localName(c, ...args) {
checkArguments([0, 1], args, 'local-name');
let n;
if (args.length === 0) {
n = c.contextNode;
}
else {
const eRes = args[0].evaluate(c);
if (!(eRes instanceof xpath_types_1.XNodeSet)) {
throw new Error('Function local-name expects (node-set?)');
}
n = eRes.first();
}
if (n == null) {
return new xpath_types_1.XString('');
}
if (((0, types_1.isElement)(n) || (0, types_1.isAttribute)(n)) && n.localName != null) {
return new xpath_types_1.XString(n.localName);
}
else if ((0, types_1.isProcessingInstruction)(n)) {
return new xpath_types_1.XString(n.target);
}
else {
return new xpath_types_1.XString(n.nodeName != null ? n.nodeName : '');
}
}
static namespaceURI(c, ...args) {
checkArguments([0, 1], args, 'namespace-uri');
let n;
if (args.length === 0) {
n = c.contextNode;
}
else {
const eRes = args[0].evaluate(c);
if (!(eRes instanceof xpath_types_1.XNodeSet)) {
throw new Error('Function namspace-uri expects (node-set?)');
}
n = eRes.first();
}
if (n == null) {
return new xpath_types_1.XString('');
}
if ((0, types_1.isElement)(n) || (0, types_1.isAttribute)(n)) {
return new xpath_types_1.XString(n.namespaceURI);
}
else {
return new xpath_types_1.XString('');
}
}
static name_(c, ...args) {
checkArguments([0, 1], args, 'name');
let n;
if (args.length === 0) {
n = c.contextNode;
}
else {
const eRes = args[0].evaluate(c);
if (!(eRes instanceof xpath_types_1.XNodeSet)) {
throw new Error('Function name expects (node-set?)');
}
n = eRes.first();
}
if (n == null) {
return new xpath_types_1.XString('');
}
if ((0, types_1.isElement)(n)) {
return new xpath_types_1.XString(n.nodeName);
}
else if ((0, types_1.isAttribute)(n)) {
return new xpath_types_1.XString(n.name || n.nodeName);
}
else if ((0, types_1.isProcessingInstruction)(n)) {
return new xpath_types_1.XString(n.target || n.nodeName);
}
else if (n.localName == null) {
return new xpath_types_1.XString('');
}
else {
return new xpath_types_1.XString(n.localName);
}
}
static string(c, ...args) {
checkArguments([0, 1], args, 'string');
if (args.length === 0) {
return new xpath_types_1.XString(xpath_types_1.XNodeSet.prototype.stringForNode(c.contextNode));
}
else {
return args[0].evaluate(c).string;
}
}
static concat(c, ...args) {
if (args.length < 2) {
throw new Error('Function concat expects (string, string[, string]*)');
}
let s = '';
for (let i = 0; i < args.length; i++) {
s += args[i].evaluate(c).stringValue;
}
return new xpath_types_1.XString(s);
}
static startsWith(c, ...args) {
checkArguments(2, args, 'starts-with');
const s1 = args[0].evaluate(c).stringValue;
const s2 = args[1].evaluate(c).stringValue;
return new xpath_types_1.XBoolean(s1.substring(0, s2.length) === s2);
}
static contains(c, ...args) {
checkArguments(2, args, 'contains');
const s1 = args[0].evaluate(c).stringValue;
const s2 = args[1].evaluate(c).stringValue;
return new xpath_types_1.XBoolean(s1.indexOf(s2) !== -1);
}
static substringBefore(c, ...args) {
checkArguments(2, args, 'substring-before');
const s1 = args[0].evaluate(c).stringValue;
const s2 = args[1].evaluate(c).stringValue;
return new xpath_types_1.XString(s1.substring(0, s1.indexOf(s2)));
}
static substringAfter(c, ...args) {
checkArguments(2, args, 'substring-after');
const s1 = args[0].evaluate(c).stringValue;
const s2 = args[1].evaluate(c).stringValue;
if (s2.length === 0) {
return new xpath_types_1.XString(s1);
}
const i = s1.indexOf(s2);
if (i === -1) {
return new xpath_types_1.XString('');
}
return new xpath_types_1.XString(s1.substring(i + s2.length));
}
static substring(c, ...args) {
checkArguments([2, 3], args, 'substring');
const s = args[0].evaluate(c).stringValue;
const n1 = Math.round(args[1].evaluate(c).numberValue) - 1;
const n2 = args.length === 3 ? n1 + Math.round(args[2].evaluate(c).numberValue) : undefined;
return new xpath_types_1.XString(s.substring(n1, n2));
}
static stringLength(c, ...args) {
checkArguments([0, 1], args, 'string-length');
let s;
if (args.length === 0) {
s = xpath_types_1.XNodeSet.prototype.stringForNode(c.contextNode) || '';
}
else {
s = args[0].evaluate(c).stringValue;
}
return new xpath_types_1.XNumber(s.length);
}
static normalizeSpace(c, ...args) {
checkArguments([0, 1], args, 'normalize-space');
let s;
if (args.length === 0) {
s = xpath_types_1.XNodeSet.prototype.stringForNode(c.contextNode);
}
else {
s = args[0].evaluate(c).stringValue;
}
let i = 0;
let j = s.length - 1;
while ((0, character_1.isSpace)(s.charCodeAt(j))) {
j--;
}
let t = '';
while (i <= j && (0, character_1.isSpace)(s.charCodeAt(i))) {
i++;
}
while (i <= j) {
if ((0, character_1.isSpace)(s.charCodeAt(i))) {
t += ' ';
while (i <= j && (0, character_1.isSpace)(s.charCodeAt(i))) {
i++;
}
}
else {
t += s.charAt(i);
i++;
}
}
return new xpath_types_1.XString(t);
}
static translate(c, ...args) {
checkArguments(3, args, 'translate');
const value = args[0].evaluate(c).stringValue;
const from = args[1].evaluate(c).stringValue;
const to = args[2].evaluate(c).stringValue;
const cMap = [...from].reduce((acc, ch, i) => {
if (!(ch in acc)) {
acc[ch] = i > to.length ? '' : to[i];
}
return acc;
}, {});
const t = [...value].map((ch) => (ch in cMap ? cMap[ch] : ch)).join('');
return new xpath_types_1.XString(t);
}
static boolean_(c, ...args) {
checkArguments(1, args, 'boolean');
return args[0].evaluate(c).bool;
}
static not(c, ...args) {
checkArguments(1, args, 'not');
return args[0].evaluate(c).bool.not();
}
static true_(_c, ...args) {
checkArguments(0, args, 'true');
return xpath_types_1.XBoolean.TRUE;
}
static false_(_c, ...args) {
checkArguments(0, args, 'false');
return xpath_types_1.XBoolean.FALSE;
}
static lang(c, ...args) {
checkArguments(1, args, 'lang');
let lang = null;
for (let n = c.contextNode; n != null && !(0, types_1.isDocument)(n); n = n.parentNode) {
if ((0, types_1.isElement)(n)) {
const a = n.getAttributeNS(consts_1.XML_NAMESPACE_URI, 'lang');
if (a != null) {
lang = String(a);
break;
}
}
}
if (lang == null) {
return xpath_types_1.XBoolean.FALSE;
}
const s = args[0].evaluate(c).stringValue;
return new xpath_types_1.XBoolean(lang.substring(0, s.length) === s && (lang.length === s.length || lang.charAt(s.length) === '-'));
}
static number(c, ...args) {
checkArguments([0, 1], args, 'number');
if (args.length === 0) {
return new xpath_types_1.XNumber(xpath_types_1.XNodeSet.prototype.stringForNode(c.contextNode));
}
return args[0].evaluate(c).number;
}
static sum(c, ...args) {
checkArguments(1, args, 'sum');
const ns = args[0].evaluate(c);
if (!(ns instanceof xpath_types_1.XNodeSet)) {
throw new Error('Function sum expects (node-set)');
}
const ua = ns.toUnsortedArray();
let n = 0;
for (let i = 0; i < ua.length; i++) {
n += new xpath_types_1.XNumber(xpath_types_1.XNodeSet.prototype.stringForNode(ua[i])).numberValue;
}
return new xpath_types_1.XNumber(n);
}
static floor(c, ...args) {
checkArguments(1, args, 'floor');
return new xpath_types_1.XNumber(Math.floor(args[0].evaluate(c).numberValue));
}
static ceiling(c, ...args) {
checkArguments(1, args, 'ceiling');
return new xpath_types_1.XNumber(Math.ceil(args[0].evaluate(c).numberValue));
}
static round(c, ...args) {
checkArguments(1, args, 'round');
return new xpath_types_1.XNumber(Math.round(args[0].evaluate(c).numberValue));
}
}
exports.Functions = Functions;
function checkArguments(expected, args, name) {
if (typeof expected === 'number') {
expected = [expected];
}
if (!expected.includes(args.length)) {
throw new Error(`Function ${name} expects ${expected.join(' or ')} arguments instead of ${args.length}`);
}
}
//# sourceMappingURL=functions.js.map
;