Красивая печать XML-файлов на Emacs - PullRequest
79 голосов
/ 15 августа 2008

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

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

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

Ответы [ 15 ]

99 голосов
/ 27 февраля 2009

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

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

85 голосов
/ 20 февраля 2009

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

C-x h
C-M-\

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

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

34 голосов
/ 02 февраля 2010

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

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

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

25 голосов
/ 15 августа 2008

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

19 голосов
/ 26 ноября 2010

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

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

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

18 голосов
/ 31 мая 2016

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

M-x sgml-mode
M-x sgml-pretty-print
8 голосов
/ 04 марта 2011

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

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

По-прежнему имеет «не полагаться на внешнюю чистоту» и т. Д. Однако для макроса 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'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!"))
5 голосов
/ 04 ноября 2011

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

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

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

2 голосов
/ 29 января 2013

Я взял версию Джейсона Вирса и добавил логику для помещения объявлений 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 голосов
/ 12 сентября 2008
  1. Emacs nxml-mode может работать в представленном формате, но вам придется разбить строки.
  2. Для более длинных файлов, которые просто не стоят этого. Запустите эту таблицу стилей (в идеале с Saxon который ИМХО получает строки отступы о праве) против длинных файлов чтобы получить красивый красивый принт. Для любых элементов, где вы хотите сохранить пустое пространство добавьте их имена вместе с «programlisting» как в «programlisting yourElementName»

НТН

...