I am trying to get an element using document.evaluate() but also want to search only within a specific element. So for example:
const element = document.evaluate('.//p', ...); //I want this to return the Hello, World p element
<html>
<body>
<div id="someId">
<p>Hello, World!<p>
</div>
</body>
</html>
Is there any way I could pass in the div with id someId into the evaluate to only search within that scope?
I know I could write the whole XPATH like .//div[@id="someId"]/p (Wouldnt work for my case) or do string concatenation but would like to find a cleaner way of doing it like passing the DOM element (or some object it contains) somewhere.
This is precisely the purpose of the second argument of document.evaluate():
contextNodespecifies the context node for the query (see the XPath specification). It's common to pass document as the context node.
const someId = document.getElementById('someId');
const result = document.evaluate('.//p', someId, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
console.log(result.snapshotItem(0)); // Hello, World!
console.log(result.snapshotItem(1)); // null
<div id="someId">
<p>Hello, World!</p>
</div>
<div>
<p>Goodbye, World!</p>
</div>
You can also use document for the contextNode, using the parent id within the query (like you asked). Like this:
const snapshotType = XPathResult.ORDERED_NODE_SNAPSHOT_TYPE;
const result1 = document.evaluate('.//div[@id="someId"]//p', document, null, snapshotType);
console.log(`result1 contains ${result1.snapshotLength} element, namely`, result1.snapshotItem(0))
//alternatively search for the actual text
const result2 = document.evaluate('.//p[contains(text(), "Hello")]', document, null, snapshotType);
console.log(`result2 contains ${result2.snapshotLength} element, namely`, result2.snapshotItem(0));
// finally, if the element order is fixed, you can take the first one
const result3 = document.evaluate('(.//p)[1]', document, null, snapshotType);
console.log(`result3 contains ${result3.snapshotLength} element, namely`, result3.snapshotItem(0));
<div id="someId">
<p>Hello, World!</p>
</div>
<div>
<p>Goodbye, World!</p>
</div>
<div>
<p>And I left</p>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With