2008-08-15 3 views
73

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

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

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

ответ

23

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

+0

К концу 2013 года tidy.el Версия: 20111222.1756 не запускается на Emacs 24 с `` `неправильным аргументом типа: stringp, nil``` – keiw 2013-12-21 12:38:16

+0

@keiw Это, вероятно, потому, что вы делаете это в буфере, у которого нет имени файла. Получил ту же ошибку и проследил ее по крайней мере на моей стороне. – Alf 2014-01-21 13:10:02

1

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

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

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

Опубликовать об этом в ближайшее время в моем блоге. Вот post about it (со ссылкой на сайт Марселя).

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

HTH

85

Если вам нужно только довольно отступы без введения каких-либо новых разрывов строк, можно применить команду 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.

+1

Хорошо defun, спасибо. Удаление (nxml-mode) из вышеприведенного символа «неплохая печать» позволяет ему работать в sgml-режиме, который встроен в emacs 22.2.1. Но я изменил его, чтобы сделать весь буфер (точка-мин) до (point-max), потому что это мое главное. Кроме того, одна ошибка: для каждой новой строки, которую вы вставляете, вам нужно будет увеличивать ее. – Cheeso 2009-06-03 15:33:44

+0

Как использовать эту функцию в Emacs? Я скопировал и вставил код функции в * scratch * buffer и оценил его. Теперь, как мне вызвать эту функцию? – 2011-02-21 12:01:34

+1

После оценки defun вы можете вызвать его, как и любую другую функцию: M-x bf-pretty-print-xml-region. (Вам не нужно набирать все это, конечно же, при использовании табуляции: Mx bf должно быть достаточно.) Вероятно, вы не хотите определять функцию каждый раз, когда хотите ее использовать, поэтому поместите ее где-нибудь там, где она загружается во время запуска, например в ~/.emacs.d/init.el – 2011-02-22 16:50:50

93

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

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

0

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

33

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

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

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

17

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

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

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

7

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

  • 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!")) 
5

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

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

В VI M вы можете сделать это

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

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

2

Я принял Jason Viers' version и добавил логику, чтобы помещать объявления 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!")) 
1

Я использую 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)) 
) 
11

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

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

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

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

от 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/

Смежные вопросы