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





Я использую режим nXML для редактирования и Аккуратный, когда я хочу отформатировать и сделать отступ для XML или HTML. Еще есть интерфейс Emacs для Tidy.
@keiw Вероятно, это потому, что вы делаете это в буфере, у которого нет имени файла. Получил ту же ошибку и проследил ее, по крайней мере, на моей стороне.
Приборка выглядит в хорошем режиме. Надо на это посмотреть. Я воспользуюсь им, если мне действительно понадобятся все функции, которые он предлагает.
Во всяком случае, эта проблема не давала мне покоя около недели, и я не искал как следует. После публикации я начал поиск и нашел один сайт с функция elisp, который неплохо справляется. Также автор предлагает использовать Tidy.
Спасибо за ответ Марсель (жаль, что у меня недостаточно очков, чтобы улучшить вас).
Скоро напишу об этом в моем блоге. Вот написать об этом (со ссылкой на сайт Марселя).
HTH
Если вам нужен только хороший отступ без введения каких-либо новых разрывов строки, вы можете применить команду 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's indentation rules."
(interactive "r")
(save-excursion
(nxml-mode)
(goto-char begin)
(while (search-forward-regexp "\>[ \t]*\<" nil t)
(backward-char) (insert "\n") (setq end (1+ end)))
(indent-region begin end))
(message "Ah, much better!"))
Это не зависит от внешнего инструмента, такого как Tidy.
Хорошее определение, спасибо. Удаление (nxml-mode) из приведенного выше defun-файла pretty-print позволяет ему работать в sgml-режиме, встроенном в emacs 22.2.1. Но я изменил его, чтобы сделать весь буфер (точка-мин) на (точка-макс), потому что это мое главное. Также есть одна ошибка: для каждой новой строки, которую вы вставляете, вам нужно будет увеличивать конец.
Как я могу использовать эту функцию в Emacs? Я скопировал и вставил код функции в буфер царапать и оценил его. Как мне вызвать эту функцию?
После оценки defun вы можете вызвать его, как любую другую функцию: M-x bf-pretty-print-xml-region. (Вам, конечно, не обязательно вводить все это, используйте завершение табуляции: M-x bf
Как насчет того, чтобы сломать длинные списки атрибутов?
Это потрясающе, потому что tidy жалуется на недопустимые кодировки символов и хочет, чтобы я их очистил перед, он переформатирует файл! Иногда дело в том, чтобы увидеть структуру неработающего xml-файла, и приборка отказывается помочь.
для каждого (insert "\n") вам также необходимо увеличить end на 1, чтобы сделать отступ для всей области, иначе вы можете пропустить последние несколько строк. Это исправление уже было добавлено в ссылку в блоге Бенджамина Феррари, указанную в этом ответе.
Вам даже не нужно писать свою собственную функцию - sgml-mode (основной модуль gnu emacs) имеет встроенную функцию красивой печати, называемую (sgml-pretty-print ...), которая принимает аргументы начала и конца области.
Если вы вырезаете и вставляете xml и обнаруживаете, что ваш терминал обрезает строки в произвольных местах, вы можете использовать этот симпатичный принтер, который сначала исправляет сломанные строки.
Как выполнить функцию, передающую регион в качестве аргумента?
(sgml-pretty-print (начало региона) (конец региона))
Я не уверен, как sgml-mode мог измениться с течением времени. Сегодня я вызвал C-x C-f foo.xml, M-x sgml-mode, затем M-x sgml-pretty-print, и мой xml-файл распечатался довольно хорошо. (Ну, emacs зависал на двадцать секунд или более перед завершением. Это был однострочный файл до красивого вывода и 720 строк после него.)
Собственно, мне тоже пришлось сделать C-x g, чтобы выделить весь буфер как область.
Мне даже не пришлось переходить в sgml-режим. Это была команда M-x в режиме nXML!
Используя Emacs 26.2, я могу оставаться в режиме nXML, выбрать весь буфер C-x h, а затем M-x sgml-pretty-print. Теперь xml будет хорошо отформатирован
В 2020 году кажется, что sgml-pretty-print по-прежнему невероятно медленный для простых улучшений формата.
Боюсь, мне гораздо больше нравится версия Бенджамина Феррари. Внутренняя симпатичная печать всегда помещает конечный тег в новую строку после значения, вставляя нежелательные CR в значения тегов.
Emacs может запускать произвольные команды с помощью M- |. Если у вас установлен xmllint:
«M- | xmllint --format -» отформатирует выбранный регион.
"C-u M- | xmllint --format -" будет делать то же самое, заменяя регион выходным
Используйте M-x mark-all-buffer впереди, чтобы пометить все содержимое буфера как область для обработки.
Благодаря Тиму Хелмстедту я сделал это так:
(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)))
быстро и легко. Большое спасибо.
Это дало мне ошибку в GNU Emacs 24, поэтому я изменил последнюю строку на: (indent-region 0 (count-lines (point-min) (point-max)))
вот несколько настроек, которые я внес в версию Бенджамина Феррари:
search-forward-regexp не указал конец, поэтому он будет работать с материалом от начала региона до конца буфера (вместо конца региона)end.<tag></tag>, что изменит его значение. Да, технически мы здесь изменяем значения всего, но пустое начало / конец гораздо более вероятно будет иметь значение. Теперь использует два отдельных, немного более строгих поиска, чтобы этого избежать.По-прежнему есть "не полагается на внешнюю приборку" и т. д. Однако для макроса cl требуется incf.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 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's 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!"))
Один из способов сделать это Если у вас есть что-то в формате ниже
<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=
Надеюсь это поможет.
Я взял Версия Джейсона Вирса и добавил логику для размещения объявлений 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's 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!"))
Использую 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))
)
Для введения разрывов строк и затем красивой печати
M-x sgml-mode
M-x sgml-pretty-print
Если вы используете Spacemacs, просто используйте команду 'spacemacs / indent-region-or-buffer'.
M-x spacemacs/indent-region-or-buffer
с 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/
К концу 2013 года tidy.el Версия: 20111222.1756 не может работать на Emacs 24 с
wrong type argument: stringp, nil.