2008-08-15 9 views
73

Utilizo emacs para editar mis archivos xml (nxml-mode) y los archivos generados por la máquina no tienen ningún formato bonito de las etiquetas.Impresión bonita de archivos XML en Emacs

He buscado bastante impresión de todo el archivo con sangría y guardarlo, pero no fue capaz de encontrar de una manera automática.

¿Hay alguna manera? O al menos algún editor en Linux que pueda hacerlo.

Respuesta

23

Uso nXML mode para editar y Tidy cuando quiero formatear y aplicar sangría a XML o HTML. También hay an Emacs interface to Tidy.

+0

A finales de 2013 tidy.el Versión: 20111222.1756 falla al ejecutarse en Emacs 24 con '' 'argumento de tipo incorrecto: stringp, nil''' – keiw

+0

@keiw Eso es probablemente porque lo estás haciendo en un búfer que no tiene un nombre de archivo. Obtuve el mismo error y lo remonté a eso de mi lado al menos. – Alf

1

Tidy parece un buen modo. Debe mirarlo. Lo usaré si realmente necesito todas las características que ofrece.

De todos modos, este problema me molestaba durante aproximadamente una semana y no estaba buscando correctamente. Después de publicar, comencé a buscar y encontré un sitio con un elisp function que lo hace bastante bien. El autor también sugiere usar Tidy.

Gracias por responder Marcel (lástima que no tengo suficientes puntos para upmod usted) .

Lo publicaré pronto en mi blog. Aquí hay un post about it (con un enlace al sitio de Marcel).

2
  1. Emacs nxml-mode puede funcionar en formato presentado, pero tendrá que dividir las líneas.
  2. Para archivos más largos que simplemente no valen la pena. Ejecute esta hoja de estilo (idealmente con Saxon , que en mi humilde opinión obtiene las sangrías de línea a la derecha) en comparación con los archivos más largos, , para obtener una bonita impresión bonita. Para cualquier elemento en el que desea conservar espacio en blanco añadir sus nombres junto a 'programlisting' como en 'programlisting yourElementName'

HTH

85

Si sólo necesita bastante sangría sin introducir ningún nuevo saltos de línea, se puede aplicar el comando indent-region a toda la memoria intermedia con estas teclas:

C-x h 
C-M-\ 

Si también necesita introducir saltos de línea, para que las etiquetas de apertura y cierre estén en líneas separadas, puede usar la siguiente función de elisp muy agradable, escrita por Benjamin Ferrari. Lo encontré en su blog y espero que sea bien para mí para reproducir aquí:

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

Esto no se basa en una herramienta externa como ordenado.

+1

Bueno, defun, gracias. La eliminación de (modo nxml) del defun de impresión bonita anterior le permite funcionar en el modo sgml que está incorporado en emacs 22.2.1. Pero lo modifiqué para hacer todo el buffer (punto-min) a (punto-máximo) porque eso es lo principal. Además, un error: por cada nueva línea que inserte, necesitará aumentar el final. – Cheeso

+0

¿Cómo puedo usar esta función en Emacs? He copiado y pegado el código de la función en * scratch * buffer y lo he evaluado. Ahora, ¿cómo invoco esta función? –

+1

Después de evaluar el defun, puede invocarlo como cualquier otra función: M-x bf-pretty-print-xml-region. (No tiene que escribirlo todo, por supuesto, use la terminación de pestañas: Mx bf debería ser suficiente). Probablemente no quiera definir la función cada vez que quiera usarla, así que colóquela en algún lugar donde se carga al inicio, por ejemplo en ~/.emacs.d/init.el –

93

Ni siquiera necesita escribir su propia función - sgml-mode (un módulo core de gnu emacs) tiene una función de impresión muy bonita llamada (sgml-pretty-print ...) que toma los argumentos de inicio y fin de la región.

Si está cortando y pegando xml y encuentra que su terminal está cortando las líneas en lugares arbitrarios, puede usar este pretty printer que repara primero las líneas quebradas.

+0

¿Cómo ejecuto una función que pasa la región como argumento? –

+1

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

+3

No estoy seguro de cómo 'sgml-mode' podría haber cambiado con el tiempo. Hoy, invoqué 'C-x C-f foo.xml',' M-x sgml-mode', luego 'M-x sgml-pretty-print' y mi archivo xml quedó bastante impreso. (Bueno, emacs colgó durante veinte segundos o más antes de completar. Era un archivo de una línea antes de la bonita impresión y 720 líneas después). – daveloyall

0

Me temo que me gusta la versión de Benjamin Ferrari mucho mejor. La bonita impresión interna siempre coloca la etiqueta final en una nueva línea después del valor, insertando CR no deseado en los valores de etiqueta.

33

Emacs puede ejecutar comandos arbitrarios con M- |. Si tiene instalado xmllint:

"M- | --format xmllint -" va a dar formato a la región seleccionada

"Cu M- | --format xmllint -" hará lo mismo, en sustitución de la región con el salida

+0

@bubak debajo de este script. ¡Gracias! –

+0

Use M-x mark-whole-buffer al frente para marcar todo el contenido del buffer como la región a procesar. – Harald

17

Gracias a Tim Helmstedt anterior que hice st como esto:

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

rápido y fácil. Muchas gracias.

+2

Esto me dio un error en GNU Emacs 24, así que cambié la última línea a: '(indent-region 0 (count-lines (point-min) (point-max)))' –

7

He aquí algunos ajustes que hice a la versión de Benjamin Ferrari:

  • la search-forward-regexp no especificaron su fin, por lo que operaría en la materia desde el principio de la región a fin de tampón (en lugar del final de la región)
  • Ahora aumenta end correctamente, como señaló Cheeso.
  • insertaría una pausa entre <tag></tag>, que modifica su valor. Sí, técnicamente estamos modificando los valores de todo aquí, pero es mucho más probable que un inicio/final vacío sea significativo. Ahora usa dos búsquedas separadas, un poco más estrictas para evitar eso.

todavía tiene el "no se basa en ordenada externa", etc. Sin embargo, sí requiere cl para la 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!")) 
5

Una forma de hacerlo es Si usted tiene algo de debajo del formato

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

En Emacs, intenta

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

Este guión voluntad por encima de ejemplo XML a continuación

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

En VI M usted puede hacer esto por

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

Espero que esto ayude.

2

Tomé Jason Viers' version y agregué lógica para poner declaraciones xmlns en sus propias líneas. Esto supone que tiene xmlns = y xmlns: sin espacios en blanco intermedios.

(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

utilizo xml-reformat-tags de xml-parse.el.Por lo general, querrá tener el punto al principio del archivo al ejecutar este comando.

Es interesante que el archivo esté incorporado en Emacspeak. Cuando estaba usando Emacspeak día a día, pensé que xml-reformat-tags es un E-Buil incorporado. Un día lo perdí y tuve que hacer una búsqueda en Internet para eso, y así ingresé a la página wiki mencionada anteriormente.

Adjunto también mi código para iniciar xml-parse. No estoy seguro de si esta es la mejor pieza de código de Emacs, pero parece funcionar para mí.

(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

para introducir saltos de línea y luego imprimir bastante

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

Si utiliza spacemacs, sólo tiene que utilizar el mandato de spacemacs/guión-región-o-buffer '.

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

partir de 2017 emacs ya viene con esta capacidad por defecto, pero usted tiene que escribir esta pequeña función en su ~/.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)))) 

luego simplemente llamar M-x reformat-xml

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

Cuestiones relacionadas