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


526

有关: 如何在(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>

1
xmllint在Debian系统上可用,您需要安装软件包libxml2-utilslibxml2不提供此工具,至少在Debian 5.0“ Lenny”和6.0“ Squeeze”上不提供)。
twonkeys 2013年

Answers:


908

libxml2-utils

该实用程序附带libxml2-utils

echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
    xmllint --format -

Perl的 XML::Twig

该命令附带 XML :: Twig 模块,有时xml-twig-tools打包:

echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
    xml_pp

xmlstarlet

该命令附带xmlstarlet

echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
    xmlstarlet format --indent-tab

tidy

检查tidy包装:

echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
    tidy -xml -i -

蟒蛇

Python xml.dom.minidom可以格式化XML(python2和python3):

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

saxon-lint

您需要saxon-lint

echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
    saxon-lint --indent --xpath '/' -

saxon-HE

您需要saxon-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'

好,快速的答案。第一种选择似乎在现代* nix安装中将更加普遍。次要点;但是可以不通过中间文件来调用它吗?即,echo '<xml .. />' | xmllint --some-read-from-stdn-option
svidgen

libxml2-utils在我美丽的Ubuntu中。
franzlorenzon 2014年

1
请注意,“ cat data.xml | xmllint --format-| tee data.xml”不起作用。在我的系统上,它有时适用于小文件,但始终会截断大文件。如果你真的想这样做在任何地方阅读backreference.org/2011/01/29/in-place-editing-of-files
user1346466

1
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 805: ordinal not in range(128)在python版本中解决,您需要定义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
FelikZ '16

1
注意,tidy还可以格式化不带root元素的xml。这对于通过管道,xml节进行格式化(例如从日志中提取)很有用。echo '<x></x><y></y>' | tidy -xml -iq
马里诺斯(Marinos)

157

xmllint --format yourxmlfile.xml

xmllint是命令行XML工具,包含在libxml2http://xmlsoft.org/)中。

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

注意:如果尚未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

苹果系统

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

吉特

如果需要代码,也可以在Git上使用: git clone git://git.gnome.org/libxml2


4
sputnick的答案包含此信息,但是crmpicco的答案是有关如何漂亮地打印XML的一般问题的最有用的答案。
赛斯·迪夫利

2
我们可以将格式化的xml输出写到其他xml文件中,并使用它。例如xmllint --format yourxmlfile.xml >> new-file.xml
LearnToLive 2016年

2
在Ubuntu 16.04上,您可以使用以下命令:sudo apt-get install libxml2-utils
Melle

这也适用于Windows。gitWindows的下载甚至安装的最新版本xmllint。示例:"C:\Program Files\Git\usr\bin\xmllint.exe" --format QCScaper.test@borland.com.cds.xml > QCScaper.test@borland.com.pretty-printed.cds.xml
Jeroen Wiert Pluimers

41

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

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

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

注意:具有许多其他可读性标志,但是自动换行的行为有点令人讨厌,无法解开(http://tidy.sourceforge.net/docs/quickref.html)。


1
很有帮助,因为我无法让xmllint将换行符添加到单个行xml文件中。谢谢!
xlttj 2014年

tidy对我也很好 与不同hxnormalize,此操作实际上会关闭<body>标签。
Sridhar Sarnobat

9
顺便说一句,以下是我发现有用的一些选项:tidy --indent yes --indent-spaces 4 --indent-attributes yes --wrap-attributes yes --input-xml yes --output-xml yes < InFile.xml > OutFile.xml
Victor Yarema '16

2
大提示@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
Net Wolf

13

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

$ echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' | xmllint --format -

12

在macOS /大多数Unix上无需安装任何软件。

采用 tidy

cat filename.xml | tidy -xml -iq

使用cat重定向查看文件以整洁地指定xml的文件类型,并在静默输出时缩进以抑制错误输出。JSON也可用于-json


1
您不需要执行以下cat步骤:tidy -xml -iq filename.xml。另外,您甚至可以tidy -xml -iq filename.xml使用该-m选项来修改原始文件...
janniks

10

xmllint支持就地格式化

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

正如Daniel Veillard所写:

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

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

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

--recoverXML文档损坏时,可能缺少选项。或者尝试使用具有严格XML输出的弱HTML解析器:

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

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

apt-get install libxml2-utils
apt-cyg install libxml2
brew install libxml2


1

我想添加一个纯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*在正则表达式中添加一些额外的东西来解决该问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.