Я использую emacs для редактирования моих файлов xml (режим nxml), и файлы, созданные машиной, не имеют красивого форматирования тегов.
Я искал возможность распечатать весь файл с отступом и сохранить его, но не смог найти автоматический способ.
Есть способ? Или, по крайней мере, какой-нибудь редактор на Linux, который может это сделать.
wrong type argument: stringp, nil
Вам даже не нужно писать свою собственную функцию - sgml-mode (основной модуль gnu emacs) имеет встроенную функцию красивой печати, называемую (sgml-pretty-print ...), которая принимает аргументы начала и конца области.
Если вы вырезаете и вставляете xml и обнаруживаете, что ваш терминал обрезает строки в произвольных местах, вы можете использовать этот симпатичный принтер, который сначала исправляет ломаные линии.
источник
sgml-mode
могло измениться со временем. Сегодня я вызванC-x C-f foo.xml
,M-x sgml-mode
, тогдаM-x sgml-pretty-print
и мой файл XML был довольно распечатан. (Ну, emacs зависал на двадцать секунд или более перед завершением. Это был однострочный файл перед красивым отпечатком и 720 строк после него.)C-x g
чтобы выделить весь буфер как область.C-x h
и затемM-x sgml-pretty-print
. Теперь xml будет хорошо отформатированЕсли вам нужен только хороший отступ без введения каких-либо новых разрывов строки, вы можете применить
indent-region
команду ко всему буферу с помощью следующих нажатий клавиш:Если вам также необходимо ввести разрывы строк, чтобы открывающие и закрывающие теги располагались на отдельных строках, вы можете использовать следующую очень красивую функцию 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.
источник
Emacs может запускать произвольные команды с помощью M- |. Если у вас установлен xmllint:
«M- | xmllint --format -» отформатирует выбранный регион.
"Cu M- | xmllint --format -" будет делать то же самое, заменяя регион выходным
источник
Благодаря Тиму Хелмстедту я сделал это так:
(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)))
быстро и легко. Большое спасибо.
источник
(indent-region 0 (count-lines (point-min) (point-max)))
Для введения разрывов строк и затем красивой печати
M-x sgml-mode M-x sgml-pretty-print
источник
вот несколько настроек, которые я внес в версию Бенджамина Феррари:
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=
Надеюсь это поможет.
источник
HTH
источник
Я взял версию Джейсона Вирса и добавил логику, позволяющую помещать объявления 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!"))
источник
Приборка выглядит в хорошем режиме. Надо на это посмотреть. Буду использовать, если мне действительно нужны все функции, которые он предлагает.
Так или иначе, эта проблема не давала мне покоя около недели, и я не искал как следует. После публикации я начал поиск и нашел один сайт с функцией elisp, которая делает это довольно хорошо. Также автор предлагает использовать Tidy.
Спасибо за ответ, Марсель
(жаль, что у меня недостаточно очков, чтобы улучшить тебя).Скоро напишу об этом в моем блоге.Вот пост об этом (со ссылкой на сайт Марселя).источник
Использую
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)) )
источник
Если вы используете 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/
источник
Боюсь, мне гораздо больше нравится версия Бенджамина Феррари. Внутренняя симпатичная печать всегда помещает конечный тег в новую строку после значения, вставляя нежелательные CR в значения тегов.
источник