在 Emacs 上漂亮地打印 XML 文件

发布于 2024-07-04 05:31:29 字数 150 浏览 4 评论 0 原文

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

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

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

I use emacs to edit my xml files (nxml-mode) and the files were generated by machine don't have any pretty formatting of the tags.

I have searched for pretty printing the entire file with indentation and saving it, but wasn't able to find an automatic way.

Is there a way? Or atleast some editor on linux which can do it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

不喜欢何必死缠烂打 2024-07-11 05:31:30

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

M-x sgml-mode
M-x sgml-pretty-print

For introducing line breaks and then pretty printing

M-x sgml-mode
M-x sgml-pretty-print
凉栀 2024-07-11 05:31:30

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

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

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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 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!"))

here's a few tweaks I made to Benjamin Ferrari's version:

  • the search-forward-regexp didn't specify an end, so it would operate on stuff from beginning of region to end of buffer (instead of end of region)
  • Now increments end properly, as Cheeso noted.
  • it would insert a break between <tag></tag>, which modifies its value. Yes, technically we're modifying values of everything here, but an empty start/end is much more likely to be significant. Now uses two separate, slightly more strict searches to avoid that.

Still has the "doesn't rely on external tidy", etc. However, it does require cl for the incf 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!"))
偏闹i 2024-07-11 05:31:30

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

快速而简单。 非常感谢。

Thanks to Tim Helmstedt above I made st like this:

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

fast and easy. Many thanks.

萌梦深 2024-07-11 05:31:30

我使用 xml-reformat-tags “nofollow">xml-parse.el。 通常,在运行此命令时,您会希望该点位于文件的开头。

有趣的是,该文件已合并到 Emacspeak 中。 当我日常使用 Emacspeak 时,我认为 xml-reformat-tags 是 Emacs 内置的。 有一天我把它弄丢了,不得不在网上搜索它,于是进入了上面提到的维基页面。

我还附上了启动 xml 解析的代码。 不确定这是否是最好的 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))
)

I use xml-reformat-tags from xml-parse.el. Usually you will want to have the point at the beginning of the file when running this command.

It's interesting that the file is incorporated into Emacspeak. When I was using Emacspeak on day-by-day basis, I thought xml-reformat-tags is an Emacs builtin. One day I lost it and had to make an internet search for that, and thus entered the wiki page mentioned above.

I'm attaching also my code to start xml-parse. Not sure if this is the best piece of Emacs code, but seems to work for me.

(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))
)
≈。彩虹 2024-07-11 05:31:30

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

M-x spacemacs/indent-region-or-buffer

If you use spacemacs, just use command 'spacemacs/indent-region-or-buffer'.

M-x spacemacs/indent-region-or-buffer
梦屿孤独相伴 2024-07-11 05:31:30

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

I'm afraid I like Benjamin Ferrari version much better. The internal pretty print always places the end tag in a new line after the value, inserting unwanted CR in the tag values.

伊面 2024-07-11 05:31:30

截至 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))))

然后只需调用 Mx reformat-xml

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

as of 2017 emacs already comes with this capability by default, but you have to write this little function into your ~/.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))))

then just call M-x reformat-xml

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

百合的盛世恋 2024-07-11 05:31:30

一种做法是
如果您

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

希望这会有所帮助。

One way of doing is
If you have something in below format

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

In Emacs, try

M-x nxml-mode
M-x replace-regexp RET  > *< RET >C-q C-j< RET 
C-M-\ to indent

This will indent above xml example to below

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

In VIM you can do this by

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

Hope this helps.

憧憬巴黎街头的黎明 2024-07-11 05:31:30

我使用 nXML 模式 进行编辑和 Tidy 当我想要格式化和缩进 XML 或 HTML 时。 还有Tidy 的 Emacs 界面

I use nXML mode for editing and Tidy when I want to format and indent XML or HTML. There is also an Emacs interface to Tidy.

酒几许 2024-07-11 05:31:30

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

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

“Cu M-| xmllint --format -”将执行相同操作,用输出替换该区域

Emacs can run arbitrary commands with M-|. If you have xmllint installed:

"M-| xmllint --format -" will format the selected region

"C-u M-| xmllint --format -" will do the same, replacing the region with the output

夏天碎花小短裙 2024-07-11 05:31:30

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

C-x h
C-M-\

如果您还需要引入换行符,以便打开和结束标签位于单独的行上,您可以使用以下非常好的 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 这样的外部工具。

If you only need pretty indenting without introducing any new line-breaks, you can apply the indent-region command to the entire buffer with these keystrokes:

C-x h
C-M-\

If you also need to introduce line-breaks, so that opening and closing tags are on separate lines, you could use the following very nice elisp function, written by Benjamin Ferrari. I found it on his blog and hope it's ok for me to reproduce it here:

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

This doesn't rely on an external tool like Tidy.

疧_╮線 2024-07-11 05:31:30

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

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

You don't even need to write your own function - sgml-mode (a gnu emacs core module) has a built-in pretty printing function called (sgml-pretty-print ...) which takes region beginning and end arguments.

If you are cutting and pasting xml and you find your terminal is chopping the lines in arbitrary places you can use this pretty printer which fixes broken lines first.

任性一次 2024-07-11 05:31:30

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

I took Jason Viers' version and added logic to put xmlns declarations on their own lines. This assumes that you have xmlns= and xmlns: with no intervening whitespace.

(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!"))
世态炎凉 2024-07-11 05:31:30

整洁看起来是一个很好的模式。 一定要看看。 如果我确实需要它提供的所有功能,我会使用它。

不管怎样,这个问题困扰了我大约一个星期,而且我没有正确地搜索。 发帖后,我开始搜索,发现一个带有 的网站elisp 函数 做得很好。 作者还建议使用Tidy。

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

很快就会在我的博客上发布有关它的信息。这是一个发布相关内容(带有 Marcel 网站的链接)。

Tidy looks like a good mode. Must look at it. Will use it if I really need all the features it offers.

Anyway, this problem was nagging me for about a week and I wasn't searching properly. After posting, I started searching and found one site with an elisp function which does it pretty good. The author also suggests using Tidy.

Thanks for answer Marcel (too bad I don't have enough points to upmod you).

Will post about it soon on my blog. Here is a post about it (with a link to Marcel's site).

╰◇生如夏花灿烂 2024-07-11 05:31:30
  1. Emacs nxml-mode 可以在呈现的格式上工作,但您必须拆分行。
  2. 对于较长的文件来说,这是不值得的。 运行这个样式表(最好使用 Saxon
    恕我直言,对于较长的文件,行缩进大约是正确的)
    以获得漂亮的打印效果。 对于任何想要保留空白的元素
    将他们的名字添加到“programlisting”旁边,如“programlisting yourElementName”

HTH

  1. Emacs nxml-mode can work on presented format, but you'll have to split the lines.
  2. For longer files that simply isn't worth it. Run this stylesheet (ideally with Saxon
    which IMHO gets the line indents about right) against longer files
    to get a nice pretty print. For any elements where you want to retain white space
    add their names alongside 'programlisting' as in 'programlisting yourElementName'

HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文