Cheerio: Retrieving all attributes of an Element

Created on 3 Dec 2015  路  4Comments  路  Source: cheeriojs/cheerio

I recently needed to retrieve all attributes of an Element to loop through the elements. After awhile of beating my head against the tutorials on doing this with jQuery (e.g. use the .attributes object) I remembered that Cheerio doesn't implement everything ...

I did find inside one of the source files that the $(element) object has a .attribs array and was able to write my code to access that array. But it's not compatible with the existing suggestions out there for using jQuery API approaches.

For example http://stackoverflow.com/questions/2048720/get-all-attributes-from-a-html-element-with-javascript-jquery

var element = $("span[name='test']");
$(element[0].attributes).each(function() {
console.log(this.nodeName+':'+this.nodeValue);});

What I did instead is:

var elem = $(element).get(0);
// attribs is an implementation detail of Cheerio
for (var nm in elem.attribs) {
    var attr = elem.attribs[nm];
    ....
}

Seems to me that at the time you create the .attribs array, you could also/instead create a compatible .attributes object.

Most helpful comment

Here is a wrapper that can be used between jQuery and Cheerio code:

const getAllAttributes = function (node) {
    return node.attributes || Object.keys(node.attribs).map(
        name => ({ name, value: node.attribs[name] })
    );
};

Then instead of using directly element.attributes, you do getAllAttributes(element). The API of the returned attributes is the same as for element.attributes.

Example (usage with cheerio):

const cheerio = require('cheerio');

const $ = cheerio.load('<ul id="tomato" class="vegetables" disabled></ul>');
console.log(getAllAttributes($('ul').get(0)));

// Output:
// [
//   { name: 'id', value: 'tomato' },
//   { name: 'class', value: 'vegetables' },
//  { name: 'disabled', value: '' }
// ]

Edit: after @bogem comment, updated with a Cheerio working example, and an implementation without Lodash/_.

All 4 comments

Supporting the entire DOM API is what jsdom is for, cheerio (probably) won't implement the attributes interface. You are in luck, though: attribs is already an object, with the attribute name as the key and the value as the entry for the key.

Here is a wrapper that can be used between jQuery and Cheerio code:

const getAllAttributes = function (node) {
    return node.attributes || Object.keys(node.attribs).map(
        name => ({ name, value: node.attribs[name] })
    );
};

Then instead of using directly element.attributes, you do getAllAttributes(element). The API of the returned attributes is the same as for element.attributes.

Example (usage with cheerio):

const cheerio = require('cheerio');

const $ = cheerio.load('<ul id="tomato" class="vegetables" disabled></ul>');
console.log(getAllAttributes($('ul').get(0)));

// Output:
// [
//   { name: 'id', value: 'tomato' },
//   { name: 'class', value: 'vegetables' },
//  { name: 'disabled', value: '' }
// ]

Edit: after @bogem comment, updated with a Cheerio working example, and an implementation without Lodash/_.

@MonsieurV thank you for your tip, it works! There is a small typo in usage though. This really works:

const element = cheerio.load('<ul id="tomato" class="vegetables"></ul>');
getAllAttributes($("ul").get(0)).forEach(({name, value}) => {
     console.log(`Attribute ${this.name}: ${this.value}`);
})

You're spot-on right @bogem, I've updated the example. (Also replaced the _.map by Object.keys().map for a more native implementation).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

askie picture askie  路  4Comments

AlbertoElias picture AlbertoElias  路  4Comments

collegepinger picture collegepinger  路  3Comments

trevorfrese picture trevorfrese  路  4Comments

rajkumarpb picture rajkumarpb  路  3Comments