Frage

Ich verwende Emacs, um meine XML-Dateien zu bearbeiten (nxml-Modus), und die Dateien wurden maschinell generiert und haben keine schöne Formatierung der Tags.

Ich habe nach einer Möglichkeit gesucht, die gesamte Datei mit Einrückung auszudrucken und zu speichern, konnte aber keinen automatischen Weg finden.

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

War es hilfreich?

Lösung

ich benutze nXML-Modus zum Bearbeiten und Ordentlich wenn ich XML oder HTML formatieren und einrücken möchte.Es gibt auch eine Emacs-Schnittstelle zu Tidy.

Andere Tipps

Sie müssen nicht einmal Ihre eigene Funktion schreiben – sgml-mode (ein GNU-Emacs-Kernmodul) verfügt über eine integrierte Pretty-Printing-Funktion namens (sgml-pretty-print ...), die Regionsanfangs- und -endargumente entgegennimmt.

Wenn Sie XML ausschneiden und einfügen und feststellen, dass Ihr Terminal die Zeilen an beliebigen Stellen abschneidet, können Sie dies verwenden hübscher Drucker Dadurch werden zunächst unterbrochene Linien behoben.

Wenn Sie nur eine hübsche Einrückung benötigen, ohne neue Zeilenumbrüche einzuführen, können Sie Folgendes anwenden indent-region Befehl an den gesamten Puffer mit diesen Tastenkombinationen:

C-x h
C-M-\

Wenn Sie auch Zeilenumbrüche einführen müssen, damit öffnende und schließende Tags in separaten Zeilen stehen, können Sie die folgende sehr schöne Elisp-Funktion verwenden, geschrieben von Benjamin Ferrari.Ich habe es auf seinem Blog gefunden und hoffe, dass es für mich in Ordnung ist, es hier zu reproduzieren:

(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 erfordert kein externes Tool wie Tidy.

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

„M-| xmllint --format -“ formatiert die ausgewählte Region

„C-u M-| xmllint --format -“ macht dasselbe und ersetzt die Region durch die Ausgabe

Dank Tim Helmstedt oben habe ich Folgendes gemacht:

(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.Vielen Dank.

Zum Einführen von Zeilenumbrüchen und zum anschließenden hübschen Drucken

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

Hier sind ein paar Änderungen, die ich an Benjamin Ferraris Version vorgenommen habe:

  • Die search-forward-regexp hat kein Ende angegeben, daher würde es sich um Dinge vom Anfang der Region bis zum Ende des Puffers handeln (anstelle des Endes der Region).
  • Jetzt inkrementiert end richtig, wie Cheeso bemerkte.
  • es würde eine Pause dazwischen einfügen <tag></tag>, wodurch sich sein Wert ändert.Ja, technisch gesehen ändern wir hier die Werte von allem, aber ein leerer Anfang/Ende ist viel wahrscheinlicher von Bedeutung.Um dies zu vermeiden, werden jetzt zwei separate, etwas strengere Suchvorgänge verwendet.

Es gibt immer noch die Funktion „Verlässt sich nicht auf externe Ordnung“ usw.Es ist jedoch erforderlich cl für die incf Makro.

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

Eine Möglichkeit, wenn Sie etwas im folgenden Format haben

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

Versuchen Sie es in Emacs

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

Dadurch wird das obige XML-Beispiel nach unten eingerückt

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

In VIM können Sie dies tun

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

Hoffe das hilft.

  1. Der Emacs-nxml-Modus kann mit dem dargestellten Format arbeiten, Sie müssen jedoch die Zeilen aufteilen.
  2. Für längere Dateien lohnt sich das einfach nicht.Führen Sie dieses Stylesheet aus (idealerweise mit Saxon, das IMHO über die richtigen Dateien richtet) gegen längere Dateien, um einen schönen hübschen Druck zu erhalten.Für alle Elemente, in denen Sie White Space behalten möchten, fügen Sie ihre Namen neben "ProgrammListing" wie in "ProgrammListing YourElementName" hinzu

HTH

ich nahm Jason Viers' Version und Logik hinzugefügt, um xmlns-Deklarationen in eigene Zeilen einzufügen.Dies setzt voraus, dass Sie xmlns= und xmlns haben:ohne dazwischen liegende 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!"))

Tidy scheint ein guter Modus zu sein.Muss es mir ansehen.Ich werde es verwenden, wenn ich wirklich alle Funktionen benötige, die es bietet.

Jedenfalls beschäftigte mich dieses Problem etwa eine Woche lang und ich suchte nicht richtig.Nach dem Posten begann ich mit der Suche und fand eine Website mit einem Elisp-Funktion Das macht es ziemlich gut.Der Autor schlägt außerdem die Verwendung von Tidy vor.

Danke für die Antwort, Marcel (Schade, dass ich nicht genug Punkte habe, um dich zu aktualisieren).

Ich werde bald darüber auf meinem Blog berichten. Hier ist ein Beitrag darüber (mit einem Link zu Marcels Seite).

ich benutze xml-reformat-tags aus xml-parse.el.Normalerweise möchten Sie den Punkt am Anfang der Datei haben, wenn Sie diesen Befehl ausführen.

Interessant ist, dass die Datei eingebunden ist Emacspeak.Als ich Emacspeak täglich nutzte, dachte ich xml-reformat-tags ist ein eingebauter Emacs.Eines Tages verlor ich es und musste im Internet danach suchen und gelangte so auf die oben erwähnte Wiki-Seite.

Ich hänge auch meinen Code an, um die XML-Analyse zu starten.Ich bin mir nicht sicher, ob dies der beste Teil des Emacs-Codes ist, aber er 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))
)

Wenn du benutzt Spacemacs, verwenden Sie einfach den Befehl „spacemacs/indent-region-or-buffer“.

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

Ich fürchte, mir gefällt die Version von Benjamin Ferrari viel besser.Der interne Pretty-Print platziert das End-Tag immer in einer neuen Zeile nach dem Wert und fügt so unerwünschte CR in die Tag-Werte ein.

Ab 2017 verfügt Emacs bereits standardmäßig über diese Funktion, Sie müssen diese kleine Funktion jedoch in Ihr Programm schreiben ~/.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))))

dann ruf einfach an M-x reformat-xml

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top