如何从命令行中打印XML?

时间:2013-04-18 18:50:04

标签: xml unix command-line

相关:How can I pretty-print JSON in (unix) shell script?

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

基本上,我希望它能改变以下内容:

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

...变成这样的东西:

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

11 个答案:

答案 0 :(得分:795)

<强> 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

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'

答案 1 :(得分:128)

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

<强> Cygwin的

apt-cyg install libxml2

<强>的MacOS

要使用Homebrew在MacOS上安装此功能,请执行以下操作: brew install libxml2

<强> GIT中

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

答案 2 :(得分:33)

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

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

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

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

答案 3 :(得分:12)

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

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

答案 4 :(得分:6)

xmllint support formatting in-place

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

当XML文档被破坏时,您可能缺少--recover选项。或者尝试使用严格的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

答案 5 :(得分:3)

这使我永远无法找到适用于我的Mac的东西。这是对我有用的东西:

brew install xmlformat
cat unformatted.html | xmlformat

答案 6 :(得分:0)

编辑:

免责声明::您通常应该安装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*来解决该问题。

答案 7 :(得分:0)

我会

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$ 

如果仅仅是因为它是“在”数据库中,而不是“仅”在文件中。在我看来,使用起来更容易。

相信其他人已经解决了这个问题。如果您愿意,毫无疑问eXist甚至可能在格式化xml方面还是“更好”,甚至还不错。

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

答案 8 :(得分:0)

使用

xidel -s input.xml -e 'serialize(.,{"indent":true()})'
<root>
  <foo a="b">lorem</foo>
  <bar value="ipsum"/>
</root>

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

答案 9 :(得分:0)

这个简单的(st)解决方案不提供缩进,但是在人眼上却更容易。此外,它还允许使用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

答案 10 :(得分:-1)

不在Mac上安装任何东西

使用tidy

cat filename.xml | tidy -xml -iq

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