Skip to content

Instantly share code, notes, and snippets.

@cho45
Created August 3, 2008 07:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cho45/3809 to your computer and use it in GitHub Desktop.
Save cho45/3809 to your computer and use it in GitHub Desktop.
// from http://www.joehewitt.com/blog/files/getElementsBySelector.js
// modified
function convertSelectorToXPath (rule, start) {
var regElement = /^([#.]?)([a-z0-9\\*_-]*)((\|)([a-z0-9\\*_-]*))?/i;
var regAttr1 = /^\[([^\]]*)\]/i;
var regAttr2 = /^\[\s*([^~=\s]+)\s*(~?=)\s*"([^"]+)"\s*\]/i;
var regPseudo = /^:([a-z_-])+/i;
var regCombinator = /^(\s*[>+\s])?/i;
var regComma = /^\s*,/i;
var index = 1;
var parts = [".//", "*"];
var lastRule = null;
while (rule.length && rule != lastRule) {
lastRule = rule;
// Trim leading whitespace
rule = rule.replace(/^\s*|\s*$/g,"");
if (!rule.length) break;
// Match the element identifier
var m = regElement.exec(rule);
if (m) {
if (!m[1]) {
// XXXjoe Namespace ignored for now
if (m[5])
parts[index] = m[5];
else
parts[index] = m[2];
}
else if (m[1] == '#')
parts.push("[@id='" + m[2] + "']");
else if (m[1] == '.')
parts.push("[contains(concat(' ', @class, ' '), concat(' ', '" + m[2] + "', ' '))]");
rule = rule.substr(m[0].length);
}
// Match attribute selectors
m = regAttr2.exec(rule);
if (m) {
if (m[2] == "~=")
parts.push("[contains(concat(' ', " + m[1] + ", ' '), concat(' ', '" + m[2] + "', ' '))]");
else
parts.push("[@" + m[1] + "='" + m[3] + "']");
rule = rule.substr(m[0].length);
} else {
m = regAttr1.exec(rule);
if (m) {
parts.push("[@" + m[1] + "]");
rule = rule.substr(m[0].length);
}
}
// Skip over pseudo-classes and pseudo-elements, which are of no use to us
m = regPseudo.exec(rule);
while (m) {
rule = rule.substr(m[0].length);
m = regPseudo.exec(rule);
}
// Match combinators
m = regCombinator.exec(rule);
if (m && m[0].length) {
if (m[0].indexOf(">") != -1)
parts.push("/");
else if (m[0].indexOf("+") != -1)
parts.push("/following-sibling::");
else
parts.push("//");
index = parts.length;
parts.push("*");
rule = rule.substr(m[0].length);
}
m = regComma.exec(rule);
if (m) {
parts.push(" | ", ".//", "*");
index = parts.length-1;
rule = rule.substr(m[0].length);
}
}
var xpath = parts.join("");
return xpath;
}
function $S (selector, context, type) {
var xpath = convertSelectorToXPath(selector);
return $X(xpath, context, type);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment