ltx-xpath
Version:
xpath evaluator for ltx
205 lines (184 loc) • 5.39 kB
JavaScript
(function() {
var axes, evaluate, foldl, functions, getopargs, isArray, operations;
isArray = Array.isArray;
foldl = function(arr, fn) {
return arr.reduce((function(a, e) {
return a.concat(fn(e));
}), []);
};
getopargs = function(exp) {
var _ref;
if (exp != null ? (_ref = exp.expression) != null ? _ref.length : void 0 : void 0) {
return foldl(exp.expression, getopargs);
} else if (((exp != null ? exp.operator : void 0) != null) && exp.args.length && (operations[exp.operator] != null)) {
return operations[exp.operator](exp.args.map(function(x) {
return getopargs.bind(x, x[0]);
}));
} else {
return [exp];
}
};
exports.axes = axes = {
'document-root': function(n) {
return [n.root()];
},
'self': function(n) {
return [n];
},
'parent': function(n) {
return (n.parent != null) && [n.parent] || [];
},
'child': function(n) {
var _ref;
return (_ref = n != null ? n.children : void 0) != null ? _ref : [];
},
'attribute': function(n, _arg) {
var nc, _ref;
nc = _arg.nc;
return ((n != null ? (_ref = n.attrs) != null ? _ref[nc] : void 0 : void 0) != null) && [n.attrs[nc]] || [];
},
'ancestor': function(n) {
var r;
r = [];
while ((n = n.parent)) {
r.unshift(n);
}
return r;
},
'ancestor-or-self': function(n) {
var r;
r = axes.ancestor(n);
r.push(n);
return r;
},
'descendant': function(n) {
var _ref;
return foldl((_ref = n != null ? n.children : void 0) != null ? _ref : [], axes['descendant-or-self']);
},
'descendant-or-self': function(n) {
var r;
r = axes.descendant(n);
r.unshift(n);
return r;
}
};
exports.operations = operations = {
'union': function(args) {
return foldl(args, function(n) {
return n();
});
},
'or': function(args) {
var a;
return (a = args[0]()).length && a[0] === true && a || args[1]();
},
'and': function(args) {
return [
operations.union(args).every(function(e) {
return e === true;
})
];
},
'=': function(args) {
return [args[0]()[0] === args[1]()[0]];
}
};
exports.functions = functions = {
'node': function(args, nodes) {
if (args.length > 1 || Object.keys(args[0]).length > 0) {
console.warn("ignoring arguments");
}
return nodes.filter(function(n) {
return (n != null ? n.is : void 0) != null;
});
},
'text': function(args, nodes) {
return nodes.filter(function(n) {
return typeof n === 'string';
});
},
'not': function(args, nodes) {
if (!args[0]()[0]) {
return nodes;
} else {
return [];
}
}
};
exports.evaluate = function(expressions, nodes, namespaces) {
if (namespaces == null) {
namespaces = {};
}
getopargs(expressions[0]).forEach(function(exp) {
if ((exp != null ? exp.seperator : void 0) === '/' && (exp != null ? exp.axis : void 0) === 'child') {
return exp.axis = 'document-root';
}
});
return evaluate(expressions, nodes, namespaces);
};
evaluate = function(expressions, nodes, namespaces) {
var args, axis, exp, xmlns, _i, _len;
for (_i = 0, _len = expressions.length; _i < _len; _i++) {
exp = expressions[_i];
if (exp.expression != null) {
nodes = evaluate(exp.expression, nodes, namespaces);
}
xmlns = namespaces[exp.prefix];
if (exp.axis) {
if ((axis = axes[exp.axis]) != null) {
nodes = foldl(nodes, function(n) {
var predicate;
predicate = [true];
if (exp.predicate != null) {
predicate = foldl(exp.predicate.slice(), function(pred) {
return evaluate(pred, [n], namespaces);
});
}
if (predicate[0]) {
return axis(n, exp);
} else {
return [];
}
});
} else {
console.error("unknown axis '" + exp.axis + "'");
}
}
if (exp.args) {
args = exp.args.slice().map(function(arg) {
return function() {
return evaluate(arg, nodes.slice(), namespaces);
};
});
if (exp.operator != null) {
if (operations[exp.operator] != null) {
nodes = operations[exp.operator](args);
} else {
console.error("unknown operator '" + exp.operator + "'");
}
} else if (exp.nc != null) {
if (functions[exp.nc] != null) {
nodes = functions[exp.nc](args, nodes);
} else {
console.error("unknown function '" + exp.nc + "'");
}
}
} else if ((exp.nc != null) && exp.nc !== "*") {
nodes = nodes.filter(function(n) {
var _ref;
return (_ref = typeof n.is === "function" ? n.is(exp.nc, xmlns) : void 0) != null ? _ref : true;
});
}
if (exp.value) {
nodes = nodes.filter(function(n) {
return n.is == null;
});
nodes.push(exp.value);
}
if (nodes.length === 0) {
break;
}
}
return nodes;
};
}).call(this);