document.evaluate and @innerHTML

C

Csaba Gabor

In Firefox 1.5 (this question is Mozilla specific as I am using
greasemonkey) I would like to be able to use document.evaluate to
return the first TD entry that shows ^\s*MySearchText\s*$. As I
understand it, xpath doesn't yet have regular expressions so I thought
to do:

function findNode (srch) {
var node;
var expr="//td[contains(@innerHTML,'"+srch+"')]";
var RE = new RegExp("\\s*" + srch + "\\s*$");
var xpathResult = document.evaluate(expr, document, null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < xpathResult.snapshotLength; i++) {
node = xpathResult.snapshotItem(i);
if (node.innerHTML.match(RE)) return (node); // node found
}

return null; // node was not found
}


This always returns null though. Specifically,
xpathResult.snapshotLength is always 0 since document.evaluate
evidently doesn't like that @innerHTML. Short of looping through all
TDs, is there another approach someone might suggest?

Thanks,
Csaba Gabor from Vienna
 
M

Martin Honnen

Csaba Gabor wrote:

var expr="//td[contains(@innerHTML,'"+srch+"')]";

@name in XPath accesses an attribute of an element, innerHTML is not an
attribute of an element, it is only a property exposed in the browser DOM.
 
M

Martin Honnen

Csaba said:
In Firefox 1.5 (this question is Mozilla specific as I am using
greasemonkey) I would like to be able to use document.evaluate to
return the first TD entry that shows ^\s*MySearchText\s*$.
var xpathResult = document.evaluate(expr, document, null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

Note also that you could or even should use
XPathResult.FIRST_ORDERED_NODE_TYPE if you are only looking for the
first node e.g.
var singleResultNode =
document.evaluate(xPathExpression, document, null, 9,
null).singleNodeValue;
if (singleResultNode != null) {
// use node here
}
That way the XPath implementation only needs to find the first node and
does not need to build the complete resulting node set.

Other optimizations make sense, for instance if you want to look for td
elements then those usually sit only inside of the body so you could
write an expression .//td and evaluate it with document.body being the
context node.
 
C

Csaba Gabor

Martin said:
Note also that you could or even should use
XPathResult.FIRST_ORDERED_NODE_TYPE if you are only looking for the
first node e.g.
var singleResultNode =
document.evaluate(xPathExpression, document, null, 9,
null).singleNodeValue;
if (singleResultNode != null) {
// use node here
}
That way the XPath implementation only needs to find the first node and
does not need to build the complete resulting node set.

Thank you Martin, your comments were very helpful. So it seems that I
really do have to stumble through all the elements (ie. I'm not really
saving anything over document.body.getElementsByTagName('TD') it seems
to me). Given that document.evaluate is supposed to be used for
trawling through the DOM, it's unfortunate that the designers did not
include the ability to search on properties as they are some of the
most important characteristics (such as text / positioning) to search
on.
Other optimizations make sense, for instance if you want to look for td
elements then those usually sit only inside of the body so you could
write an expression .//td and evaluate it with document.body being the
context node.

You show a period in front of that //td
(How) does that alter the meaning? That is, how does
document.evaluate("//td", document.body, null, 9, null)
differ from
document.evaluate(".//td", document.body, null, 9, null)

The greasemonkey documentation has a few examples at:
http://diveintogreasemonkey.org/patterns/match-attribute.html
but they are very primitive. On the other hand, I didn't see any //
examples in the documentation that they pointed me to. Would you know
of a good source for examples?

Thanks again,
Csaba
 
M

Martin Honnen

Csaba said:
You show a period in front of that //td
(How) does that alter the meaning? That is, how does
document.evaluate("//td", document.body, null, 9, null)
differ from
document.evaluate(".//td", document.body, null, 9, null)

The first (//td) is an absolute XPath expression, it always starts from
the root node (document node in the DOM) while the second (.//td) is a
relative XPath expression.
 
C

cyberrus

Csaba said:
In Firefox 1.5 (this question is Mozilla specific as I am using
greasemonkey) I would like to be able to use document.evaluate to
return the first TD entry that shows ^\s*MySearchText\s*$. As I
understand it, xpath doesn't yet have regular expressions so I thought
....

the function you are lookin for is called string() - see here
http://www.w3.org/TR/xpath#section-String-Functions
- it returns context node converted into string (but it doesn't handle
RegExps) - if you wanna find first ocurrance of string "srch" in all td
nodes - the evaluator should loook like this:

function findNode (srch) {
return document.evaluate(
"//td[contains(string(),'"+srch+"')]",
document,
null,
9,
null).singleNodeValue;
}

as i mentioned above it wouldn't catch regexp - to handle it you have
to use standard DOM methods with loop like this:

function findNodeRE (srch) {
var allTd = document.getElementsByTagName('TD');
for(var i=0;i<allTd.length;i++){
if(srch.test(allTd.textContent))
return allTd;
}
}

pay attention that "srch" variable in second function is RegExp object
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top