2008-08-15 6 views
73

Ich benutze Emacs, um meine XML-Dateien (nxml-Modus) zu bearbeiten und die Dateien wurden von Maschine generiert haben keine schöne Formatierung der Tags.Pretty Drucken von XML-Dateien auf Emacs

Ich habe gesucht, die ganze Datei mit Einrückung hübsch auszudrucken und es zu speichern, aber war nicht in der Lage, einen automatischen Weg zu finden.

Gibt es einen Weg? Oder zumindest einen Editor unter Linux, der das kann.

Antwort

23

Ich verwende nXML mode zum Bearbeiten und Tidy, wenn ich XML oder HTML formatieren und einrücken möchte. Es gibt auch an Emacs interface to Tidy.

+0

Bis Ende 2013 funktioniert die tidy.el Version: 20111222.1756 nicht auf Emacs 24 mit '' 'falschem Argument: stringp, nil''' – keiw

+0

@keiw Das ist wahrscheinlich, weil Sie es in einem Puffer tun, der keinen Dateinamen hat. Habe den gleichen Fehler und verfolgte ihn zumindest auf meiner Seite. – Alf

1

Tidy sieht wie ein guter Modus aus. Muss es anschauen. Werde es benutzen, wenn ich wirklich alle Funktionen brauche, die es bietet.

Wie auch immer, dieses Problem nagte mich seit ungefähr einer Woche und ich suchte nicht richtig. Nach dem Posten begann ich zu suchen und fand eine Seite mit einer elisp function, die es ziemlich gut macht. Der Autor schlägt auch vor, Tidy zu verwenden.

Danke für die Antwort Marcel (Schade, ich habe nicht genug Punkte, um Sie zu upmodieren) .

Wird bald darüber in meinem Blog veröffentlichen. Hier ist eine post about it (mit einem Link zu Marcel's Website).

2
  1. Emacs nxml-mode kann mit dem dargestellten Format arbeiten, aber Sie müssen die Zeilen aufteilen.
  2. Für längere Dateien, die es einfach nicht wert ist. Führen Sie dieses Stylesheet (im Idealfall mit Saxon , das IMHO die Zeile Einrückungen über Recht bekommt) gegen längere Dateien , um einen schönen schönen Druck zu erhalten. Für alle Elemente, wo Sie weißen Raum beibehalten möchten fügen Sie ihre Namen neben 'program' wie in 'program yourElementName'

HTH

85

Wenn Sie nur ziemlich Einrücken ohne neue Zeilenumbrüche einzuführen, können Sie den indent-region Befehl an den gesamten Puffer mit diesen Tastenanschläge gelten:

C-x h 
C-M-\ 

Wenn Sie auch Zeilenumbrüche müssen einzuführen, Damit öffnende und schließende Tags in separaten Zeilen stehen, könnten Sie die folgende sehr nette elisp-Funktion verwenden, die von Benjamin Ferrari geschrieben wurde. Ich fand es auf seinem Blog und hoffen, dass es in Ordnung ist für mich, es zu reproduzieren hier:

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

Dies beruht nicht auf einem externen Tool wie Tidy.

+1

Gute defun, danke. Das Entfernen des (nxml-Modus) aus dem obigen Pretty-Print-Defun erlaubt es, im sgml-Modus zu arbeiten, der in emacs 22.2.1 integriert ist. Aber ich habe es modifiziert, um den gesamten Puffer (Punkt-Min) bis (Punkt-Max) zu machen, weil das meine Hauptsache ist. Auch ein Bug: Für jede neue Zeile, die Sie einfügen, müssen Sie Ende erhöhen. – Cheeso

+0

Wie kann ich diese Funktion in Emacs verwenden? Ich habe den Funktionscode in * scratch * buffer kopiert und eingefügt und ausgewertet. Nun, wie rufe ich diese Funktion auf? –

+1

Nachdem Sie das defun ausgewertet haben, können Sie es wie jede andere Funktion aufrufen: M-x bf-pretty-print-xml-region. (Sie müssen nicht alles eingeben, natürlich Tabulatorvervollständigung: Mx bf sollte genug sein.) Sie wollen wahrscheinlich nicht die Funktion jedes Mal definieren, wenn Sie es verwenden möchten, also setzen Sie es irgendwo wo es wird zur Startzeit geladen, z in ~/.emacs.d/init.el –

93

Sie müssen nicht einmal Ihre eigene Funktion schreiben - sgml-mode (ein Gnu Emacs Kernmodul) hat eine eingebaute hübsche Druckfunktion namens (sgml-pretty-print ...), die Argumente für den Anfang und das Ende der Region übernimmt.

Wenn Sie xml ausschneiden und einfügen und feststellen, dass Ihr Terminal die Zeilen an beliebigen Stellen zerhackt, können Sie diese pretty printer verwenden, die zuerst die gestrichelten Linien fixiert.

+0

Wie führe ich eine Funktion aus, die die Region als Argument übergibt? –

+1

(sgml-pretty-print (region-anfang) (region-end)) – ScootyPuff

+3

Ich bin mir nicht sicher, wie 'sgml-mode' im Laufe der Zeit verändert haben könnte. Heute habe ich 'C-x C-f foo.xml',' M-x sgml-mode', dann 'M-x sgml-pretty-print' aufgerufen und meine XML-Datei wurde schön ausgedruckt. (Nun, Emacs erhängte sich für zwanzig oder mehr Sekunden vor dem Abschluss. Es war eine Ein-Zeilen-Datei vor dem hübschen Druck und 720 Zeilen danach.) – daveloyall

0

Ich fürchte, ich mag Benjamin Ferrari Version viel besser. Der interne Pretty-Druck platziert das End-Tag immer in eine neue Zeile nach dem Wert und fügt unerwünschte CR in die Tag-Werte ein.

33

Emacs kann beliebige Befehle mit M- | ausführen. Wenn Sie xmllint installiert:

"M- | xmllint --format -" wird der ausgewählte Bereich zu formatieren

"Cu M- | xmllint --format -" das Gleiche tun, anstelle der Region mit der

Ausgang
+0

@bubak unten skripted dies. Vielen Dank! –

+0

Verwenden Sie M-x Mark-Whole-Buffer vorne, um den gesamten Pufferinhalt als zu verarbeitende Region zu markieren. – Harald

17

Dank Tim Helmstedt oben I st wie folgt aus:

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

schnell und einfach. Danke vielmals.

+2

Dies gab mir einen Fehler auf GNU Emacs 24, also änderte ich die letzte Zeile zu: '(Einrückung-Bereich 0 (Zähllinien (Punkt-Min) (Punkt-Max))) –

7

hier ein paar Tweaks ich Benjamin Ferrari-Version gemacht:

  • die search-forward-regexp kein Ende angegeben hat, so wäre es auf Sachen von Anfang Region bis zum Ende des Puffers (statt Ende Region arbeiten)
  • Jetzt inkrementen end richtig, wie Cheeso festgestellt.
  • würde es eine Pause zwischen <tag></tag> einfügen, die seinen Wert ändert. Ja, technisch modifizieren wir hier alles, aber ein leerer Anfang/Ende ist viel wahrscheinlicher. Jetzt werden zwei separate, etwas stringentere Suchanfragen verwendet, um dies zu vermeiden.

Noch hat die „beruht nicht auf externe ordentlich“ usw. Es ist jedoch cl für das Makro incf erfordert.

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

Eine Möglichkeit, zu tun, ist Wenn Sie etwas in folgendem Format

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

In Emacs haben, versuchen

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

Dies wird indent oben xml Beispiel auf unter

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

In VI M Sie können dies tun, indem Sie

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

Hoffen, dass dies hilft.

2

Ich nahm Jason Viers' version und Logik hinzugefügt, um XMLNs-Deklarationen auf ihren eigenen Zeilen zu setzen. Dies setzt voraus, dass Sie xmlns = und xmlns haben: ohne dazwischenliegende Leerzeichen.

(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

Ich benutze xml-reformat-tags von xml-parse.el.Normalerweise möchten Sie den Punkt am Anfang der Datei haben, wenn Sie diesen Befehl ausführen. Es ist interessant, dass die Datei in Emacspeak integriert ist. Als ich Emacspeak Tag für Tag benutzte, dachte ich, xml-reformat-tags ist ein Emacs eingebaut. Eines Tages habe ich es verloren und musste dafür eine Suche im Internet durchführen und betrat die oben erwähnte Wiki-Seite.

Ich füge auch meinen Code an, um xml-parse zu starten. Nicht sicher, ob das der beste Emacs Code ist, aber scheint für mich zu funktionieren.

(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

Für Zeilenumbrüche Einführung und dann ziemlich Druck

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

Wenn Sie spacemacs verwenden, verwenden Sie einfach den Befehl 'spacemacs/indent-region-oder-Puffer'.

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

ab 2017 Emacs kommt bereits mit dieser Fähigkeit standardmäßig, aber Sie haben diese kleine Funktion in Ihre ~/.emacs.d/init.el schreiben:

(require 'sgml-mode) 

(defun reformat-xml() 
    (interactive) 
    (save-excursion 
    (sgml-pretty-print (point-min) (point-max)) 
    (indent-region (point-min) (point-max)))) 

dann rufen Sie einfach M-x reformat-xml

Quelle: https://davidcapello.com/blog/emacs/reformat-xml-on-emacs/