Làm thế nào để in XML đẹp từ dòng lệnh?


528

Liên quan: Làm thế nào tôi có thể in JSON đẹp trong tập lệnh shell (unix)?

Có tập lệnh shell (unix) để định dạng XML ở dạng người có thể đọc được không?

Về cơ bản, tôi muốn nó biến đổi như sau:

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

... thành một cái gì đó như thế này:

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

1
Để có xmllintsẵn trên các hệ thống Debian, bạn cần cài đặt gói libxml2-utils( libxml2không cung cấp công cụ này, ít nhất là không có trên Debian 5.0 "Lenny" và 6.0 "Bóp").
twonkey

Câu trả lời:


909

libxml2-utils

Tiện ích này đi kèm libxml2-utils:

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

Perl của XML::Twig

Lệnh này đi kèm với XML :: Twig mô-đun, đôi khi xml-twig-toolsgói:

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

xmlstarlet

Lệnh này đi kèm xmlstarlet:

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

tidy

Kiểm tra tidygói:

echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
    tidy -xml -i -

Con trăn

Python xml.dom.minidomcó thể định dạng XML (cả python2 và 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

Bạn cần saxon-lint:

echo '<root><foo a="b">lorem</foo><bar value="ipsum" /></root>' |
    saxon-lint --indent --xpath '/' -

saxon-HE

Bạn cần 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'

Tốt, trả lời nhanh. Tùy chọn đầu tiên có vẻ như sẽ phổ biến hơn trên các bản cài đặt * nix hiện đại. Một điểm nhỏ; Nhưng nó có thể được gọi mà không làm việc thông qua một tập tin trung gian? Tức là echo '<xml .. />' | xmllint --some-read-from-stdn-option?
svidgen

Gói này nằm libxml2-utilstrong Ubuntu đẹp của tôi.
franzlorenzon

1
Lưu ý rằng "cat data.xml | xmllint --format - | tee data.xml" không hoạt động. Trên hệ thống của tôi, đôi khi nó hoạt động cho các tệp nhỏ, nhưng luôn cắt bớt các tệp lớn. Nếu bạn thực sự muốn làm bất cứ điều gì tại chỗ, hãy đọc backreference.org/2011/01/29/in-place-editing-of-files
user1346466

1
Để giải quyết UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 805: ordinal not in range(128)trong phiên bản python bạn muốn xác định 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
Lưu ý rằng gọn gàng cũng có thể định dạng xml không có phần tử gốc . Điều này rất hữu ích để định dạng thông qua một phần ống, xml (ví dụ: được trích xuất từ ​​nhật ký). echo '<x></x><y></y>' | tidy -xml -iq
Marinos An

157

xmllint --format yourxmlfile.xml

xmllint là một công cụ XML dòng lệnh và được bao gồm trong libxml2( http://xmlsoft.org/ ).

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

Lưu ý: Nếu bạn chưa libxml2cài đặt, bạn có thể cài đặt nó bằng cách làm như sau:

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

Hệ điều hành Mac

Để cài đặt cái này trên MacOS với Homebrew, chỉ cần làm: brew install libxml2

Git

Cũng có sẵn trên Git nếu bạn muốn mã: git clone git://git.gnome.org/libxml2


4
Câu trả lời của sputnick chứa thông tin này, nhưng câu trả lời của crmpicco là câu trả lời hữu ích nhất ở đây cho câu hỏi chung về cách in XML đẹp.
Seth Difley

2
chúng ta có thể viết ra đầu ra xml được định dạng vào một số tệp xml khác và sử dụng .. ví dụ: xmllint --format yourxmlfile.xml >> new-file.xml
LearnToLive

2
Trên Ubuntu 16.04, bạn có thể sử dụng như sau:sudo apt-get install libxml2-utils
Melle

Điều này cũng hoạt động trên Windows; gitcho Windows tải xuống thậm chí cài đặt một phiên bản gần đây của xmllint. Ví dụ:"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

Bạn cũng có thể sử dụng gọn gàng , có thể cần phải được cài đặt trước (ví dụ: trên Ubuntu: sudo apt-get install tidy).

Đối với điều này, bạn sẽ phát hành một cái gì đó như sau:

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

Lưu ý: có nhiều cờ dễ đọc bổ sung, nhưng hành vi ngắt từ gây khó chịu một chút để gỡ rối ( http://tidy.sourceforge.net/docs/quickref.html ).


1
Hữu ích, vì tôi không thể có xmllint để thêm ngắt dòng vào một tệp xml dòng đơn. Cảm ơn!
xlttj

tidylàm việc tốt cho tôi quá Không giống như hxnormalize, điều này thực sự đóng <body>thẻ.
Sridhar Sarnobat

9
BTW, đây là một số tùy chọn mà tôi thấy hữu ích : tidy --indent yes --indent-spaces 4 --indent-attributes yes --wrap-attributes yes --input-xml yes --output-xml yes < InFile.xml > OutFile.xml.
Victor Yarema

2
Mẹo tuyệt vời @VictorYarema. Tôi đã kết hợp nó với pyributionize và thêm nó vào .bashrc: alias prettyxml='tidy --indent yes --indent-spaces 4 --indent-attributes yes --wrap-attributes yes --input-xml yes --output-xml yes | pygmentize -l xml' và sau đó có thểcurl url | prettyxml
Net Wolf

13

Bạn đã không đề cập đến một tệp, vì vậy tôi giả sử bạn muốn cung cấp chuỗi XML làm đầu vào tiêu chuẩn trên dòng lệnh. Trong trường hợp đó, hãy làm như sau:

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

12

Không cần cài đặt bất cứ thứ gì trên macOS / hầu hết Unix.

Sử dụng tidy

cat filename.xml | tidy -xml -iq

Chuyển hướng xem tệp với mèo để gọn gàng chỉ định loại tệp của xml và thụt lề trong khi đầu ra yên tĩnh sẽ chặn đầu ra lỗi. JSON cũng hoạt động với -json.


1
Bạn không cần catbước : tidy -xml -iq filename.xml. Ngoài ra, bạn thậm chí có thể tidy -xml -iq filename.xmlsử dụng -mtùy chọn để sửa đổi tệp gốc ...
janniks

10

xmllint hỗ trợ định dạng tại chỗ :

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

Như Daniel Veillard đã viết:

Tôi nghĩ xmllint -o tst.xml --format tst.xml nên an toàn vì trình phân tích cú pháp sẽ tải đầy đủ đầu vào vào một cây trước khi mở đầu ra để tuần tự hóa nó.

Mức thụt lề được điều khiển bởi XMLLINT_INDENTbiến môi trường theo mặc định là 2 khoảng trắng. Ví dụ cách thay đổi thụt lề thành 4 khoảng trắng:

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

Bạn có thể thiếu --recovertùy chọn khi tài liệu XML của bạn bị hỏng. Hoặc thử trình phân tích cú pháp HTML yếu với đầu ra XML nghiêm ngặt:

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

--nsclean, --nonet, --nocdata, --noblanksVv có thể hữu ích. Đọc trang người đàn ông.

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

2

Điều này khiến tôi mãi mãi phải tìm thứ gì đó hoạt động trên máy mac của mình. Đây là những gì làm việc cho tôi:

brew install xmlformat
cat unformatted.html | xmlformat

1
Câu trả lời của tôi ở trên hoạt động trên mac
jasonleonhard

1

Tôi muốn thêm một giải pháp Bash thuần túy, vì không khó để làm điều đó bằng tay và đôi khi bạn sẽ không muốn cài đặt một công cụ bổ sung để thực hiện công việc.

#!/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

Dán nó vào một tập tin kịch bản và ống trong xml. Điều này giả sử xml là tất cả trên một dòng và không có thêm khoảng trắng ở bất cứ đâu. Người ta có thể dễ dàng thêm một số bổ sung \s*vào regexes để khắc phục điều đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.