Довольно печатать XML файлы на Emacs

Я использую emacs для редактирования моих xml файлов (nxml-mode), и файлы были сгенерированы машиной, не имеют никакого довольно форматирования тегов.

Я искал довольно полную распечатку всего файла с отступом и сохранил его, но не смог найти автоматический путь.

Есть ли способ? Или, по крайней мере, некоторый редактор на linux, который может это сделать.

Ответ 2

Вам даже не нужно писать свою собственную функцию - sgml-mode (основной модуль gnu emacs) имеет встроенную симпатичную функцию печати (sgml-pretty-print...), которая принимает начало и конец региона аргументы.

Если вы вырезаете и вставляете xml, и вы обнаружите, что ваш терминал рубит строки в произвольных местах, вы можете использовать этот красивый принтер, который исправляет сломанные строк.

Ответ 3

Если вам требуется только отступы, не вводя никаких новых разрывов строк, вы можете применить команду indent-region для всего буфера с помощью этих нажатий клавиш:

C-x h
C-M-\

Если вам также необходимо ввести разрывы строк, так что открывающие и закрывающие теги находятся на отдельных строках, вы можете использовать следующую очень приятную функцию elisp, написанную Бенджамин Феррари. Я нашел его в своем блоге и надеюсь, что мне будет хорошо воспроизвести его здесь:

(defun bf-pretty-print-xml-region (begin end)
  "Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this.  The function inserts linebreaks to separate tags that have
nothing but whitespace between them.  It then indents the markup
by using nxml indentation rules."
  (interactive "r")
  (save-excursion
      (nxml-mode)
      (goto-char begin)
      (while (search-forward-regexp "\>[ \\t]*\<" nil t) 
        (backward-char) (insert "\n"))
      (indent-region begin end))
    (message "Ah, much better!"))

Это не зависит от внешнего инструмента, такого как Tidy.

Ответ 4

Emacs может выполнять произвольные команды с помощью M- |. Если у вас установлен xmllint:

"M- | xmllint --format -" будет отформатировать выбранную область

"C-u M- | xmllint --format -" будет делать то же самое, заменив область выходом

Ответ 5

Благодаря Тиму Хельмштедту выше я сделал так:

(defun nxml-pretty-format ()
    (interactive)
    (save-excursion
        (shell-command-on-region (point-min) (point-max) "xmllint --format -" (buffer-name) t)
        (nxml-mode)
        (indent-region begin end)))

быстро и легко. Большое спасибо.

Ответ 6

Для введения разрывов строк, а затем довольно печати

M-x sgml-mode
M-x sgml-pretty-print

Ответ 7

здесь несколько настроек, которые я сделал для версии Бенджамина Феррари:

  • search-forward-regexp не указывал конец, поэтому он работал бы с материалом от начала области до конца буфера (вместо конца области).
  • Теперь увеличивает end правильно, как отметил Чисо.
  • он вставляет разрыв между <tag></tag>, который изменяет его значение. Да, технически мы изменяем ценности всего здесь, но пустая старт/конец гораздо более значима. Теперь для этого нужно использовать два отдельных, немного более строгих поиска.

Тем не менее, "не полагается на внешний порядок" и т.д. Однако для макроса incf для incf требуется cl.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; pretty print xml region
(defun pretty-print-xml-region (begin end)
  "Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this.  The function inserts linebreaks to separate tags that have
nothing but whitespace between them.  It then indents the markup
by using nxml indentation rules."
  (interactive "r")
  (save-excursion
    (nxml-mode)
    (goto-char begin)
    ;; split <foo><foo> or </foo><foo>, but not <foo></foo>
    (while (search-forward-regexp ">[ \t]*<[^/]" end t)
      (backward-char 2) (insert "\n") (incf end))
    ;; split <foo/></foo> and </foo></foo>
    (goto-char begin)
    (while (search-forward-regexp "<.*?/.*?>[ \t]*<" end t)
      (backward-char) (insert "\n") (incf end))
    (indent-region begin end nil)
    (normal-mode))
  (message "All indented!"))

Ответ 8

Один из способов сделать это Если у вас есть что-то в формате ниже

<abc>     <abc><abc>   <abc></abc> </abc></abc>       </abc>

В Emacs попробуйте

M-x nxml-mode
M-x replace-regexp RET  > *< RET >C-q C-j< RET 
C-M-\ to indent

Это будет отступ над примером xml ниже

<abc>
  <abc>
    <abc>
      <abc>
      </abc>
    </abc>
  </abc>
</abc>

В VIM вы можете сделать это с помощью

:set ft=xml
:%s/>\s*</>\r</g
ggVG=

Надеюсь, что это поможет.

Ответ 9

  • Emacs nxml-mode может работать в представленном формате, но вам придется разделить строки.
  • Для более длинных файлов, которые просто не стоят. Запустите эту таблицу стилей (в идеале с саксонской который IMHO получает отступы строки справа) от более длинных файлов чтобы получить красивый симпатичный принт. Для любых элементов, в которых вы хотите сохранить пробел добавьте их имена вместе с "programlisting", как в "programlisting yourElementName"

НТН

 

         

Ответ 10

Я принял версию Джейсона Вирса и добавил логику, чтобы помещать объявления xmlns в свои собственные строки. Это предполагает, что у вас есть xmlns = и xmlns: без промежуточных пробелов.

(defun cheeso-pretty-print-xml-region (begin end)
  "Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this.  The function inserts linebreaks to separate tags that have
nothing but whitespace between them.  It then indents the markup
by using nxml indentation rules."
  (interactive "r")
  (save-excursion
    (nxml-mode)
    ;; split <foo><bar> or </foo><bar>, but not <foo></foo>
    (goto-char begin)
    (while (search-forward-regexp ">[ \t]*<[^/]" end t)
      (backward-char 2) (insert "\n") (incf end))
    ;; split <foo/></foo> and </foo></foo>
    (goto-char begin)
    (while (search-forward-regexp "<.*?/.*?>[ \t]*<" end t)
      (backward-char) (insert "\n") (incf end))
    ;; put xml namespace decls on newline
    (goto-char begin)
    (while (search-forward-regexp "\\(<\\([a-zA-Z][-:A-Za-z0-9]*\\)\\|['\"]\\) \\(xmlns[=:]\\)" end t)
      (goto-char (match-end 0))
      (backward-char 6) (insert "\n") (incf end))
    (indent-region begin end nil)
    (normal-mode))
  (message "All indented!"))

Ответ 11

Tidy выглядит как хороший режим. Надо смотреть на это. Будет использовать его, если мне действительно нужны все функции, которые он предлагает.

Во всяком случае, эта проблема проталкивала меня около недели, и я не искал должным образом. После публикации я начал поиск и нашел один сайт с elisp function, который делает это довольно хорошо. Автор также предлагает использовать Tidy.

Спасибо за ответ Marcel (слишком плохо, что у меня недостаточно очков, чтобы продвигать вас).

Будет опубликован в ближайшее время в моем блоге. разместите об этом (со ссылкой на Марсель).

Ответ 12

Я использую xml-reformat-tags от xml-parse.el. Обычно вы хотите иметь точку в начале файла при выполнении этой команды.

Интересно, что файл включен в Emacspeak. Когда я ежедневно использовал Emacspeak, я думал, что xml-reformat-tags - встроенный Emacs. Однажды я потерял его и должен был сделать интернет-поиск для этого и, таким образом, ввел указанную выше страницу вики.

Я также добавляю свой код для запуска xml-parse. Не уверен, что это лучший код Emacs, но, похоже, работает для меня.

(if (file-exists-p "~/.emacs.d/packages/xml-parse.el")
  (let ((load-path load-path))
    (add-to-list 'load-path "~/.emacs.d/packages")
    (require 'xml-parse))
)

Ответ 13

Если вы используете spacemacs, просто используйте команду 'spacemacs/indent-region-or-buffer'.

M-x spacemacs/indent-region-or-buffer

Ответ 14

Боюсь, мне больше нравится версия Бенджамина Феррари. Внутренняя красивая печать всегда помещает конечный тег в новую строку после значения, вставляя нежелательные CR в значения тега.

Ответ 15

по состоянию на 2017 г. emacs уже поставляется с этой возможностью по умолчанию, но вы должны записать эту небольшую функцию в свой ~/.emacs.d/init.el:

(require 'sgml-mode)

(defun reformat-xml ()
  (interactive)
  (save-excursion
    (sgml-pretty-print (point-min) (point-max))
    (indent-region (point-min) (point-max))))

то просто позвоните M-x reformat-xml

источник: https://davidcapello.com/blog/emacs/reformat-xml-on-emacs/