vending-machine/mobile/node_modules/licia/xpath.js
2026-04-03 06:07:13 +08:00

150 lines
3.9 KiB
JavaScript

var isStr = require('./isStr');
var Class = require('./Class');
exports = function(xpath, optimized) {
if (isStr(xpath)) {
return findEl(xpath);
} else {
return getXpath(xpath, optimized);
}
};
function findEl(xpath) {
var ret = [];
var nodesSnapshot = document.evaluate(
xpath,
document,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (var i = 0; i < nodesSnapshot.snapshotLength; i++) {
ret.push(nodesSnapshot.snapshotItem(i));
}
return ret;
}
function getXpath(node) {
var optimized =
arguments.length > 1 && arguments[1] !== undefined
? arguments[1]
: false;
if (node.nodeType === Node.DOCUMENT_NODE) {
return '/';
}
var steps = [];
var contextNode = node;
while (contextNode) {
var step = xPathValue(contextNode, optimized);
if (!step) {
break;
}
steps.push(step);
if (step.optimized) {
break;
}
contextNode = contextNode.parentNode;
}
steps.reverse();
return (steps.length && steps[0].optimized ? '' : '/') + steps.join('/');
}
function xPathValue(node, optimized) {
var ownValue;
var ownIndex = xPathIndex(node);
if (ownIndex === -1) {
return null;
}
switch (node.nodeType) {
case Node.ELEMENT_NODE:
if (optimized && node.getAttribute('id')) {
return new Step(
'//*[@id="' + node.getAttribute('id') + '"]',
true
);
}
ownValue = node.localName;
break;
case Node.ATTRIBUTE_NODE:
ownValue = '@' + node.nodeName();
break;
case Node.TEXT_NODE:
case Node.CDATA_SECTION_NODE:
ownValue = 'text()';
break;
case Node.PROCESSING_INSTRUCTION_NODE:
ownValue = 'processing-instruction()';
break;
case Node.COMMENT_NODE:
ownValue = 'comment()';
break;
case Node.DOCUMENT_NODE:
ownValue = '';
break;
default:
ownValue = '';
break;
}
if (ownIndex > 0) {
ownValue += '[' + ownIndex + ']';
}
return new Step(ownValue, node.nodeType === Node.DOCUMENT_NODE);
}
function xPathIndex(node) {
function areNodesSimilar(left, right) {
if (left === right) {
return true;
}
if (
left.nodeType === Node.ELEMENT_NODE &&
right.nodeType === Node.ELEMENT_NODE
) {
return left.localName === right.localName;
}
if (left.nodeType === right.nodeType) {
return true;
}
var leftType =
left.nodeType === Node.CDATA_SECTION_NODE
? Node.TEXT_NODE
: left.nodeType;
var rightType =
right.nodeType === Node.CDATA_SECTION_NODE
? Node.TEXT_NODE
: right.nodeType;
return leftType === rightType;
}
var siblings = node.parentNode ? node.parentNode.children : null;
if (!siblings) {
return 0;
}
var hasSameNamedElements;
for (var i = 0; i < siblings.length; ++i) {
if (areNodesSimilar(node, siblings[i]) && siblings[i] !== node) {
hasSameNamedElements = true;
break;
}
}
if (!hasSameNamedElements) {
return 0;
}
var ownIndex = 1;
for (var _i = 0; _i < siblings.length; ++_i) {
if (areNodesSimilar(node, siblings[_i])) {
if (siblings[_i] === node) {
return ownIndex;
}
++ownIndex;
}
}
return -1;
}
var Step = Class({
initialize: function(value, optimized) {
this.value = value;
this.optimized = optimized || false;
},
toString: function() {
return this.value;
}
});
module.exports = exports;