Utilizo emacs para editar mis archivos xml (modo nxml) y los archivos generados por la máquina no tienen un formato bonito de las etiquetas.
He buscado bastante imprimir todo el archivo con sangría y guardarlo, pero no pude encontrar una forma automática.
¿Hay alguna manera? O al menos algún editor en Linux que pueda hacerlo.
wrong type argument: stringp, nil
Ni siquiera necesita escribir su propia función: sgml-mode (un módulo principal de gnu emacs) tiene una función de impresión bonita incorporada llamada (sgml-pretty-print ...) que toma los argumentos de inicio y final 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 esta bonita impresora que corrige las líneas discontinuas primero.
fuente
sgml-mode
pudo haber cambiado con el tiempo. Hoy en día, invoquéC-x C-f foo.xml
,M-x sgml-mode
y, a continuaciónM-x sgml-pretty-print
y mi archivo xml puso bastante impresa. (. Bueno, emacs colgados durante veinte segundos o más antes de completar Fue un archivo de una línea antes de la impresión bonita y después de 720 líneas.)C-x g
para seleccionar todo el búfer como región.C-x h
y luegoM-x sgml-pretty-print
. El xml estará bastante formateado ahoraSi solo necesita una sangría bastante sin introducir nuevos saltos de línea, puede aplicar el
indent-region
comando a todo el búfer con estas pulsaciones de teclas:C-x h C-M-\
Si también necesita introducir saltos de línea, de modo que las etiquetas de apertura y cierre estén en líneas separadas, puede usar la siguiente función elisp muy agradable, escrita por Benjamin Ferrari . Lo encontré en su blog y espero que esté bien para mí reproducirlo 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") (setq end (1+ end))) (indent-region begin end)) (message "Ah, much better!"))
Esto no depende de una herramienta externa como Tidy.
fuente
Emacs puede ejecutar comandos arbitrarios con M- |. Si tiene xmllint instalado:
"M- | xmllint --format -" formateará la región seleccionada
"Cu M- | xmllint --format -" hará lo mismo, reemplazando la región con la salida
fuente
Gracias a Tim Helmstedt arriba hice st así:
(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)))
rapido y facil. Muchas gracias.
fuente
(indent-region 0 (count-lines (point-min) (point-max)))
Para introducir saltos de línea y luego una bonita impresión
M-x sgml-mode M-x sgml-pretty-print
fuente
aquí hay algunos ajustes que hice a la versión de Benjamin Ferrari:
search-forward-regexp
no especificó un final, por lo que operaría en cosas desde el principio de la región hasta el final del búfer (en lugar del final de la región)end
correctamente, como señaló Cheeso.<tag></tag>
, lo 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 depende del orden externo", etc. Sin embargo, sí lo requiere
cl
para laincf
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!"))
fuente
Una forma de hacerlo es si tiene algo en el siguiente formato
<abc> <abc><abc> <abc></abc> </abc></abc> </abc>
En Emacs, intente
M-x nxml-mode M-x replace-regexp RET > *< RET >C-q C-j< RET C-M-\ to indent
Esto sangrará el ejemplo xml anterior al siguiente
<abc> <abc> <abc> <abc> </abc> </abc> </abc> </abc>
En VIM puede hacer esto
:set ft=xml :%s/>\s*</>\r</g ggVG=
Espero que esto ayude.
fuente
HTH
fuente
Tomé versión Jason Viers' y la lógica añadido para poner xmlns declaraciones 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!"))
fuente
Tidy parece un buen modo. Debo mirarlo. Lo usaré si realmente necesito todas las funciones que ofrece.
De todos modos, este problema me estuvo molestando durante aproximadamente una semana y no estaba buscando correctamente. Después de publicar, comencé a buscar y encontré un sitio con una función elisp que lo hace bastante bien. El autor también sugiere usar Tidy.
Gracias por la respuesta Marcel
(lástima que no tengo suficientes puntos para mejorarte).Publicaré sobre esto pronto en mi blog.Aquí hay una publicación al respecto (con un enlace al sitio de Marcel).fuente
Yo uso
xml-reformat-tags
de xml-parse.el . Por lo general, querrá tener el punto al principio del archivo cuando ejecute 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
era un Emacs 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)) )
fuente
Si usa spacemacs , simplemente use el comando 'spacemacs / indent-region-or-buffer'.
M-x spacemacs/indent-region-or-buffer
fuente
A partir de 2017, emacs ya viene con esta capacidad de forma predeterminada, pero debe 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))))
entonces solo llama
M-x reformat-xml
fuente: https://davidcapello.com/blog/emacs/reformat-xml-on-emacs/
fuente
Me temo que me gusta mucho más la versión de Benjamin Ferrari. La impresión bonita interna siempre coloca la etiqueta final en una nueva línea después del valor, insertando CR no deseado en los valores de la etiqueta.
fuente