mirror of
https://github.com/appium/appium.git
synced 2026-04-23 20:11:08 -05:00
59 lines
1.6 KiB
JavaScript
59 lines
1.6 KiB
JavaScript
import {select as xpathQuery} from 'xpath';
|
|
import {DOMParser} from '@xmldom/xmldom';
|
|
import _ from 'lodash';
|
|
|
|
export function runQuery(query, xmlStr) {
|
|
const dom = new DOMParser().parseFromString(xmlStr);
|
|
const nodes = xpathQuery(query, dom);
|
|
return nodes;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {string} query
|
|
* @param {string} xmlStr
|
|
* @param {boolean} multiple
|
|
* @returns {string|null}
|
|
*/
|
|
export function transformQuery(query, xmlStr, multiple) {
|
|
const nodes = runQuery(query, xmlStr);
|
|
if (!_.isArray(nodes)) {
|
|
return null;
|
|
}
|
|
|
|
const newQueries = nodes.map((node) => {
|
|
const indexPath = getNodeAttrVal(node, 'indexPath');
|
|
// at this point indexPath will look like /0/0/1/1/0/1/0/2
|
|
let newQuery = indexPath
|
|
.substring(1) // remove leading / so we can split
|
|
.split('/') // split into idnexes
|
|
.map((indexStr) => {
|
|
// map to xpath node indexes (1-based)
|
|
const xpathIndex = parseInt(indexStr, 10) + 1;
|
|
return `*[${xpathIndex}]`;
|
|
})
|
|
.join('/'); // reapply /
|
|
|
|
// now to make this a valid xpath from the root, prepend the / we removed earlier
|
|
return `/${newQuery}`;
|
|
});
|
|
|
|
let newSelector = null;
|
|
if (newQueries.length) {
|
|
if (multiple) {
|
|
newSelector = newQueries.join(' | ');
|
|
} else {
|
|
newSelector = newQueries[0];
|
|
}
|
|
}
|
|
return newSelector;
|
|
}
|
|
|
|
export function getNodeAttrVal(node, attr) {
|
|
const attrObjs = Object.values(node.attributes).filter((obj) => obj.name === attr);
|
|
if (!attrObjs.length) {
|
|
throw new Error(`Tried to retrieve a node attribute '${attr}' but the node didn't have it`);
|
|
}
|
|
return attrObjs[0].value;
|
|
}
|