好,用jQuery的幫助我編寫了這個替代XPath解析器,適用於我的用例場景。解析器試圖停留在由我的輸入指定的XPath上,但是如果DOM模型在路徑的中間部分添加了一個新標籤,其中路徑的其餘部分包含在這個單個元素中,解析器會識別此添加幷包含此單個元素進入路徑。這當然不適用於每個人和每個用例場景,但它適用於我的。也許這個解決方案是幫助別人,至少要經過一些擴展:
var SloppyXPathParser = (function() {
function childExists($cursor, element) {
assertSelection($cursor);
var $movedCursor = $cursor.children(element.name);
if ($movedCursor.size() > element.index) {
return jQuery($movedCursor.get(element.index));
} else if ($cursor.children().size() == 1) {
return childExists(jQuery($cursor.children().get(0)), element);
} else {
throw 'Cannot browse to \'' + element.name + '\' at index ' + element.index + '\'';
}
}
function assertSelection($cursor) {
if (!($cursor instanceof jQuery) || $cursor.size() != 1) {
throw 'Selection is invalid: ' + $cursor.size();
}
}
function parsePath(rawPath) {
var nodes = rawPath.split('/');
var regex = new RegExp('([a-zA-Z]+)\\[([0-9]+)\\]');
var elements = [];
var index = 0;
jQuery(nodes).each(function (key, element) {
if (element.length == 0) {
return true;
}
if (!regex.test(element)) {
throw 'Path element does not match regex: ' + element;
}
var matched = regex.exec(element);
elements[index++] = { name: matched[1], index: matched[2] };
});
return elements;
}
function findElement(input) {
var elements = parsePath(input);
var $cursor = jQuery(document);
jQuery(elements).each(function (key, element) {
$cursor = childExists($cursor, element);
});
try {
assertSelection($cursor);
} catch (cause) {
console.log('Exception: ' + cause);
return false;
}
return $cursor.get(0);
}
return {
find: function (input) {
return findElement(input);
}
}
})();
var input = '/html[0]/body[0]/table[0]/tr[1]/td[1]';
SloppyXPathParser.find(input);
與HTML源爲:
<html>
<body>
<table>
<tr>
<td>wrong</td>
<td>wrong</td>
</tr>
<tr>
<td>wrong</td>
<td>right</td>
</tr>
</table>
</body>
</html>
可以通過例如檢查瀏覽器添加了一個tbody
元素到DOM的Firebug。解析器會識別它並跳過該條目。
要麼給XPath的框架有問題,要麼你的文檔在服務器上被當作XML/XHTML,在瀏覽器上被當作HTML。 – Alohci
好吧,框架在服務器端,並操縱和分析文檔的源代碼。我嘗試以在客戶端使用這些路徑位置的方式擴展框架。 –