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

当前回答

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

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

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

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

其他回答

Xmllint支持就地格式化:

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

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

我认为 Xmllint -o tst.xml——格式化tst.xml 当解析器将输入完全加载到树中时,应该是安全的吗 在打开输出序列化它之前。

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

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

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

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

——nclean,——nonet,——nocdata,——noblanks等可能有用。阅读手册页。

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

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

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

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

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

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

使用整洁

Cat filename.xml | tidy -xml -iq .xml

使用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*来解决这个问题。