Search code examples
javascriptnode.jscheerio

How to get next text node with cheerio


<p>
<i class="icon-home"></i>
address
<br>
<i class="icon-website"></i>
http://www.website.com
<br>
<i class="icon-tel"></i>
phone number
<br>
<i class="icon-mail"></i>
<a href="mailto:email@mail.com">Contact email</a>
<br>
</p>

I'm trying to get "address", "http://www.website.com" and "phone number".

const address = $("i.icon-home").next();
const website = $("i.icon-website").next();
const phoneNumber = $("i.icon-tel").next();

Using next() gives me the next <br> element. How can I get the next text element?


Solution

  • The various jQuery-ish methods of Cheerio focus on Element nodes, but you're looking for the content of Text nodes.

    The easiest way given the HTML you've shown is to use the underlying DOM(like) element's nextSibling to access its next sibling (which will be the Text node) and get the text from that via nodeValue:

    const address = $("i.icon-home")[0].nextSibling.nodeValue;
    const website = $("i.icon-website")[0].nextSibling.nodeValue;
    const phoneNumber = $("i.icon-tel")[0].nextSibling.nodeValue;
    

    ([0] accesses the first matching DOM(ish) element inside the Cheerio collection.)

    A couple of notes on that:

    1. You may want to trim whitespace off (by calling trim()), as the whitespace at the beginning and end of the Text nodes is preserved.

    2. If you're unsure whether there will be a Text node (or indeed any node) following the image, you might want to be more defensive:

    const getNextText = (element) => {
        if (!element.nodeName) { // If it's a Cheerio object...
            element = element[0];
        }
        const next = element.nextSibling;
        return next?.nodeType === 3 ? next.nodeValue.trim() : "";
    };
    

    Then

    const address = getNextText($("i.icon-home"));
    const website = getNextText($("i.icon-website"));
    const phoneNumber = getNextText($("i.icon-tel"));