function _fnGetRowElements(settings, row, colIdx, d) {
		var
			tds = [],
			td = row.firstChild,
			name, col, i = 0, contents,
			columns = settings.aoColumns,
			objectRead = settings._rowReadObject;

		// Allow the data object to be passed in, or construct
		d = d !== undefined ?
			d :
			objectRead ?
				{} :
				[];

		var attr = function (str, td) {
			if (typeof str === 'string') {
				var idx = str.indexOf('@');

				if (idx !== -1) {
					var attr = str.substring(idx + 1);
					var setter = _fnSetObjectDataFn(str);
					setter(d, td.getAttribute(attr));
				}
			}
		};

		// Read data from a cell and store into the data object
		var cellProcess = function (cell) {
			if (colIdx === undefined || colIdx === i) {
				col = columns[i];
				contents = (cell.innerHTML).trim();

				if (col && col._bAttrSrc) {
					var setter = _fnSetObjectDataFn(col.mData._);
					setter(d, contents);

					attr(col.mData.sort, cell);
					attr(col.mData.type, cell);
					attr(col.mData.filter, cell);
				}
				else {
					// Depending on the `data` option for the columns the data can
					// be read to either an object or an array.
					if (objectRead) {
						if (!col._setter) {
							// Cache the setter function
							col._setter = _fnSetObjectDataFn(col.mData);
						}
						col._setter(d, contents);
					}
					else {
						d[i] = contents;
					}
				}
			}

			i++;
		};

		if (td) {
			// `tr` element was passed in
			while (td) {
				name = td.nodeName.toUpperCase();

				if (name == "TD" || name == "TH") {
					cellProcess(td);
					tds.push(td);
				}

				td = td.nextSibling;
			}
		}
		else {
			// Existing row object passed in
			tds = row.anCells;

			for (var j = 0, jen = tds.length; j < jen; j++) {
				cellProcess(tds[j]);
			}
		}

		// Read the ID from the DOM if present
		var rowNode = row.firstChild ? row : row.nTr;

		if (rowNode) {
			var id = rowNode.getAttribute('id');

			if (id) {
				_fnSetObjectDataFn(settings.rowId)(d, id);
			}
		}

		return {
			data: d,
			cells: tds
		};
	}
Build a data source object from an HTML row, reading the contents of the
cells that are in the row.

@param {object} settings DataTables settings object
@param {node|object} TR element from which to read data or existing row
  object from which to re-read the data from the cells
@param {int} [colIdx] Optional column index
@param {array|object} [d] Data source object. If `colIdx` is given then this
  parameter should also be given and will be used to write the data into.
  Only the column in question will be written
@returns {object} Object with two parameters: `data` the data read, in
  document order, and `cells` and array of nodes (they can be useful to the
  caller, so rather than needing a second traversal to get them, just return
  them from here).
@memberof DataTable#oApi