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

相关:# EYZ0

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

基本上,我想要它转换如下:

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

... 变成这样:

<root>
<foo a="b">lorem</foo>
<bar value="ipsum" />
</root>
390758 次浏览

# EYZ0

这个实用程序带有libxml2-utils:

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

Perl的# EYZ0

这个命令带有XML::树枝 模块,有时是xml-twig-tools包:

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

# EYZ0

这个命令带有xmlstarlet:

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

# EYZ0

检查tidy包:

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

Python

Python的xml.dom.minidom可以格式化XML(也适用于遗留的python2):

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

# EYZ0

你需要saxon-lint:

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

# EYZ0

你需要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'

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

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

# EYZ0

xmllint是一个命令行XML工具,包含在libxml2 (http://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

# EYZ0

Cygwin

# EYZ0

MacOS

要在MacOS上使用Homebrew安装此程序,只需执行以下操作: # EYZ0 < / p >

Git

如果你想要代码,也可以在Git上使用: # EYZ0 < / p >

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

为此,您可以发布如下内容:

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

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

# EYZ0:

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

正如丹尼尔·维拉德所写:

我认为< p > # EYZ0 当解析器将输入完全加载到树中时,应该是安全的吗

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

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

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

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

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

使用# EYZ0

# EYZ0

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

我花了很长时间才找到能在我的mac上运行的软件。以下是对我有效的方法:

brew install xmlformat
cat unformatted.html | xmlformat

编辑:

免责声明:你通常更喜欢安装一个成熟的工具,如xmllint来完成这样的工作。XML/HTML可能是一团乱麻。但是,在某些情况下,使用现有工具比手动安装新工具更可取,而且可以肯定XML的源代码是有效的(足够有效)。我为其中一种情况编写了这个脚本,但这种情况很少见,所以请谨慎使用。


我想添加一个纯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*来修复这个问题

我想:

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$

如果只是因为它是&;in"一个数据库,而不是“just”;一个文件。在我看来,更容易处理。

相信别人已经解决了这个问题。如果你愿意,毫无疑问eXist甚至可能“更好”;在格式xml,或一样好。

当然,您总是可以以各种不同的方式查询数据。我尽量让它简单。您也可以只使用GUI,但您指定了控制台。

与# EYZ0:

xidel -s input.xml -se . --output-node-format=xml --output-node-indent
<root>
<foo a="b">lorem</foo>
<bar value="ipsum"/>
</root>

file:write("output.xml",.,{"indent":true()})保存到文件中。

这个简单的解决方案不提供缩进,但对人眼来说要容易得多。此外,它还允许使用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

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

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