如何从命令行漂亮地打印XML?

How to pretty print XML from the command line?

提问人:svidgen 提问时间:4/19/2013 最后编辑:Communitysvidgen 更新时间:11/12/2023 访问量:411072

问:

相关:如何在 (unix) shell 脚本中漂亮打印 JSON?

是否有 (unix) shell 脚本以人类可读的形式格式化 XML?

基本上,我希望它转换以下内容:

<root><foo a="b">lorem</foo><bar value="ipsum" /></root>

...变成这样的东西:

<root>
    <foo a="b">lorem</foo>
    <bar value="ipsum" />
</root>
xml unix 命令行 perl xidel

评论

1赞 twonkeys 9/20/2013
要在 Debian 系统上可用,您需要安装软件包( 不提供此工具,至少在 Debian 5.0 “Lenny” 和 6.0 “Squeeze”上不提供)。xmllintlibxml2-utilslibxml2
1赞 Sam Mason 3/29/2022
如今,Web 浏览器(例如 Firefox / Chrome)往往可以很好地打印漂亮的 XML 文档。(作为评论发布,因为这不是 CLI,而是一个非常方便的替代方案)

答:

1154赞 Gilles Quénot 4/19/2013 #1

来自 libxml2 的 xmllint

xmllint --format file.xml

(在基于 Debian 的发行版上安装 libxml2-utils 软件包)

XML::Twig 模块xml_pp

xml_pp < file.xml

(在基于 Debian 的发行版上安装 xml-twig-tools 软件包)

XMLStarlet

xmlstarlet format --indent-tab file.xml

整洁

tidy -xml -i file.xml

Python 的 xml.dom.minidom

echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
  python -c 'import sys, xml.dom.minidom; print(xml.dom.minidom.parseString(sys.stdin.read()).toprettyxml())'

Saxon-lint(我自己的项目)

saxon-lint --indent --xpath '/' file.xml

撒克逊-HE

echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
  java -cp /usr/share/java/saxon/saxon9he.jar net.sf.saxon.Query \
       -s:- -qs:/ '!indent=yes'

西德尔

xidel --output-node-format=xml --output-node-indent -se . -s file.xml

(归功于 Reino)

所有命令的输出:

<root>
  <foo a="b">lorem</foo>
  <bar value="ipsum"/>
</root>

评论

0赞 svidgen 4/19/2013
好,快速回答。第一个选项似乎在现代 *nix 安装中会更加普遍。一个小问题;但是可以在不处理中间文件的情况下调用它吗?即,?echo '<xml .. />' | xmllint --some-read-from-stdn-option
2赞 user1346466 12/4/2014
请注意,“cat data.xml |xmllint --格式 - |三通数据.xml“不起作用。在我的系统上,它有时适用于小文件,但总是截断大文件。如果你真的想做任何事情,请阅读 backreference.org/2011/01/29/in-place-editing-of-files
3赞 FelikZ 11/2/2016
要在 python 版本中求解,您要定义:UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 805: ordinal not in range(128)PYTHONIOENCODING="UTF-8"cat some.xml | PYTHONIOENCODING="UTF-8" python -c 'import sys;import xml.dom.minidom;s=sys.stdin.read();print xml.dom.minidom.parseString(s).toprettyxml()' > pretty.xml
4赞 Marinos An 10/9/2019
请注意,tidy 还可以格式化没有根元素的 xml。这对于通过管道、xml 部分(例如从日志中提取)进行格式化很有用。echo '<x></x><y></y>' | tidy -xml -iq
1赞 Markus 12/9/2019
没有找到任何着色选项?有什么提示吗?现在我使用 vim 来获取着色,但是我必须创建一个新格式化的 xml 才能再次具有良好的可读性
15赞 David 4/19/2013 #2

您没有提到文件,因此我假设您希望在命令行上提供 XML 字符串作为标准输入。在这种情况下,请执行以下操作:

$ echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' | xmllint --format -
190赞 crmpicco 11/15/2013 #3

xmllint --format yourxmlfile.xml

xmllint 是一个命令行 XML 工具,包含在 (http://xmlsoft.org/) 中。libxml2

================================================

注意:如果您没有安装 libxml2,您可以通过执行以下操作来安装它:

CentOS 操作系统

cd /tmp
wget ftp://xmlsoft.org/libxml2/libxml2-2.8.0.tar.gz
tar xzf libxml2-2.8.0.tar.gz
cd libxml2-2.8.0/
./configure
make
sudo make install
cd

Ubuntu的

sudo apt-get install libxml2-utils

天鹅云

apt-cyg install libxml2

MacOS操作系统

要使用 Homebrew 在 MacOS 上安装它,只需执行以下操作:brew install libxml2

Git的

如果你想要代码,也可以在 Git 上找到:git clone git://git.gnome.org/libxml2

评论

4赞 Seth Difley 11/27/2014
sputnick 的回答包含了这些信息,但 crmpicco 的回答是关于如何漂亮打印 XML 的一般问题最有用的答案。
4赞 LearnToLive 1/13/2016
我们可以将格式化的XML输出写出到其他XML文件中,并使用它。例如 xmllint --format yourxmlfile.xml >>new-file.xml
2赞 Melle 1/24/2017
在 Ubuntu 16.04 上,您可以使用以下命令:sudo apt-get install libxml2-utils
1赞 Jeroen Wiert Pluimers 12/21/2017
这也适用于 Windows;git for Windows 下载甚至会安装最新版本的 .例:xmllint"C:\Program Files\Git\usr\bin\xmllint.exe" --format [email protected] > [email protected]
0赞 Ax_ 7/6/2021
从 MacOS 中,通过 brew 安装了 libxml2。要取消缩小 xml 并将其保存到一个新文件中,它使用了以下命令xmllint --format in.xml > out.xml
46赞 matanster 10/13/2014 #4

您也可以使用 tidy,它可能需要先安装(例如在 Ubuntu 上:sudo )。apt-get install tidy

为此,您将发出如下内容:

tidy -xml -i your-file.xml > output.xml

注意:有许多额外的可读性标志,但自动换行行为有点烦人(http://tidy.sourceforge.net/docs/quickref.html)。

评论

1赞 xlttj 11/13/2014
很有帮助,因为我无法让 xmllint 向单行 xml 文件添加换行符。谢谢!
0赞 Sridhar Sarnobat 11/26/2014
tidy对我来说也很有效。与此不同的是,这样做实际上是关闭标签。hxnormalize<body>
13赞 Victor Yarema 2/19/2016
顺便说一句,这里有一些我发现有用的选项:.tidy --indent yes --indent-spaces 4 --indent-attributes yes --wrap-attributes yes --input-xml yes --output-xml yes < InFile.xml > OutFile.xml
3赞 Net Wolf 11/13/2017
很棒的提示@VictorYarema。我将它与 pygmentize 结合起来,并将其添加到我的 .bashrc: 中,然后可以alias prettyxml='tidy --indent yes --indent-spaces 4 --indent-attributes yes --wrap-attributes yes --input-xml yes --output-xml yes | pygmentize -l xml'curl url | prettyxml
14赞 gavenkoa 5/29/2018 #5

XMLLINT 支持就地格式化

for f in *.xml; do xmllint -o $f --format $f; done

正如丹尼尔·韦拉德(Daniel Veillard)所写:

我认为应该是安全的,因为解析器会将输入完全加载到树中 在打开输出进行序列化之前。xmllint -o tst.xml --format tst.xml

缩进级别由环境变量控制,默认情况下为 2 个空格。如何将缩进更改为 4 个空格的示例:XMLLINT_INDENT

XMLLINT_INDENT='    '  xmllint -o out.xml --format in.xml

当您的XML文档被破坏时,您可能缺少选项。或者尝试使用严格的 XML 输出的弱 HTML 解析器:--recover

xmllint --html --xmlout <in.xml >out.xml

--nsclean、 、 等可能有用。阅读手册页。--nonet--nocdata--noblanks

apt-get install libxml2-utils
dnf install libxml2
apt-cyg install libxml2
brew install libxml2
21赞 jasonleonhard 5/10/2019 #6

无需在macOS / 大多数Unix上安装任何东西。

tidy

cat filename.xml | tidy -xml -iq

将使用 cat 查看文件重定向到 tidy,指定 xml 的文件类型,并在安静输出时缩进将抑制错误输出。JSON 也适用于 。-json

评论

2赞 janniks 3/3/2020
您不需要步骤:。此外,您甚至可以使用该选项来修改原始文件...cattidy -xml -iq filename.xmltidy -xml -iq filename.xml-m
3赞 Sridhar Sarnobat 3/16/2020 #7

我花了很长时间才找到在我的 Mac 上运行的东西。以下是对我有用的东西:

brew install xmlformat
cat unformatted.html | xmlformat
0赞 Leon S. 5/7/2020 #8

编辑:

免责声明:您通常应该更喜欢安装成熟的工具,例如完成这样的工作。XML/HTML 可能是一个可怕的残缺不全的混乱。但是,在某些情况下,使用现有工具比手动安装新工具更可取,并且可以肯定的是,XML 的源代码是有效的(足够)。我已经为其中一种情况编写了这个脚本,但它们很少见,所以在之前要谨慎。xmllint


我想添加一个纯粹的 Bash 解决方案,因为手动完成并不难,有时您不想安装额外的工具来完成这项工作。

#!/bin/bash

declare -i currentIndent=0
declare -i nextIncrement=0
while read -r line ; do
  currentIndent+=$nextIncrement
  nextIncrement=0
  if [[ "$line" == "</"* ]]; then # line contains a closer, just decrease the indent
    currentIndent+=-1
  else
    dirtyStartTag="${line%%>*}"
    dirtyTagName="${dirtyStartTag%% *}"
    tagName="${dirtyTagName//</}"
    # increase indent unless line contains closing tag or closes itself
    if [[ ! "$line" =~ "</$tagName>" && ! "$line" == *"/>"  ]]; then
      nextIncrement+=1
    fi
  fi

  # print with indent
  printf "%*s%s" $(( $currentIndent * 2 )) # print spaces for the indent count
  echo $line
done <<< "$(cat - | sed 's/></>\n</g')" # separate >< with a newline

将其粘贴到脚本文件中,然后通过管道将 xml 传送。 这假定 xml 都在一行上,并且任何地方都没有多余的空格。人们可以很容易地在正则表达式中添加一些额外的东西来解决这个问题。\s*

评论

1赞 Gilles Quénot 6/16/2020
希望永远不要在某个地方看到这个作为系统管理员 -_-
0赞 Leon S. 6/19/2020
@GillesQuenot 什么意思?是否存在我没有看到的安全风险?
0赞 Gilles Quénot 6/19/2020
因为使用真正的解析器以外的任何东西来解析 XML/HTML 是(或很快就会)有缺陷的。如果是个人电脑上的小型个人脚本,由您决定,但用于生产,没办法。它会打破!
0赞 Leon S. 6/19/2020
我同意 XML/HTML 可能会被严重破坏,但它确实取决于来源。我为我们自己生成的一些 XML 编写了这篇文章,所以这是一个非常安全的赌注。
1赞 Gilles Quénot 6/19/2020
直到实习生改变 XML 的制作方式:)
0赞 Nicholas Saunders 11/22/2020 #9

我会:

nicholas@mordor:~/flwor$ 
nicholas@mordor:~/flwor$ cat ugly.xml 


<root><foo a="b">lorem</foo><bar value="ipsum" /></root>

nicholas@mordor:~/flwor$ 
nicholas@mordor:~/flwor$ basex
BaseX 9.0.1 [Standalone]
Try 'help' to get more information.
> 
> create database pretty
Database 'pretty' created in 231.32 ms.
> 
> open pretty
Database 'pretty' was opened in 0.05 ms.
> 
> set parser xml
PARSER: xml
> 
> add ugly.xml
Resource(s) added in 161.88 ms.
> 
> xquery .
<root>
  <foo a="b">lorem</foo>
  <bar value="ipsum"/>
</root>
Query executed in 179.04 ms.
> 
> exit
Have fun.
nicholas@mordor:~/flwor$ 

如果只是因为它“在”数据库中,而不是“只是”文件。在我看来,更容易合作。

相信其他人已经解决了这个问题。如果您愿意,毫无疑问,甚至可能在格式方面“更好”,或者同样好。eXistxml

当然,您始终可以通过各种不同的方式查询数据。我尽可能保持简单。您也可以只使用 GUI,但您指定了控制台。

1赞 Reino 11/29/2020 #10

使用

$ xidel -s input.xml -e . --output-node-format=xml --output-node-indent
$ xidel -s input.xml -e 'serialize(.,{"indent":true()})'

$ echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' | \
  xidel -se . --output-node-format=xml --output-node-indent
$ echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' | \
  xidel -se 'serialize(.,{"indent":true()})'

评论

0赞 potong 8/11/2023
第一个解决方案似乎已过时,因为这两个选项都不在,尽管第二个解决方案没有抛出错误(回显的解决方案需要接收标准输入),但这也不会缩进 xml。xidel --help-xidel
0赞 Reino 8/12/2023
@potong 请使用最新的二进制文件
0赞 potong 8/13/2023
这是基于上一个官方版本 Xidel 0.9.8。
4赞 nby 12/10/2020 #11

这种简单的解决方案不提供压痕,但对人眼来说要容易得多。此外,它还允许通过简单的工具(如 grep、head、awk 等)更轻松地处理 xml。

用于将“<”替换为前面的换行符。sed

正如 Gilles 所提到的,在生产中使用它可能不是一个好主意。

# check you are getting more than one line out
sed 's/</\n</g' sample.xml | wc -l

# check the output looks generally ok
sed 's/</\n</g' sample.xml | head

# capture the pretty xml in a different file
sed 's/</\n</g' sample.xml > prettySample.xml

评论

2赞 Arthur Bowers 5/23/2022
感谢您的回复,无需下载任何内容。
0赞 Gilles Quénot 12/5/2022
sed不是 XML 解析器
1赞 jpseng 11/11/2022 #12

yq 可用于漂亮地打印 XML。 它有一个定义缩进的选项。

yq --input-format xml --output-format xml --indent 2

评论

0赞 Sergey Ponomarev 3/19/2023
还有 yq -P,但我试过了,看起来并没有真正起作用。刚刚生成了一个格式良好的 XMLyq --input-format xml --output-format xml