Хорошая печать XML-файлов на Emacs

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
84
0
40 789
15
Перейти к ответу Данный вопрос помечен как решенный

Ответы 15

Ответ принят как подходящий

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

К концу 2013 года tidy.el Версия: 20111222.1756 не может работать на Emacs 24 с wrong type argument: stringp, nil.

keiw 21.12.2013 16:38

@keiw Вероятно, это потому, что вы делаете это в буфере, у которого нет имени файла. Получил ту же ошибку и проследил ее, по крайней мере, на моей стороне.

Alf 21.01.2014 17:10

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

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

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

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

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

HTH

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

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

Хорошее определение, спасибо. Удаление (nxml-mode) из приведенного выше defun-файла pretty-print позволяет ему работать в sgml-режиме, встроенном в emacs 22.2.1. Но я изменил его, чтобы сделать весь буфер (точка-мин) на (точка-макс), потому что это мое главное. Также есть одна ошибка: для каждой новой строки, которую вы вставляете, вам нужно будет увеличивать конец.

Cheeso 03.06.2009 19:33

Как я могу использовать эту функцию в Emacs? Я скопировал и вставил код функции в буфер царапать и оценил его. Как мне вызвать эту функцию?

Alexandre Rademaker 21.02.2011 15:01

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

Christian Berg 22.02.2011 19:50

Как насчет того, чтобы сломать длинные списки атрибутов?

ceving 21.09.2012 16:33

Это потрясающе, потому что tidy жалуется на недопустимые кодировки символов и хочет, чтобы я их очистил перед, он переформатирует файл! Иногда дело в том, чтобы увидеть структуру неработающего xml-файла, и приборка отказывается помочь.

TauPan 23.05.2016 11:45

для каждого (insert "\n") вам также необходимо увеличить end на 1, чтобы сделать отступ для всей области, иначе вы можете пропустить последние несколько строк. Это исправление уже было добавлено в ссылку в блоге Бенджамина Феррари, указанную в этом ответе.

Kind Stranger 19.08.2020 16:40

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

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

Как выполнить функцию, передающую регион в качестве аргумента?

Alexandre Rademaker 08.12.2010 02:33

(sgml-pretty-print (начало региона) (конец региона))

ScootyPuff 04.01.2011 18:57

Я не уверен, как sgml-mode мог измениться с течением времени. Сегодня я вызвал C-x C-f foo.xml, M-x sgml-mode, затем M-x sgml-pretty-print, и мой xml-файл распечатался довольно хорошо. (Ну, emacs зависал на двадцать секунд или более перед завершением. Это был однострочный файл до красивого вывода и 720 строк после него.)

daveloyall 10.08.2015 21:14

Собственно, мне тоже пришлось сделать C-x g, чтобы выделить весь буфер как область.

daveloyall 10.08.2015 23:23

Мне даже не пришлось переходить в sgml-режим. Это была команда M-x в режиме nXML!

nroose 04.07.2018 04:04

Используя Emacs 26.2, я могу оставаться в режиме nXML, выбрать весь буфер C-x h, а затем M-x sgml-pretty-print. Теперь xml будет хорошо отформатирован

Swedgin 12.08.2019 16:03

В 2020 году кажется, что sgml-pretty-print по-прежнему невероятно медленный для простых улучшений формата.

NetMage 09.11.2020 23:56

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

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

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

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

Используйте M-x mark-all-buffer впереди, чтобы пометить все содержимое буфера как область для обработки.

Harald 12.08.2017 09:14

Благодаря Тиму Хелмстедту я сделал это так:

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

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

Это дало мне ошибку в GNU Emacs 24, поэтому я изменил последнюю строку на: (indent-region 0 (count-lines (point-min) (point-max)))

John J. Camilleri 08.01.2014 14:05

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

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

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

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

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

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

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

Если вы используете 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/

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