Ładne drukowanie plików XML na Emacsie

Używam Emacsa do edycji plików xml (tryb nxml) i pliki zostały wygenerowane przez maszynę nie mają żadnego ładnego formatowania znaczników.

Szukałem ładnego wydruku całego pliku z wcięciami i zapisaniem go, ale nie mogłem znaleźć automatycznego sposobu.

Jest jakiś sposób? Albo przynajmniej jakiś edytor na Linuksie, który potrafi to zrobić.

Author: Community, 2008-08-15

15 answers

Używam trybu nXMLdo edycji i Tidy Kiedy chcę sformatować i wciąć XML lub HTML. Istnieje również interfejs Emacs do uporządkowania.

 24
Author: Marcel Levy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-23 00:59:41

Nie musisz nawet pisać własnej funkcji-sgml-mode (moduł rdzeniowy gnu emacs) ma wbudowaną funkcję pretty printing o nazwie (sgml-pretty-print ...), która pobiera argumenty rozpoczynające i kończące region.

Jeśli wycinasz i wklejasz xml i zauważysz, że twój terminal rąbie linie w dowolnych miejscach, możesz użyć tej pretty printer, która najpierw naprawia łamane linie.

 96
Author: Juan Garcia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-27 16:47:05

Jeśli potrzebujesz tylko ładnego wcięcia bez wprowadzania nowych podziałów linii, możesz zastosować polecenie indent-region do całego bufora za pomocą tych naciśnięć klawiszy:

C-x h
C-M-\

Jeśli musisz również wprowadzić podziały linii, aby znaczniki otwierające i zamykające były na oddzielnych liniach, możesz użyć poniższej bardzo ładnej funkcji elisp, napisanej przez Benjamina Ferrari . Znalazłem go na jego blogu i mam nadzieję, że mogę go tutaj odtworzyć: {]}

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

To nie polega na zewnętrznym narzędziu, takim jak Schludnie.

 85
Author: Christian Berg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-20 16:51:01

Emacs może uruchamiać dowolne polecenia z M|/. Jeśli masz zainstalowany xmllint:

"m - | xmllint --format -" sformatuje wybrany region

"C - U M - | xmllint --format -" zrobi to samo, zamieniając region na wyjście

 33
Author: Tim Helmstedt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-02 03:50:04

Dzięki Timowi Helmstedtowi powyżej zrobiłem st tak:

(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)))
Szybko i łatwo. Wielkie dzięki.
 18
Author: bubak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-02 16:44:53

Do wprowadzania podziałów linii, a następnie ładnego drukowania

M-x sgml-mode
M-x sgml-pretty-print
 14
Author: Talespin_Kit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-31 07:52:00

Oto kilka poprawek, które zrobiłem do wersji Benjamina Ferrari:

  • search-forward-regexp nie określał końca, więc operował na rzeczach od początku regionu do końca bufora (zamiast końca regionu)
  • Teraz zwiększa end prawidłowo, jak zauważył Cheese.
  • wstawia przerwę między <tag></tag>, która modyfikuje jego wartość. Tak, technicznie modyfikujemy wartości wszystkiego, ale pusty początek/koniec jest znacznie bardziej prawdopodobny. Teraz używa dwóch oddzielnych, nieco bardziej rygorystyczne poszukiwania, aby tego uniknąć.

Nadal ma "nie opiera się na zewnętrznej tidy", itp. Jednak wymaga cl dla makra 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!"))
 7
Author: Jason Viers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-08 17:13:11

Jednym ze sposobów jest Jeśli masz coś w poniższym formacie

<abc>     <abc><abc>   <abc></abc> </abc></abc>       </abc>

W Emacsie spróbuj

M-x nxml-mode
M-x replace-regexp RET  > *< RET >C-q C-j< RET 
C-M-\ to indent

Spowoduje to wcięcie powyżej przykładu xml do poniżej

<abc>
  <abc>
    <abc>
      <abc>
      </abc>
    </abc>
  </abc>
</abc>

W VIM możesz to zrobić przez

:set ft=xml
:%s/>\s*</>\r</g
ggVG=
Mam nadzieję, że to pomoże.
 5
Author: user1028948,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-04 02:32:33
  1. Emacs nxml-mode może pracować na prezentowanym formacie, ale będziesz musiał podzielić linie.
  2. dla dłuższych plików, które po prostu nie są tego warte. Uruchom ten arkusz stylów (najlepiej z Saxon które IMHO dostaje wcięcia linii o prawo) na dłuższych plikach aby uzyskać ładny, ładny odcisk. Dla wszystkich elementów, w których chcesz zachować białą spację dodaj ich nazwy obok 'programlisting' jak w 'programlisting yourElementName'

HTH

 2
Author: DaveP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-12 08:14:40

Wziąłem wersję Jasona Viera i dodałem logikę, aby umieścić deklaracje xmlns na własnych liniach. Zakłada się, że masz xmlns= i xmlns: bez interweniujących białych znaków.

(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
Author: Cheeso,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:24

Tidy wygląda jak dobry tryb. Muszę na to spojrzeć. Użyje go, jeśli naprawdę potrzebuję wszystkich funkcji, które oferuje.

W każdym razie, ten problem dręczył mnie przez około tydzień i nie szukałem prawidłowo. Po opublikowaniu zacząłem szukać i znalazłem jedną stronę z funkcją elisp , która robi to całkiem nieźle. Autor sugeruje również stosowanie Tidy.

Dzięki za odpowiedź Marcel (szkoda, że nie mam wystarczająco punktów, aby cię podnieść) .

wkrótce napiszę o tym na moim blogu. Oto post o tym (z linkiem do strony Marcela).

 1
Author: cnu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-16 06:01:12

Używam xml-reformat-tags od XML-parse.el. Zazwyczaj podczas uruchamiania tego polecenia będziesz chciał mieć punkt na początku pliku.

Interesujące jest to, że plik jest wbudowany w Emacspeak . Kiedy używałem emacspeak na co dzień, myślałem, że xml-reformat-tags jest emacsem. Pewnego dnia zgubiłem go i musiałem poszukać w Internecie i tym samym wszedłem na wspomnianą powyżej stronę wiki.

Dołączam również mój kod, aby rozpocząć XML-parse. Nie jestem pewien, czy jest to najlepszy kawałek kodu Emacsa, ale wydaje się działać dla mnie.

(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
Author: Jarekczek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-03 15:30:45

Jeśli używasz spacemacs , po prostu użyj polecenia "spacemacs/indent-region-or-buffer".

M-x spacemacs/indent-region-or-buffer
 1
Author: JohnnyZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-10 08:33:32

Obawiam się, że bardziej podoba mi się Wersja Benjamina Ferrari. Wewnętrzny druk pretty zawsze umieszcza znacznik końcowy w nowej linii po wartości, wstawiając niechciane CR do wartości znacznika.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-12 18:18:21

Od 2017 roku emacs jest już domyślnie wyposażony w tę funkcję, ale musisz zapisać tę małą funkcję w swoim ~/.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))))

Następnie po prostu zadzwoń M-x reformat-xml

Źródło: https://davidcapello.com/blog/emacs/reformat-xml-on-emacs/

 0
Author: ninrod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-07 03:30:12