I'm doing quite a bit of manual XML editing (the source definition of some code generation I'm doing is a custom XML format) and of course prefer to use Emacs over any special purpose (usually ugly) XML editors. nXml mode has stood me well in the past, but I cannot get my head around its "outline" support. Various internet and SO posts effectively say nothing - I'm wondering if anyone has any practical experience with outlining/folding XML in Emacs (any mode) whether or not that requires altering the XML structure itself.
Asked
Active
Viewed 8,214 times
46
-
Look into outshine. – Malabarba Nov 01 '14 at 15:03
-
Here is a link to an example I did a while back dealing with folding code for arbitrary tags in nxml mode -- perhaps it could help you develop your own code: http://superuser.com/a/787030/206164 The particular tag I tackled was `xsl` -- I incorporated a counter to deal with nested tags with the same name. – lawlist Nov 02 '14 at 04:23
4 Answers
47
I found this SO post: https://stackoverflow.com/questions/944614/emacs-does-hideshow-work-with-xml-mode-sgml-mode
(require 'hideshow)
(require 'sgml-mode)
(require 'nxml-mode)
(add-to-list 'hs-special-modes-alist
'(nxml-mode
"<!--\\|<[^/>]*[^/]>"
"-->\\|</[^/>]*[^/]>"
"<!--"
sgml-skip-tag-forward
nil))
(add-hook 'nxml-mode-hook 'hs-minor-mode)
;; optional key bindings, easier than hs defaults
(define-key nxml-mode-map (kbd "C-c h") 'hs-toggle-hiding)
You can use the code from there, slightly modified, for nxml-mode easily.
This will allow you to toggle hiding/unhiding of xml elements with C-ch and will support underscores in the names.

Jordon Biondo
- 12,332
- 2
- 41
- 62
-
2
-
4@SeanAllred: I fixed the typo. The cut-and-pasters will thank you for the catch! – Dan Nov 05 '14 at 19:20
-
Brilliant! It also looks like it will be easy to write custom functions for `hideshow` like scanning a buffer to toggle all instances of a given tag etc. Would also be nice if clicking on an ellipsis with a mouse would un-hide, but I'll try not to shave the yak too much :) – Mark Nov 06 '14 at 05:21
-
@MarkAufflick hideshow has mouse support, by default, shift + mouse 2 is bound to hs-mouse-toggle-hiding, which should work exactly like you want it to. – Jordon Biondo Nov 07 '14 at 14:11
-
2+1000. This answer saved my sanity. I love nxml-mode but was switching constantly between it and a dedicated XML editor just for the latter's tag-folding support. I wonder, though, if it'd be possible to implement this functionality using the same library as [dirtree.el](https://github.com/zk/emacs-dirtree), which supports fold/unfold with the mouse and line-drawing of the tree structure in GUI Emacsen? – dodgethesteamroller Nov 03 '15 at 22:55
-
Don't understand the necessity for `sgml-skip-tag-forward`. I replaced it with `nil`. In Emacs 25.3 `forward-sexp-function` is `nxml-forward-balanced-item` – gavenkoa Nov 25 '17 at 21:10
-
13
web-mode has element folding built in and bound to C-c C-f. But you will lose some of the features of using nxml-mode obviously.

Jordon Biondo
- 12,332
- 2
- 41
- 62
-
I did not know about web-mode (don't do much web dev these days). I'll try it out and report back, thanks. – Mark Nov 02 '14 at 10:18
-
1So close! Unfortunately web-mode doesn't allow for underscores in xml tag names (which we use). Littered throughout the web-mode code are hundreds of near-same hard coded regex strings. I had a stab at working out which should be modified but it because exhausting! Otherwise, the folding in web-mode does indeed work :) – Mark Nov 05 '14 at 01:13
1
There is a quite wonderful gem called noxml-fold-mode
that exactly helps with that.
https://github.com/paddymcall/noxml-fold
It can do folding and it also has visibility cycling.

Christian Herenz
- 365
- 2
- 14
-1
(add-to-list
'hs-special-modes-alist
'(nxml-mode
"<!--\\|<[^/>][^>]*>" "-->\\|</[^/>]+>" "<!--" #'nxml-forward-element nil))
(add-hook 'nxml-mode-hook #'hs-minor-mode)
;; (setcdr (assoc 'nxml-mode hs-special-modes-alist) (list "<!--\\|<[^/>][^>]*>" "-->\\|</[^/>]+>" "<!--" #'nxml-forward-element nil))

gavenkoa
- 3,352
- 19
- 36