Question

J'utilise Emacs pour éditer mes fichiers XML (mode nxml) et les fichiers ont été générés par la machine et n'ont pas de joli formatage des balises.

J'ai cherché à imprimer le fichier entier avec indentation et à l'enregistrer, mais je n'ai pas réussi à trouver un moyen automatique.

Y a-t-il un moyen ?Ou au moins un éditeur sous Linux qui peut le faire.

Était-ce utile?

La solution

j'utilise Mode nXML pour l'édition et Rangé quand je veux formater et mettre en retrait XML ou HTML.Il y a aussi une interface Emacs vers Tidy.

Autres conseils

Vous n'avez même pas besoin d'écrire votre propre fonction - sgml-mode (un module principal de Gnu Emacs) a une jolie fonction d'impression intégrée appelée (sgml-pretty-print ...) qui prend les arguments de début et de fin de région.

Si vous coupez et collez du XML et que vous constatez que votre terminal coupe les lignes à des endroits arbitraires, vous pouvez utiliser ceci jolie imprimante qui corrige d'abord les lignes brisées.

Si vous n'avez besoin que d'une jolie indentation sans introduire de nouveaux sauts de ligne, vous pouvez appliquer la indent-region commande à l'ensemble du tampon avec ces touches :

C-x h
C-M-\

Si vous devez également introduire des sauts de ligne, afin que les balises d'ouverture et de fermeture soient sur des lignes distinctes, vous pouvez utiliser la très belle fonction elisp suivante, écrite par Benjamin Ferrari.Je l'ai trouvé sur son blog et j'espère pouvoir le reproduire ici :

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

Cela ne repose pas sur un outil externe comme Tidy.

Emacs peut exécuter des commandes arbitraires avec M-|.Si xmllint est installé :

"M-| xmllint --format -" formatera la région sélectionnée

"C-u M-| xmllint --format -" fera de même, en remplaçant la région par la sortie

Merci à Tim Helmstedt ci-dessus, j'ai fait comme ceci :

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

rapide et facile.Merci beaucoup.

Pour introduire des sauts de ligne et ensuite une jolie impression

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

voici quelques modifications que j'ai apportées à la version de Benjamin Ferrari :

  • le search-forward-regexp n'a pas spécifié de fin, donc il fonctionnerait sur des éléments du début de la région à la fin du tampon (au lieu de la fin de la région)
  • Maintenant incréments end correctement, comme l'a noté Cheeso.
  • cela insérerait une pause entre <tag></tag>, ce qui modifie sa valeur.Oui, techniquement, nous modifions les valeurs de tout ici, mais un début/fin vide est beaucoup plus susceptible d'être significatif.Utilise désormais deux recherches distinctes, légèrement plus strictes, pour éviter cela.

Il y a toujours le "ne dépend pas du rangement externe", etc.Toutefois, cela nécessite cl pour le incf macro.

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

Une façon de faire est si vous avez quelque chose au format ci-dessous

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

Dans Emacs, essayez

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

Cela indentera l'exemple XML ci-dessus vers le bas

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

Dans VIM, vous pouvez le faire en

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

J'espère que cela t'aides.

  1. Le mode nxml d'Emacs peut fonctionner sur le format présenté, mais vous devrez diviser les lignes.
  2. Pour les fichiers plus longs, cela n’en vaut tout simplement pas la peine.Exécutez cette feuille de style (idéalement avec Saxon qui, à mon humble avis, obtient les indents de ligne à droite) contre les fichiers plus longs pour obtenir une jolie jolie impression.Pour tous les éléments où vous souhaitez conserver l'espace blanc, ajoutez leurs noms aux côtés de la «liste de programmes» comme dans «PROGRAMSLISTING youElementName»

HTH

j'ai pris La version de Jason Viers et ajout d'une logique pour placer les déclarations xmlns sur leurs propres lignes.Cela suppose que vous avez xmlns= et xmlns :sans espace intermédiaire.

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

Bien rangé semble être un bon mode.Il faut le regarder.Je l'utiliserai si j'ai vraiment besoin de toutes les fonctionnalités qu'il offre.

Quoi qu'il en soit, ce problème me harcelait depuis environ une semaine et je ne cherchais pas correctement.Après avoir posté, j'ai commencé à chercher et j'ai trouvé un site avec un fonction élisp ce qui le fait plutôt bien.L'auteur suggère également d'utiliser Tidy.

Merci pour la réponse Marcel (dommage que je n'ai pas assez de points pour vous mettre à jour).

J'en parlerai bientôt sur mon blog. Voici une poster à ce sujet (avec un lien vers le site de Marcel).

j'utilise xml-reformat-tags depuis xml-parse.el.Habituellement, vous souhaiterez avoir le point au début du fichier lors de l’exécution de cette commande.

Il est intéressant que le fichier soit incorporé dans Emacspeak.Lorsque j'utilisais Emacspeak au quotidien, je pensais xml-reformat-tags est un module intégré à Emacs.Un jour, je l'ai perdu et j'ai dû faire une recherche sur Internet pour le trouver, et je suis donc entré dans la page wiki mentionnée ci-dessus.

Je joins également mon code pour démarrer XML-parse.Je ne sais pas si c'est le meilleur morceau de code Emacs, mais cela semble fonctionner pour moi.

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

Si tu utilises macs spatiaux, utilisez simplement la commande 'spacemacs/indent-region-or-buffer'.

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

J'ai bien peur d'aimer beaucoup mieux la version de Benjamin Ferrari.La jolie impression interne place toujours la balise de fin dans une nouvelle ligne après la valeur, en insérant un CR indésirable dans les valeurs de la balise.

depuis 2017, emacs est déjà doté de cette fonctionnalité par défaut, mais vous devez écrire cette petite fonction dans votre ~/.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))))

alors appelle simplement M-x reformat-xml

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top