コマンドラインからXMLをきれいに出力する方法は?


528

関連:(Unix)シェルスクリプトでJSONをきれいに出力するにはどうすればよいですか?

XMLを人間が読める形式にフォーマットする(UNIX)シェルスクリプトはありますか?

基本的に、私はそれが以下を変換することを望みます:

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

...このようなものに:

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

1
持っているxmllintDebianシステムで利用可能な、あなたはパッケージをインストールする必要がありますlibxml2-utilslibxml2少なくとも、ではないのDebian 5.0「レニー」と6.0「スクイーズ」に、このツールを提供していません)。
Twonkeys 2013

回答:


909

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

良い答えです。最初のオプションは、最新の* nixインストールではよりユビキタスになるようです。マイナーなポイント。しかし、中間ファイルを介さずに呼び出すことはできますか?つまり、echo '<xml .. />' | xmllint --some-read-from-stdn-option
svidgen 2013

パッケージはlibxml2-utils私の美しいubuntuにあります。
franzlorenzon 14

1
「cat data.xml | xmllint --format-| tee data.xml」は機能しないことに注意してください。私のシステムでは、小さいファイルでも動作することがありますが、常に巨大なファイルは切り捨てられました。あなたは本当に場所で何かをしたい場合は読みbackreference.org/2011/01/29/in-place-editing-of-files
user1346466を

1
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 805: ordinal not in range(128)定義するpythonバージョンで解決するにはPYTHONIOENCODING="UTF-8"cat some.xml | PYTHONIOENCODING="UTF-8" python -c 'import sys;import xml.dom.minidom;s=sys.stdin.read();print xml.dom.minidom.parseString(s).toprettyxml()' > pretty.xml
FelikZ

1
tidyルート要素なしでxmlをフォーマットすることもできることに注意してください。これは、パイプ、xmlセクション(たとえば、ログから抽出)を介してフォーマットするのに役立ちます。echo '<x></x><y></y>' | tidy -xml -iq
Marinos

157

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

マックOS

これをMacOSにHomebrewでインストールするには、次のようにします。 brew install libxml2

ギット

コードが必要な場合は、Gitでも利用できます。 git clone git://git.gnome.org/libxml2


4
sputnickの回答にはこの情報が含まれていますが、ここではcrmpiccoの回答が、XMLをきれいに出力する方法に関する一般的な質問に対する最も有用な回答です。
Seth Difley 2014年

2
フォーマットされたxml出力を他のxmlファイルに書き出して使用できます。例:xmllint --format yourxmlfile.xml >> new-file.xml
LearnToLive

2
Ubuntuの16.04であなたは以下のように使用することができますsudo apt-get install libxml2-utils
メレ

これはWindowsでも機能します。gitWindows用のダウンロードはさえの最新バージョンをインストールしますxmllint。例:"C:\Program Files\Git\usr\bin\xmllint.exe" --format QCScaper.test@borland.com.cds.xml > QCScaper.test@borland.com.pretty-printed.cds.xml
Jeroen Wiert Pluimers '21 / 12/17

41

また、最初にインストールする必要があるtidyを使用することもできます(Ubuntuの場合はsudoなどapt-get install tidy)。

このためには、次のようなものを発行します。

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

注:多くの可読性フラグが追加されていますが、ワードラップ動作はもつれを解くのが少し面倒です(http://tidy.sourceforge.net/docs/quickref.html)。


1
xmllintで単一行のxmlファイルに改行を追加できなかったため、役に立ちました。ありがとう!
xlttj 2014年

tidy私もうまくいきます。とは異なりhxnormalize、これは実際に<body>タグを閉じます。
Sridhar Sarnobat 2014年

9
ところで、ここに私が便利だと思ったいくつかのオプションがあります:tidy --indent yes --indent-spaces 4 --indent-attributes yes --wrap-attributes yes --input-xml yes --output-xml yes < InFile.xml > OutFile.xml
Victor Yarema 2016

2
素晴らしいヒント@VictorYarema。私はそれをpygmentizeと組み合わせて.bashrcに追加しました。それから、 alias prettyxml='tidy --indent yes --indent-spaces 4 --indent-attributes yes --wrap-attributes yes --input-xml yes --output-xml yes | pygmentize -l xml' 次のことができますcurl url | prettyxml
Net Wolf

13

ファイルについて言及しなかったので、コマンドラインで標準入力としてXML文字列を提供したいと思います。その場合は、次のようにします。

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

12

macOS /ほとんどのUnixには何もインストールしません。

使用する tidy

cat filename.xml | tidy -xml -iq

catを使用してファイルの表示をリダイレクトすると、xmlのファイルタイプを整頓し、クワイエット出力中にインデントすると、エラー出力が抑制されます。JSONはでも動作し-jsonます。


1
次のcat手順は必要ありませんtidy -xml -iq filename.xml。また、オプションをtidy -xml -iq filename.xml使用して元のファイル-m変更することもできます...
janniks

10

xmllintはインプレースのフォーマットをサポートします:

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

ダニエル・ベイラードが書いたように:

xmllint -o tst.xml --format tst.xml パーサーは、出力を開いてシリアル化する前に、ツリーに入力を完全にロードするので、安全だと思います 。

インデントレベルはXMLLINT_INDENT、デフォルトで2つのスペースである環境変数によって制御されます。インデントを4つのスペースに変更する方法の例:

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

--recoverXMLドキュメントが壊れている場合、オプションが不足している可能性があります。または、厳密なXML出力を使用した弱いHTMLパーサーを試してください。

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

--nsclean--nonet--nocdata--noblanksなどが有用である可能性があります。manページを読んでください。

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

2

これは私のMacで動作する何かを見つけるのに永遠にかかりました。これが私のために働いたものです:

brew install xmlformat
cat unformatted.html | xmlformat

1
上記の私の答えはMacで動作します
jasonleonhard

1

純粋な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がすべて1行にあり、余分なスペースがどこにもないことを前提としています。これ\s*を修正するために、正規表現に簡単に追加できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.