相关:如何在(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>
相关:如何在(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>
当前回答
xmllint
这个实用程序附带libxml2-utils:
echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
xmllint --format -
Perl的XML::树枝
这个命令附带了XML::Twig perl模块,有时是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
检查整齐的包装:
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())'
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'
其他回答
xidel:
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()})保存到文件中。
xmllint
这个实用程序附带libxml2-utils:
echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
xmllint --format -
Perl的XML::树枝
这个命令附带了XML::Twig perl模块,有时是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
检查整齐的包装:
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())'
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'
您没有提到文件,所以我假设您想在命令行上提供XML字符串作为标准输入。在这种情况下,请执行以下操作:
$ echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' | xmllint --format -
编辑:
免责声明:您通常应该更喜欢安装像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*来解决这个问题。
无需在macOS /大多数Unix上安装任何东西。
使用整洁
Cat filename.xml | tidy -xml -iq .xml
使用cat重定向查看文件,指定xml文件类型为tidy,并在安静输出时缩进,将抑制错误输出。JSON也可以使用-json。