Красивая печать XML-файлов на Emacs

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

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

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

15.08.2008 17:17:14
15 ОТВЕТОВ
РЕШЕНИЕ

Я использую режим nXML для редактирования и Tidy, когда я хочу отформатировать и сделать отступ XML или HTML. Существует также интерфейс Emacs для Tidy.

25
23.10.2015 00:59:41
К концу 2013 года tidy.el Версия: 20111222.1756 не может работать на Emacs 24 сwrong type argument: stringp, nil
keiw 21.12.2013 12:38:16
@keiw Это, вероятно, потому что вы делаете это в буфере, у которого нет имени файла. Получил ту же ошибку и проследил ее до той стороны, по крайней мере.
Alf 21.01.2014 13:10:02

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

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

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

Скоро опубликую об этом в моем блоге. Вот пост об этом (со ссылкой на сайт Марселя).

1
16.08.2008 06:01:12
  1. Emacs nxml-mode может работать в представленном формате, но вам придется разделить строки.
  2. Для более длинных файлов это просто не стоит. Запустите эту таблицу стилей (в идеале с Saxon, которая, по-моему, правильно рассчитывает отступ строки) для более длинных файлов, чтобы получить красивый красивый отпечаток. Для любых элементов, где вы хотите сохранить пробелы, добавьте их имена вместе с «programlisting», как в «programlisting yourElementName»

НТН

2
12.09.2008 08:14:40

Если вам нужен только красивый отступ без введения новых разрывов строки, вы можете применить 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"))
      (indent-region begin end))
    (message "Ah, much better!"))

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

86
20.02.2009 16:51:01
Хороший defun, спасибо. Удаление (nxml-mode) из описанного выше defun pretty-print позволяет ему работать в sgml-mode, встроенном в emacs 22.2.1. Но я изменил его, чтобы сделать весь буфер (point-min) в (point-max), потому что это мое главное. Также одна ошибка: для каждой новой строки, которую вы вставляете, вам нужно будет увеличивать конец.
Cheeso 3.06.2009 15:33:44
Как я могу использовать эту функцию в Emacs? Я скопировал и вставил код функции в пустой буфер и оценил его. Теперь, как мне вызвать эту функцию?
Alexandre Rademaker 21.02.2011 12:01:34
После оценки defun вы можете вызвать его, как и любую другую функцию: Mx bf-pretty-print-xml-region. (Вы не должны вводить все это, конечно, используйте завершение табуляции: Mx bf <tab> должно быть достаточно.) Вы, вероятно, не хотите определять функцию каждый раз, когда хотите ее использовать, поэтому поместите ее куда-нибудь где он загружается во время запуска, например, в ~ / .emacs.d / init.el
Christian Berg 22.02.2011 16:50:50
Как насчет ломать длинные списки атрибутов?
ceving 21.09.2012 12:33:23
Это невероятно, потому что приборка жалуется на неправильные кодировки символов и хочет, чтобы я их очистил, прежде чем он переформатирует файл! Иногда дело в том, чтобы увидеть структуру поврежденного XML-файла, и приборка откажется помочь.
TauPan 23.05.2016 08:45:02

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

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

106
27.02.2009 16:47:05
Как выполнить функцию, передав регион в качестве аргумента?
Alexandre Rademaker 7.12.2010 23:33:26
(sgml-pretty-print (регион-начало) (регион-конец))
ScootyPuff 4.01.2011 15:57:43
Я не уверен, как это sgml-modeмогло измениться со временем. Сегодня я вызвал C-x C-f foo.xml, а M-x sgml-modeзатем M-x sgml-pretty-printмой XML-файл стал довольно распечатанным. (Ну, emacs зависал на двадцать секунд или больше до завершения. Это был файл в одну строку до красивого отпечатка и 720 строк после.)
daveloyall 10.08.2015 18:14:04
На самом деле, мне также нужно было сделать C-x gвесь буфер в качестве региона.
daveloyall 10.08.2015 20:23:57
Мне даже не пришлось переключаться в режим sgml. Это была команда Mx в режиме nXML!
nroose 4.07.2018 01:04:46

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

0
12.05.2009 18:18:21

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

«M- | xmllint --format -» отформатирует выбранный регион

«Cu M- | xmllint --format -» сделает то же самое, заменив регион выходным

35
2.02.2010 03:50:04
Используйте Mx mark-whole-buffer впереди, чтобы пометить содержимое всего буфера как область для обработки.
Harald 12.08.2017 06:14:03

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

(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)))

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

19
2.12.2015 16:44:53
Это дало мне ошибку в GNU Emacs 24, поэтому я изменил последнюю строку на:(indent-region 0 (count-lines (point-min) (point-max)))
John J. Camilleri 8.01.2014 10:05:43

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

  • the 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!"))
8
8.05.2013 17:13:11

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

<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=

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

5
4.11.2011 02:32:33

Я взял версию Джейсона Вирса и добавил логику для размещения объявлений 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!"))
2
23.05.2017 11:33:24

Я использую 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))
)
1
3.02.2014 15:30:45

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

M-x sgml-mode
M-x sgml-pretty-print
19
31.05.2016 07:52:00

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

M-x spacemacs/indent-region-or-buffer
1
10.08.2016 08:33:32

по состоянию на 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/

1
7.04.2017 03:30:12