Як красиво роздрукувати XML з командного рядка?


528

Пов'язане: Як я можу симпатично роздрукувати JSON у (unix) оболонці сценарію?

Чи існує сценарій оболонки (unix) для форматування XML у читаному для людини вигляді?

В основному, я хочу, щоб вона перетворила наступне:

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

... у щось подібне:

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

1
Щоб мати xmllintдоступ у системах Debian, вам потрібно встановити пакет libxml2-utils( libxml2не надається цей інструмент, принаймні не на Debian 5.0 "Lenny" та 6.0 "Squeeze").
twonkeys

Відповіді:


909

libxml2-utils

Ця утиліта постачається із libxml2-utils:

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

Перл 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

Пакет libxml2-utilsу моїй прекрасній ubuntu.
franzlorenzon

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
Зауважте, що охайний також може форматувати xml без кореневого елемента . Це корисно для форматування через трубу, розділи xml (наприклад, витягнуті з журналів). echo '<x></x><y></y>' | tidy -xml -iq
Марінос

157

xmllint --format yourxmlfile.xml

xmllint - це інструмент XML командного рядка і входить до нього libxml2( http://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

Сігвін

apt-cyg install libxml2

MacOS

Щоб встановити це на MacOS за допомогою Homebrew, просто виконайте такі дії: brew install libxml2

Git

Також доступний на Git, якщо ви хочете код: git clone git://git.gnome.org/libxml2


4
Відповідь sputnick містить цю інформацію, але відповідь crmpicco є найбільш корисною відповіддю на загальне питання про те, як красиво друкувати XML.
Сет Діфлі

2
ми можемо виписати, що відформатований xml виводиться на якийсь інший XML-файл, і використовувати його .. напр. xmllint --форматувати yourxmlfile.xml >> new-file.xml
LearnToLive

2
У Ubuntu 16.04 ви можете скористатись наступним:sudo apt-get install libxml2-utils
Melle

Це працює і в Windows; gitдля завантаження Windows навіть встановлюється остання версія 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

41

Ви також можете використовувати акуратно , який, можливо, потрібно буде встановити спочатку (наприклад, на 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

tidyдобре працює і для мене. На відміну від hxnormalizeцього зроблене фактично закриває <body>тег.
Шрідхар Сарнобат

9
До речі, ось кілька варіантів , які я знайшов корисним: tidy --indent yes --indent-spaces 4 --indent-attributes yes --wrap-attributes yes --input-xml yes --output-xml yes < InFile.xml > OutFile.xml.
Віктор Ярема

2
Чудова порада @VictorYarema. Я поєднав його з пігментізмом і додав його до мого .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
Чистий Вовк

13

Ви не згадали про файл, тому я вважаю, що ви хочете надати рядок XML як стандартний вхід у командному рядку. У цьому випадку виконайте наступне:

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

12

Не встановлюючи нічого на macOS / most Unix.

Використовуйте tidy

cat filename.xml | tidy -xml -iq

Перенаправлення перегляду файлу з котом на охайне вказівку типу файлу 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

Можливо, вам не вистачає --recoverопції, коли ваші XML документи зламані. Або спробуйте слабкий HTML-аналізатор зі строгим виведенням XML:

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

--nsclean, --nonet, --nocdata, І --noblanksт.д. , може бути корисним. Прочитати сторінку чоловіка.

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 знаходиться в одному рядку, і зайвих пробілів ніде немає. Можна було б легко додати щось додаткове \s*до регулярних виразів, щоб виправити це.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.