| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- 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;
|