I have a file with xml all on one line. Does the functionality already exist to reformat this buffer to be somewhat user-readable?
Does the functionality already exist to reformat this buffer to be somewhat user-readable?
Of course, and you have plenty of options. I'd probably feed it to an external program using:
C-x h C-u M-| xmllint --format - RET
This program comes with
libxml2. You could also use
tidy. Here's a list of commandline xml formatting tools: https://stackoverflow.com/questions/16090869/how-to-pretty-print-xml-from-the-command-line
You could also do a search and replace and then indent:
M-% > < RET > C-q C-j < RET ! C-M-\
Neat trick: you can copy and paste the above string into
eval-expression) like this:
(execute-kbd-macro (kbd "M-% > < RET > C-q C-j < RET ! C-M-\\"))
sgml-mode has a command to do this:
sgml-pretty-print. If you're in
nxml-mode it looks like you need switch to
sgml-mode first. You could write a command to temporarily switch to sgml-mode, run pretty-print, then switch back to nxml-mode.
For example, here is a command that will pretty-print the region, optionally with auto-fill enabled:
(defun xml-pretty-print (beg end &optional arg) "Reformat the region between BEG and END. With optional ARG, also auto-fill." (interactive "*r\nP") (let ((fill (or (bound-and-true-p auto-fill-function) -1))) (sgml-mode) (when arg (auto-fill-mode)) (sgml-pretty-print beg end) (nxml-mode) (auto-fill-mode fill)))
write this into your
(require 'sgml-mode) (defun ninrod/reformat-xml () (interactive) (save-excursion (sgml-pretty-print (point-min) (point-max)) (indent-region (point-min) (point-max))))
reload emacs, then just call
M-x reformat-xml on the badly formatted xml buffer.
Following the hint of the answer above, and assuming you have
tidy installed a variation could be:
`C-x h M-| tidy -quiet -xml -utf8 -indent -`
This will open a new buffer
*Shell Command Output* instead of directly replacing the contents of the buffer. After checking the result, replace the old contents with the new with:
C-x h M-insert-buffer
choose the suggested default which will probably be
*Shell Command Output*. You can save the command for later with a keyboard macro:
C-x ( C-x h M-| tidy -quiet -xml -utf8 -indent - C-x) C-x C-k n pretty-xml
With this you can execute
M-x pretty-xml to reformat the buffer.
You can leverage the tidy command line program to do the dirty work for you. See the tidy man page for options that are sent below in 'call-process-region'. With an xml file/buffer open, execute M-x tidy-xml-buffer to format/indent the buffer's xml. '-xml' means require valid xml. '-i' means indent the xml. '-wrap 0' means don't wrap text. '-omit' means eliminate any unnecessary closing tags. '-q' means quiet output.
(defun tidy-xml-buffer () (interactive) (save-excursion (call-process-region (point-min) (point-max) "tidy" t t nil "-xml" "-i" "-wrap" "0" "-omit" "-q" "-utf8"))) (bind-key "C-c M-h" #'tidy-xml-buffer nxml-mode-map)
We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.