我使用 emacs 编辑我的 xml 文件(nxml 模式),并且这些文件是由机器生成的,没有任何漂亮的标签格式。
我已经搜索了带有缩进的漂亮打印整个文件并保存它,但无法找到自动方式。
有办法吗?或者至少有一些 Linux 上的编辑器可以做到这一点。
您甚至不需要编写自己的函数 - sgml-mode(一个 gnu emacs 核心模块)有一个名为 (sgml-pretty-print ...) 的内置漂亮打印函数,它接受区域开始和结束参数。
如果您正在剪切和粘贴 xml,并且您发现您的终端正在任意位置截断线条,您可以使用这台漂亮的打印机,它首先修复断线。
如果您只需要漂亮的缩进而不引入任何新的换行符,则可以indent-region
使用以下击键将该命令应用于整个缓冲区:
C-x h
C-M-\
如果您还需要引入换行符,以便开始和结束标签在不同的行上,您可以使用以下非常好的 elisp 函数,由Benjamin Ferrari编写。我在他的博客上找到了它,希望我可以在这里复制它:
(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 这样的外部工具。
Emacs 可以使用 M-| 运行任意命令。如果您安装了 xmllint:
"M-| xmllint --format -" 将格式化所选区域
"Cu M-| xmllint --format -" 将做同样的事情,用输出替换区域
感谢上面的 Tim Helmstedt,我做了这样的 st:
(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)))
快速简单。非常感谢。
用于引入换行符,然后进行漂亮的打印
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!"))
一种方法是如果您有以下格式的内容
<abc> <abc><abc> <abc></abc> </abc></abc> </abc>
在 Emacs 中,尝试
M-x nxml-mode
M-x replace-regexp RET > *< RET >C-q C-j< RET
C-M-\ to indent
这会将上面的 xml 示例缩进到下面
<abc>
<abc>
<abc>
<abc>
</abc>
</abc>
</abc>
</abc>
在 VIM 中,您可以通过
:set ft=xml
:%s/>\s*</>\r</g
ggVG=
希望这可以帮助。
高温高压
我采用了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 内置的。有一天我把它弄丢了,不得不在网上搜索它,然后就进入了上面提到的维基页面。
我还附上了我的代码以启动 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))
)
如果您使用spacemacs,只需使用命令“spacemacs/indent-region-or-buffer”。
M-x spacemacs/indent-region-or-buffer
自 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。