Package: emacs As of 36c43e95de5e (2014-12-18 16:44:11 +0000), shr-tag-table fails to pass a valid DOM value to shr-tag-table-1 when the table contains a thead, tfoot, or caption element (or any combination thereof.) Consider, e. g.: (with-temp-buffer (mapcar (lambda (table) (erase-buffer) (let ((r (shr-tag-table table))) (cons r (buffer-string)))) '((table nil (thead nil (tr nil (th nil "Foo") (th nil "Bar"))) (tbody nil (tr nil (th nil "Baz") (th nil "Qux")))) (table nil (thead nil (tr nil (th nil "Foo") (th nil "Bar"))) (tr nil (th nil "Baz") (th nil "Qux"))) (table nil (tr nil (th nil "Foo") (th nil "Bar")) (tfoot nil (tr nil (th nil "Baz") (th nil "Qux")))) (table nil (caption nil "Hello, world!") (tr nil (th nil "Foo") (th nil "Bar")) (tr nil (th nil "Baz") (th nil "Qux"))) (table nil (tr nil (th nil "Foo") (th nil "Bar")) (tr nil (th nil "Baz") (th nil "Qux")))))) ; → ((nil . "") (nil . "") (nil . "") (nil . "") ; (nil . " Foo Bar \n Baz Qux \n")) The reasons to this are twofold. First of all, shr-tag-table generally assumes that the value of header and footer locals (and body, – if at least one of header, footer is non-nil) are lists of elements, while they are in fact DOM values: 1440 (defun shr-tag-table (dom) 1441 (shr-ensure-paragraph) 1442 (let* ((caption (dom-child-by-tag dom 'caption)) 1443 (header (dom-child-by-tag dom 'thead)) 1444 (body (or (dom-child-by-tag dom 'tbody) dom)) 1445 (footer (dom-child-by-tag dom 'tfoot)) Suppose that (thead nil (tr nil (th nil "Foo") (th nil "Bar"))) gets assigned to ‘header’, for instance. Now, at a later point, ‘header’ is assumed to hold a list of elements instead, which are put into a new tbody element: 1469 (if (= nbody nfooter) 1470 `((tr (td (table (tbody ,@header ,@body ,@footer))))) 1471 (nconc `((tr (td (table (tbody ,@header ,@body))))) 1472 (if (= nfooter 1) 1473 footer 1474 `((tr (td (table (tbody ,@footer)))))))) The second reason behind this problem is that the above backquote templates by no means lead to valid DOM values! For example, the last template above should instead read: `((tr nil (td nil (table nil (tbody nil ,@footer))))) Please consider the patch MIMEd. * lisp/net/shr.el (shr-tag-table): Ensure that shr-tag-table-1 gets passed a valid DOM value for tables containing a thead, tfoot, or caption. FWIW, applying the change makes the example above give a more sensible result: ((nil . " Foo Bar \n Baz Qux \n") (nil . " Foo Bar \n Baz Qux \n") (nil . " Foo Bar \n Baz Qux \n") (nil . " Hello, world! \n Foo Bar \n Baz Qux \n") (nil . " Foo Bar \n Baz Qux \n")) PS. I also took the liberty of rearranging a chain of ‘if’ forms into a cond. Not that it makes a big difference, though. -- FSF associate member #7257 np. Hope – Apocalyptica … 3013 B6A0 230E 334A