85

我使用 emacs 编辑我的 xml 文件(nxml 模式),并且这些文件是由机器生成的,没有任何漂亮的标签格式。

我已经搜索了带有缩进的漂亮打印整个文件并保存它,但无法找到自动方式。

有办法吗?或者至少有一些 Linux 上的编辑器可以做到这一点。

4

15 回答 15

113

您甚至不需要编写自己的函数 - sgml-mode(一个 gnu emacs 核心模块)有一个名为 (sgml-pretty-print ...) 的内置漂亮打印函数,它接受区域开始和结束参数。

如果您正在剪切和粘贴 xml,并且您发现您的终端正在任意位置截断线条,您可以使用这台漂亮的打印机,它首先修复断线。

于 2009-02-27T16:47:05.117 回答
89

如果您只需要漂亮的缩进而不引入任何新的换行符,则可以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 这样的外部工具。

于 2009-02-20T15:41:39.950 回答
35

Emacs 可以使用 M-| 运行任意命令。如果您安装了 xmllint:

"M-| xmllint --format -" 将格式化所选区域

"Cu M-| xmllint --format -" 将做同样的事情,用输出替换区域

于 2010-02-02T03:50:04.800 回答
25

当我想格式化和缩进 XML 或 HTML 时,我使用nXML 模式进行编辑和整理。Tidy还有一个 Emacs 接口。

于 2008-08-15T17:47:29.893 回答
20

感谢上面的 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)))

快速简单。非常感谢。

于 2010-11-25T21:00:50.373 回答
20

用于引入换行符,然后进行漂亮的打印

M-x sgml-mode
M-x sgml-pretty-print
于 2016-05-31T07:52:00.807 回答
8

这是我对 Benjamin Ferrari 的版本进行的一些调整:

  • 没有search-forward-regexp指定结束,因此它将对从区域开始到缓冲区结束(而不是区域结束)的内容进行操作
  • end正如 Cheeso 所指出的,现在正确递增。
  • 它将在 之间插入一个中断<tag></tag>,从而修改其值。是的,从技术上讲,我们正在修改这里所有内容的值,但是空的开始/结束更可能是重要的。现在使用两个单独的、稍微更严格的搜索来避免这种情况。

仍然有“不依赖外部整洁”等。但是,它确实需要clincf

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 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!"))
于 2011-03-04T19:19:28.820 回答
5

一种方法是如果您有以下格式的内容

<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=

希望这可以帮助。

于 2011-11-04T02:32:33.367 回答
2
  1. Emacs nxml-mode 可以处理呈现的格式,但您必须拆分行。
  2. 对于根本不值得的较长文件。对较长的文件运行此样式表(最好使用 Saxon,恕我直言,行缩进正确)以获得漂亮的打印效果。对于要保留空格的任何元素,请在“programlisting”旁边添加它们的名称,如“programlisting yourElementName”

高温高压

于 2008-09-12T08:14:40.567 回答
2

我采用了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!"))
于 2013-01-29T18:21:56.437 回答
1

整洁看起来是一个不错的模式。必须看看它。如果我真的需要它提供的所有功能,我会使用它。

无论如何,这个问题困扰了我大约一个星期,我没有正确搜索。发布后,我开始搜索并找到一个具有elisp 功能的网站,它做得很好。作者还建议使用 Tidy。

感谢 Marcel 的回答(太糟糕了,我没有足够的积分来升级你)

很快就会在我的博客上发布它。这是一篇关于它的帖子(带有指向 Marcel 网站的链接)。

于 2008-08-15T18:09:10.227 回答
1

xml-reformat-tagsxml-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))
)
于 2014-02-02T14:35:39.653 回答
1

如果您使用spacemacs,只需使用命令“spacemacs/indent-region-or-buffer”。

M-x spacemacs/indent-region-or-buffer
于 2016-08-10T08:33:32.453 回答
1

自 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/

于 2017-04-07T03:22:12.277 回答
0

恐怕我更喜欢本杰明法拉利版本。内部漂亮的打印总是将结束标签放在值之后的新行中,在标签值中插入不需要的 CR。

于 2009-05-12T18:18:21.687 回答