漂亮的在Emacs上打印XML文件

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

我search了漂亮的打印整个文件并保存,但无法find一个自动的方式。

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

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

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

如果您正在剪切和粘贴xml,并且您发现您的terminal正在任意位置切断线条,则可以使用这台漂亮的打印机来修复虚线。

如果您只需要很小的缩进而不引入任何新的换行符,则可以使用这些击键将indent-region命令应用于整个缓冲区:

 Cx h CM-\ 

如果您还需要引入换行符,以便打开和closures标签位于单独的行中,则可以使用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")) (indent-region begin end)) (message "Ah, much better!")) 

这不依赖像Tidy这样的外部工具。

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

“M- | xmllint –format – ”将格式化选定的区域

“Cu M- | xmllint –format – ”将执行相同的操作,用输出replace区域

感谢上面的Tim Helmstedt,我这样做了:

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

快速和容易。 非常感谢。

为了引入换行符,然后漂亮的打印

 Mx sgml-mode Mx sgml-pretty-print 

这里是我对本杰明·法拉利版本的一些调整:

  • search-forward-regexp没有指定结束search-forward-regexp ,所以它将在从区域开始到缓冲区结束(而不是结束区域)
  • 正如Cheeso指出的那样,现在增量end
  • 它会在<tag></tag>之间插入一个中断,修改其值。 是的,从技术上讲,我们正在修改这里的所有东西的价值,但空的开始/结束更有可能是重要的。 现在使用两个单独的,稍微严格的search来避免这种情况。

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

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 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中,试试

 Mx nxml-mode Mx replace-regexp RET > *< RET >Cq Cj< RET CM-\ to indent 

这将缩小上面的xml例子到下面

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

在VIM中,你可以通过

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

希望这可以帮助。

  1. Emacs的nxml模式可以工作在提供的格式,但你将不得不拆分线。
  2. 对于更长的文件,根本是不值得的。 运行这个样式表(理想情况下,与恕我直言,得到行缩进左右的撒克逊)对较长的文件,以获得一个不错的漂亮打印。 对于任何要保留空白的元素,请在“programlisting yourElementName”中添加与“programlisting”一起的名称,

HTH

我拿了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!")) 

整洁看起来是一个很好的模式。 必须看看它。 将使用它,如果我真的需要它提供的所有function。

无论如何,这个问题困扰了我大约一个星期,我没有正确的search。 发布后,我开始search,发现一个网站与一个elisp函数 ,这是非常好的。 作者还build议使用Tidy。

谢谢你回答马塞尔(太糟糕了,我没有足够的积分来提升你)

将在我的博客上很快发布。 这里是一个关于它的post (链接到Marcel的网站)。

我使用xml-reformat-tags -parse.el中的 xml-reformat-tags 。 通常在运行这个命令时,你会希望在文件的开始处有一点。

有趣的是,该文件被合并到Emacspeak 。 当我日常使用Emacspeak时,我认为xml-reformat-tags是一个Emacs内置的。 有一天我失去了它,不得不进行互联网search,因此进入了上面提到的维基页面。

我也附上我的代码来启动XMLparsing。 不知道这是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'。

 Mx spacemacs/indent-region-or-buffer 

我害怕我喜欢本杰明·法拉利版本好多了。 内部漂亮的打印总是将结束标记放在一个新行后面,在标记值中插入不需要的CR。

截至2017年,emacs默认已经有了这个function,但是你必须在你的~/.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)))) 

然后调用Mx reformat-xml

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