簡體   English   中英

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

[英]How to pretty print XML from the command line?

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

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'

xmllint --format yourxmlfile.xml

xmllint是一個命令行 XML 工具,包含在libxml2 ( http://xmlsoft.org/ ) 中。

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

注意:如果您沒有安裝libxml2 ,您可以通過執行以下操作來安裝它:

中央操作系統

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

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

為此,您將發出如下內容:

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

注意:有許多額外的可讀性標志,但自動換行行為有點煩人( http://tidy.sourceforge.net/docs/quickref.html )。

無需在 macOS / 大多數 Unix 上安裝任何東西。

使用tidy

cat filename.xml | tidy -xml -iq

使用 cat 重定向查看文件以整齊指定 xml 的文件類型並在安靜輸出時縮進將抑制錯誤輸出。 JSON 也適用於-json

您沒有提到文件,所以我假設您想在命令行上提供 XML 字符串作為標准輸入。 在這種情況下,請執行以下操作:

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

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

當您的 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

我花了很長時間才找到可以在我的 Mac 上運行的東西。 這對我有用:

brew install xmlformat
cat unformatted.html | xmlformat

這種簡單的(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

編輯:

免責聲明:您通常應該更喜歡安裝像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$ 

如果只是因為它“在”一個數據庫中,而不是“只是”一個文件。 在我看來,更容易使用。

相信其他人已經解決了這個問題。 如果您願意,毫無疑問eXist在格式化xml方面甚至可能“更好”,或者一樣好。

當然,您始終可以以各種不同的方式查詢數據。 我盡量保持簡單。 您也可以只使用 GUI,但您指定了控制台。

使用

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()})保存到文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM