Reputation: 27862
Disclaimer: I know that parsing HTML with regex is not the correct approach. I am actually just trying to parse text inside the HTML.
I am parsing several pages, and I am looking for prices. Here is what I have so far:
var all = document.body.querySelectorAll(":not(script)");
var regex = /\$[0-9,]+(\.[0-9]{2})?/g;
for (var i = 0; i < all.length; i++) {
var node_value = all[i].nodeValue;
for (var j = 0; j < all[i].childNodes.length; j++) {
var node_value = all[i].childNodes[j].nodeValue;
if (node_value !== null) {
var matches = node_value.match(regex);
if (matches !== null && matches.length > 0) {
alert("that's a match");
}
}
}
}
This particular code can get me prices like this:
<div>This is the current price: <span class="current">$60.00</span></div>
However, there are some prices that have the following structure:
<div>This is the current price: <sup>$</sup><span>80.00</span></div>
How could I improve the algorithm in order to find those prices? Shall I look in the first for loop for <sup>symbol</sup><span>price</span>
with regex?
Important: Once a match, I need to findout which DOM element is holding that price. The most inner element that is holding the price. So for example:
<div><span>$80.00</span></div>
I would need to say that is the element that is holding the price, not the div.
Upvotes: 1
Views: 2347
Reputation: 324830
Try this:
var text = document.body.textContent || document.body.innerText,
regex = /\$\s*[0-9,]+(?:\s*\.\s*\d{2})?/g,
match = text.match(regex);
if( match) {
match = match[0].replace(/\s/g,"");
alert("Match found: "+match);
}
Using a recursive search:
function findPrice(node) {
node = node || document.body;
var text = node.textContent || node.innerText,
regex = /\$\s*[0-9,]+(?:\s*\.\s*\d{2})?/,
match = text.match(regex);
if( match) {
var children = node.children, l = children.length, i;
for( i=0; i<l; i++) {
if( findPrice(children[i])) {
return children[i];
}
}
// if no children matched, then this is the narrowest container
return node;
}
else return false;
}
var result = findPrice();
Upvotes: 1
Reputation: 3464
If you can choose your browser, you might use XPath to pre-select your candidates. The following code finds candidates nodes. I tried it in Firefox 25. You might also want to look at What browsers support Xpath 2.0? and http://www.yaldex.com/ajax-tutorial-4/BBL0029.html for cross-browser approaches.
<html><head><script type="text/javascript">
function func() {
//span containing digits preceeded by superscript dollar sign
var xpathExpr1 = "//span[translate(text(),'0123456789.,','')!=text()][preceding-sibling::sup[text()='$']]";
//span containing digits and starting with dollar sign
var xpathExpr2 = "//span[translate(text(),'0123456789.,','')!=text() and contains(text(),'$')]";
var xpathExpr3 = xpathExpr1 + "|" + xpathExpr2; // union
var contextNode = document.body;
var namespaceResolver = function(prefix){return "";}
var resultType = XPathResult.UNORDERED_NODE_ITERATOR_TYPE;
var xpathResult = document.evaluate(xpathExpr1, contextNode, namespaceResolver, resultType, null);
alert(xpathResult);
var node;
while ((node = xpathResult.iterateNext()) != null) {
alert(node.textContent);
}
}
</script></head>
<body onload="func()"> aaa
<sup>$</sup><span>80.00</span> bbb
<span>$129</span> ccc
<sup>$</sup><span>ABC</span> ddd
</body></html>
Upvotes: 0