Вопрос

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

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

Благодаря Тиму Хелмстедту выше, я сделал 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)))

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

За то, что ввел разрывы строк, а затем красиво напечатал

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=

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

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

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

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

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

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

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

Я использую xml-reformat-tags От xml-синтаксический анализ.el.Обычно при выполнении этой команды требуется указывать точку в начале файла.

Интересно, что файл включен в Изможденный язык.Когда я изо дня в день пользовался Emacspeak, я думал xml-reformat-tags является встроенным в Emacs.Однажды я потерял его, и мне пришлось искать его в Интернете, и таким образом я зашел на упомянутую выше вики-страницу.

Я также прилагаю свой код для запуска xml-синтаксического анализа.Не уверен, что это лучший фрагмент кода 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/indent-region-or-buffer".

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top