Selenium WebDriver kullanarak JavaScript ile XPath üzerinden bir elementi almak için bir yol var mı?
Aşağıdakine benzer bir şey arıyorum:
getElementByXpath(//html[1]/body[1]/div[1]).innerHTML
JS kullanarak elementlerin innerHTML'sini almam gerekiyor (bunu Selenium WebDriver/Java'da kullanmak için, çünkü WebDriver bunu kendisi bulamıyor), ama nasıl?
ID özniteliğini kullanabilirim, ama tüm öğelerin ID özniteliği yok.
Cevap #1
document.evaluate öğesini kullanabilirsiniz:
Bir XPath ifade dizisini değerlendirir ve mümkünse belirtilen türde bir sonuç döndürür.
W3 tarafından standartlaştırılmıştır ve tamamen belgelenmiştir: https://developer.mozilla.org/en-US/docs/Web/API/Document.evaluate
function getElementByXpath(path) {
return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
console.log( getElementByXpath("//html[1]/body[1]/div[1]") );<div>foo</div>https://gist.github.com/yckart/6351935
Mozilla geliştirici ağında ayrıca harika bir giriş bulunmaktadır: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript#document.evaluate
Alternatif versiyon, XPathEvaluator kullanılarak:
function getElementByXPath(xpath) {
return new XPathEvaluator()
.createExpression(xpath)
.evaluate(document, XPathResult.FIRST_ORDERED_NODE_TYPE)
.singleNodeValue
}
console.log( getElementByXPath("//html[1]/body[1]/div[1]") );<div>foo/bar</div>Cevap #2
Chrome Geliştirici Araçlarında aşağıdakileri çalıştırabilirsiniz:
$x("some xpath")
Cevap #3
Xpath ve javascript kullanarak bir WebElement'i tanımlamak için, bir xpath ifadesini değerlendiren ve bir sonuç döndüren evaluate() yöntemini kullanmanız gerekir.
document.evaluate()
document.evaluate() bir XPath ifadesine ve verilen diğer parametrelere dayalı olarak bir XPathResult döner.
Sözdizimi şudur:
var xpathResult = document.evaluate(
xpathExpression,
contextNode,
namespaceResolver,
resultType,
result
);
Nerede :
xpathExpression: Değerlendirilecek XPath'i temsil eden dize.contextNode: Sorgu için bağlam düğümünü belirtir. Yaygın uygulama, bağlam düğümü olarakdocumentgeçirmektir.namespaceResolver: Herhangi bir ad alanı önekine geçirilecek ve bu önekle ilişkili ad alanı URI'sını temsil eden bir dize döndürmesi gereken işlev. Bu, öneklerin belge ile eşleştirilebilmesi için XPath içinde çözümlenmesi amacıyla kullanılacaktır. HTML belgeleri için veya hiçbir ad alanı öneki kullanılmadığındanullyaygındır.resultType: XPathResult yapıcısının adlandırılmış sabit özelliklerini kullanarak döndürülecek XPathResult türüne karşılık gelen bir tamsayı, örneğinXPathResult.ANY_TYPE, ve bu özellikler 0'dan 9'a kadar olan tamsayılara karşılık gelir.result: Sonuçlar için kullanılacak mevcut bir XPathResult.nullen yaygın olandır ve yeni bir XPathResult oluşturur
Gösteri
Bir örnek olarak, Google Ana Sayfasındaki Arama Kutusu, xpath ile //*[@name='q'] olarak benzersiz şekilde tanımlanabilir ve ayrıca google-chrome-devtools Console kullanılarak aşağıdaki komut ile de tanımlanabilir:
$x("//*[@name='q']")
Anlık Görüntü:
Aynı öğe, document.evaluate() ve xpath ifadesi kullanılarak da şu şekilde tanımlanabilir:
document.evaluate("//*[@name='q']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
Anlık Görüntü:
Cevap #4
Chrome komut satırı API'sinden $x gibi bir şey (birden fazla öğe seçmek için) denemek için:
var xpath = function(xpathToExecute){
var result = [];
var nodesSnapshot = document.evaluate(xpathToExecute, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
for ( var i=0 ; i < nodesSnapshot.snapshotLength; i++ ){
result.push( nodesSnapshot.snapshotItem(i) );
}
return result;
}
Bu MDN genel bakışı yardımcı oldu: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript
Cevap #5
Birçok tarayıcıda $x(xPath) konsol yerleşik olarak bulunsa da, işte JavaScript'te XPath kullanmaya giriş bölümünden, komut dosyalarında kullanıma hazır, faydalı ama sabit kodlu parçacıkların bir derlemesi:
Anlık Görüntü
Bu, xpath sonuç kümesinin tek seferlik bir anlık görüntüsünü verir. DOM değişikliklerinden sonra veriler eski olabilir.
const $x = xp => {
const snapshot = document.evaluate(
xp, document, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null
);
return [...Array(snapshot.snapshotLength)]
.map((_, i) => snapshot.snapshotItem(i))
;
};
console.log($x('//h2[contains(., "foo")]'));<h2>foo</h2>
<h2>foobar</h2>
<h2>bar</h2>İlk sıralı düğüm
const $xOne = xp =>
document.evaluate(
xp, document, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null
).singleNodeValue
;
console.log($xOne('//h2[contains(., "foo")]'));<h2>foo</h2>
<h2>foobar</h2>
<h2>bar</h2>Yineleyici
Ancak, belgenin yinelemeler arasında değiştirildiğini (belge ağacının değiştirildiğini) unutmayın; bu durum yinelemeyi geçersiz kılar ve
XPathResult'ininvalidIteratorStateözelliğitrueolarak ayarlanır ve birNS_ERROR_DOM_INVALID_STATE_ERRistisnası fırlatılır.
function *$xIter(xp) {
const iter = document.evaluate(
xp, document, null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE, null
);
for (;;) {
const node = iter.iterateNext();
if (!node) {
break;
}
yield node;
}
}
// dump to array
console.log([...$xIter('//h2[contains(., "foo")]')]);
// return next item from generator
const xpGen = $xIter('//h2[text()="foo"]');
console.log(xpGen.next().value);<h2>foo</h2>
<h2>foobar</h2>
<h2>bar</h2>Cevap #6
DOM üzerinde bir XPath ifadesi çalıştırmak için javascript'in document.evaluate özelliğini kullanabilirsiniz. Bence bu, IE 6'ya kadar tarayıcılarda bir şekilde destekleniyor.
MDN: https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate
IE bunun yerine selectNodes metodunu destekler.
MSDN: https://msdn.microsoft.com/en-us/library/ms754523(v=vs.85).aspx

