我使用emacs编辑我的xml文件(nxml-mode),并且这些文件是由计算机生成的,没有任何漂亮的标记格式。
我已经搜索了漂亮的带有缩进的整个文件打印并保存了,但是找不到自动方式。
有办法吗?或者至少在Linux上有一些可以做到的编辑器。
Answers:
当我要格式化和缩进XML或HTML时,我使用nXML模式进行编辑和整理。Tidy还有一个Emacs界面。
您甚至不需要编写自己的函数-sgml-mode(一个gnu emacs核心模块)具有一个内置的漂亮打印函数,称为(sgml-pretty-print ...),该函数接受区域的开始和结束参数。
如果您要剪切和粘贴xml,并且发现终端在任意位置剪切线,则可以使用此漂亮的打印机来首先修复虚线。
sgml-mode
随着时间的流逝会有怎样的变化。今天,我调用了C-x C-f foo.xml
,M-x sgml-mode
然后M-x sgml-pretty-print
xml文件被漂亮地打印了。(好吧,emacs在完成前挂了20秒或更长时间。这是漂亮打印之前的一行文件,之后是720行。)
C-x g
选择整个缓冲区作为区域。
C-x h
,然后选择M-x sgml-pretty-print
。xml现在将进行漂亮的格式化
如果只需要缩进而不引入任何新的换行符,则可以indent-region
通过以下按键将命令应用于整个缓冲区:
C-x h
C-M-\
如果还需要引入换行符,以使开始和结束标签位于单独的行上,则可以使用由Benjamin Ferrari编写的以下非常好的elisp函数。我在他的博客上找到了它,希望我可以在此处复制它:
(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!"))
这不依赖于Tidy这样的外部工具。
感谢上面的蒂姆·赫尔姆施泰特,我这样写了:
(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)))
快速简便。非常感谢。
(indent-region 0 (count-lines (point-min) (point-max)))
用于引入换行符,然后进行漂亮的打印
M-x sgml-mode
M-x sgml-pretty-print
这是我对本杰明·法拉利(Benjamin Ferrari)版本的一些调整:
search-forward-regexp
没有指定一个结束,所以它会在东西从区域的开始到结束缓冲运行(而不是区域的结束)end
如Cheeso所述,现在可以正确增加。<tag></tag>
,从而修改其值。是的,从技术上讲,我们正在修改此处所有内容的值,但是空的开始/结束很可能很重要。现在使用两个单独的,更严格的搜索来避免这种情况。仍然有“不依靠外部整洁”,等等。但是,它需要cl
的incf
宏。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 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!"))
我采用了Jason Viers的版本,并添加了将xmlns声明放在自己的行上的逻辑。假设您有xmlns =和xmlns:且中间没有空格。
(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!"))
我xml-reformat-tags
从xml-parse.el使用。通常,运行此命令时,您希望将点放在文件的开头。
有趣的是,该文件已合并到Emacspeak中。当我每天使用Emacspeak时,我以为xml-reformat-tags
是Emacs内置的。有一天,我丢失了它,不得不在互联网上搜索它,因此进入了上面提到的Wiki页面。
我还要附加我的代码以启动xml-parse。不知道这是否是Emacs代码的最佳片段,但似乎对我有用。
(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))
)
截至2017年,emacs默认已经具有此功能,但是您必须将此小功能写入您的~/.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))))
然后打电话 M-x reformat-xml
来源:https : //davidcapello.com/blog/emacs/reformat-xml-on-emacs/
恐怕我会更喜欢本杰明·法拉利版本。内部漂亮的打印内容总是将结束标记放在该值之后的新行中,从而在标记值中插入不必要的CR。
wrong type argument: stringp, nil