커맨드 라인에서 XML을 예쁘게 인쇄하는 방법은 무엇입니까?


528

관련 : 어떻게 (유닉스) 쉘 스크립트에서 JSON을 꽤 - 인쇄 할 수 있습니까?

사람이 읽을 수있는 형식으로 XML을 형식화하는 (유닉스) 셸 스크립트가 있습니까?

기본적으로 다음을 변형하고 싶습니다.

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

...이 같은 것으로 :

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

1
이려면 xmllint데비안 시스템에서 사용할 수, 당신은 패키지를 설치해야합니다 libxml2-utils( libxml2적어도하지 데비안 5.0 "레니"및 6.0 "짜기"에이 도구를 제공하지 않습니다).
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 -

파이썬

파이썬 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아름다운 우분투에 있습니다.
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)파이썬 버전에서 해결하려면 다음과 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
Marinos An

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

우분투

sudo apt-get install libxml2-utils

사이 그윈

apt-cyg install libxml2

맥 OS

Homebrew와 함께 MacOS에 이것을 설치하려면 다음을 수행하십시오. brew install libxml2

힘내

코드를 원한다면 Git에서도 사용 가능합니다 : git clone git://git.gnome.org/libxml2


4
sputnick의 답변에는 이러한 정보가 포함되어 있지만 crmpicco의 답변은 XML을 예쁘게 인쇄하는 방법에 대한 일반적인 질문에 대한 가장 유용한 답변입니다.
세스 디 플리

2
우리는 밖으로 쓸 수 다른 XML 파일을 사용하는 것이 .. 예를 들어 xmllint가 --format yourxmlfile.xml >> 새로운 file.xml에 XML 형식 출력
LearnToLive

2
Ubuntu 16.04에서는 다음을 사용할 수 있습니다.sudo apt-get install libxml2-utils
Melle

이것은 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

41

당신은 또한 사용할 수 있습니다 정돈 (: 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>태그를 닫습니다 .
Sridhar Sarnobat '11

9
BTW, 여기 내가 찾은 유용한 옵션이 있습니다 : 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
좋은 팁 @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

Daniel Veillard가 다음과 같이 썼습니다 :

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등이 유용 할 수 있습니다. 매뉴얼 페이지를 읽으십시오.

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*그것을 고치기 위해 정규 표현식에 여분의 것을 쉽게 추가 할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.