Emacs에서 XML 파일 인쇄하기


84

emacs를 사용하여 내 xml 파일 (nxml-mode)을 편집하고 컴퓨터에서 생성 된 파일에는 태그의 형식이 예쁘지 않습니다.

들여 쓰기로 전체 파일을 인쇄하고 저장하는 방법을 검색했지만 자동 방법을 찾을 수 없었습니다.

방법이 있습니까? 또는 그것을 할 수있는 리눅스에서 적어도 일부 편집기.

답변:


25

편집 에는 nXML 모드 를 사용 하고 XML 또는 HTML의 서식을 지정하고 들여 쓰고 싶을 때는 Tidy 를 사용합니다. Tidy에 대한 Emacs 인터페이스 도 있습니다 .


2013 년 말까지 tidy.el 버전 : 20111222.1756은 Emacs 24에서 실행되지 않습니다wrong type argument: stringp, nil
keiw

@keiw 아마도 파일 이름이없는 버퍼에서 수행하고 있기 때문일 것입니다. 같은 오류가 발생하여 적어도 내 쪽에서 추적했습니다.
Alf

108

sgml-mode (gnu emacs 코어 모듈)에는 영역 시작 및 끝 인수를받는 (sgml-pretty-print ...)라는 예쁜 인쇄 기능이 내장되어 있습니다.

xml을 자르고 붙여넣고 터미널이 임의의 위치에서 줄을 자르는 것을 발견하면 먼저 끊어진 줄을 수정 하는이 예쁜 프린터 를 사용할 수 있습니다 .


1
(sgml-pretty-print (region-beginning) (region-end))
ScootyPuff 2011 년

7
sgml-mode시간이 지남에 따라 어떻게 바뀌 었는지 잘 모르겠습니다 . 오늘은 호출 C-x C-f foo.xml, M-x sgml-mode다음, M-x sgml-pretty-print나의 XML 파일은 꽤 인쇄되었다. (. 음 이십 초 이상 교수형 이맥스 완료하기 전에이 후 한 줄의 예쁜 인쇄하기 전에 파일 720 줄을이었다.)
daveloyall

1
사실, C-x g전체 버퍼를 영역으로 선택 해야 했습니다.
daveloyall

3
sgml 모드로 전환 할 필요조차 없었습니다. nXML 모드의 Mx 명령이었습니다!
nroose

1
Emacs 26.2를 사용하여 nXML 모드를 유지하고 전체 버퍼 C-x h를 선택한 다음 M-x sgml-pretty-print. XML은 이제 꽤 형식화 될 것입니다
Swedgin

87

새로운 줄 바꿈없이 들여 쓰기 만 필요한 경우 indent-region다음 키 입력으로 전체 버퍼에 명령을 적용 할 수 있습니다 .

C-x h
C-M-\

또한 여는 태그와 닫는 태그가 별도의 줄에 있도록 줄 바꿈을 도입해야하는 경우 Benjamin Ferrari가 작성한 다음과 같은 매우 멋진 elisp 함수를 사용할 수 있습니다 . 나는 그의 블로그에서 그것을 찾았고 여기에서 그것을 재현해도 좋기를 바랍니다.

(defun bf-pretty-print-xml-region (begin end)
  "Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this.  The function inserts linebreaks to separate tags that have
nothing but whitespace between them.  It then indents the markup
by using nxml's indentation rules."
  (interactive "r")
  (save-excursion
    (nxml-mode)
    (goto-char begin)
    (while (search-forward-regexp "\>[ \\t]*\<" nil t) 
      (backward-char) (insert "\n") (setq end (1+ end)))
    (indent-region begin end))
  (message "Ah, much better!"))

이것은 Tidy와 같은 외부 도구에 의존하지 않습니다.


1
고마워요. 위의 pretty-print defun에서 (nxml-mode)를 제거하면 emacs 22.2.1에 내장 된 sgml-mode에서 작동 할 수 있습니다. 하지만 전체 버퍼 (point-min)를 (point-max)로 변경하도록 수정했습니다. 또한 하나의 버그 : 삽입하는 각 줄 바꿈에 대해 끝을 증가시켜야합니다.
Cheeso

Emacs에서이 기능을 어떻게 사용할 수 있습니까? 스크래치 버퍼에 함수 코드를 복사하여 붙여넣고 평가했습니다. 이제이 함수를 어떻게 호출합니까?
Alexandre Rademaker

1
defun을 평가 한 후 Mx bf-pretty-print-xml-region과 같은 다른 함수처럼 호출 할 수 있습니다. (물론 모두 입력 할 필요는 없습니다. 탭 완성 기능을 사용하십시오. Mx bf <tab>이면 충분합니다.) 사용하고 싶을 때마다 함수를 정의하고 싶지는 않을 것이므로 어딘가에 두십시오. 시작 시간에로드됩니다. 예 : ~ / .emacs.d / init.el
Christian Berg

1
긴 속성 목록을 깨는 것은 어떻습니까?
ceving

tidy가 잘못된 문자 인코딩에 대해 불평 하고 파일을 다시 포맷 하기 전에 정리하기를 원 하기 때문에 이것은 훌륭합니다! 때때로 요점은 깨진 xml 파일의 구조를 보는 것이고 깔끔한 것은 도움을 거부 할 것입니다.
TauPan

35

Emacs는 M- |로 임의의 명령을 실행할 수 있습니다. xmllint가 설치된 경우 :

"M- | xmllint --format-"은 선택한 영역의 형식을 지정합니다.

"Cu M- | xmllint --format-"은 동일한 작업을 수행하여 영역을 출력으로 바꿉니다.


Mx mark-whole-buffer를 앞에 사용하여 전체 버퍼 콘텐츠를 처리 할 영역으로 표시합니다.
Harald

19

위의 Tim Helmstedt 덕분에 다음과 같이 st를 만들었습니다.

(defun nxml-pretty-format ()
    (interactive)
    (save-excursion
        (shell-command-on-region (point-min) (point-max) "xmllint --format -" (buffer-name) t)
        (nxml-mode)
        (indent-region begin end)))

빠르고 쉽습니다. 감사합니다.


2
: I가 마지막 줄을 변경 이렇게하면, GNU 이맥스 24 일에 나에게 오류를 준(indent-region 0 (count-lines (point-min) (point-max)))
존 J. 카밀레

19

줄 바꿈 도입 후 예쁜 인쇄

M-x sgml-mode
M-x sgml-pretty-print

8

Benjamin Ferrari의 버전에 대한 몇 가지 변경 사항은 다음과 같습니다.

  • (가) search-forward-regexp는 버퍼의 끝 부분의 시작에서 물건에서 작동 할 수 있도록, 끝을 지정하지 않았다 (대신 지역의 말)
  • 이제 endCheeso가 언급했듯이 제대로 증가 합니다.
  • 사이에 브레이크를 삽입하여 <tag></tag>값을 수정합니다. 예, 기술적으로 여기에서 모든 값을 수정하고 있지만 빈 시작 / 끝이 훨씬 더 중요합니다. 이제이를 방지하기 위해 약간 더 엄격한 두 개의 개별 검색을 사용합니다.

여전히 "외부 정리에 의존하지 않음"등이 있습니다. 그러나 매크로 가 필요 cl합니다 incf.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; pretty print xml region
(defun pretty-print-xml-region (begin end)
  "Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this.  The function inserts linebreaks to separate tags that have
nothing but whitespace between them.  It then indents the markup
by using nxml's indentation rules."
  (interactive "r")
  (save-excursion
    (nxml-mode)
    (goto-char begin)
    ;; split <foo><foo> or </foo><foo>, but not <foo></foo>
    (while (search-forward-regexp ">[ \t]*<[^/]" end t)
      (backward-char 2) (insert "\n") (incf end))
    ;; split <foo/></foo> and </foo></foo>
    (goto-char begin)
    (while (search-forward-regexp "<.*?/.*?>[ \t]*<" end t)
      (backward-char) (insert "\n") (incf end))
    (indent-region begin end nil)
    (normal-mode))
  (message "All indented!"))

5

한 가지 방법은 아래 형식의 것이 있으면

<abc>     <abc><abc>   <abc></abc> </abc></abc>       </abc>

Emacs에서

M-x nxml-mode
M-x replace-regexp RET  > *< RET >C-q C-j< RET 
C-M-\ to indent

위의 xml 예제를 아래로 들여 씁니다.

<abc>
  <abc>
    <abc>
      <abc>
      </abc>
    </abc>
  </abc>
</abc>

VIM에서는 다음과 같이 할 수 있습니다.

:set ft=xml
:%s/>\s*</>\r</g
ggVG=

도움이 되었기를 바랍니다.


2
  1. Emacs nxml-mode는 제시된 형식에서 작동 할 수 있지만 행을 분할해야합니다.
  2. 단순히 가치가없는 더 긴 파일의 경우. 더 긴 파일에 대해이 스타일 시트 (이상적으로는 IMHO가 줄 들여 쓰기를하는 Saxon와 함께)를 실행하여 멋지고 예쁜 인쇄물을 얻으십시오. 공백을 유지하려는 요소의 경우 'programlisting yourElementName'에서와 같이 'programlisting'과 함께 이름을 추가하십시오.

HTH


2

나는했다 제이슨 Viers '버전 자신의 라인에서의 xmlns 선언을 넣어 및 로직을 추가. 여기에서는 공백없이 xmlns = 및 xmlns :가 있다고 가정합니다.

(defun cheeso-pretty-print-xml-region (begin end)
  "Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this.  The function inserts linebreaks to separate tags that have
nothing but whitespace between them.  It then indents the markup
by using nxml's indentation rules."
  (interactive "r")
  (save-excursion
    (nxml-mode)
    ;; split <foo><bar> or </foo><bar>, but not <foo></foo>
    (goto-char begin)
    (while (search-forward-regexp ">[ \t]*<[^/]" end t)
      (backward-char 2) (insert "\n") (incf end))
    ;; split <foo/></foo> and </foo></foo>
    (goto-char begin)
    (while (search-forward-regexp "<.*?/.*?>[ \t]*<" end t)
      (backward-char) (insert "\n") (incf end))
    ;; put xml namespace decls on newline
    (goto-char begin)
    (while (search-forward-regexp "\\(<\\([a-zA-Z][-:A-Za-z0-9]*\\)\\|['\"]\\) \\(xmlns[=:]\\)" end t)
      (goto-char (match-end 0))
      (backward-char 6) (insert "\n") (incf end))
    (indent-region begin end nil)
    (normal-mode))
  (message "All indented!"))

1

깔끔한 모드가 좋은 것 같습니다. 그것을 봐야합니다. 제공하는 모든 기능이 정말로 필요한 경우 사용할 것입니다.

어쨌든,이 문제는 약 1 주일 동안 저를 괴롭 혔고 제대로 검색하지 못했습니다. 게시물을 올린 후 검색을 시작 하고 꽤 잘하는 elisp 기능이 있는 사이트를 찾았 습니다. 저자는 또한 Tidy를 사용할 것을 제안합니다.

대답 Marcel에 감사드립니다 (너무 나빠서 upmod 할 포인트가 충분하지 않습니다) .

내 블로그에 곧 게시 할 예정입니다. 여기에 대한 게시물이 있습니다 (Marcel 사이트 링크 포함).


1

xml-parse.elxml-reformat-tags 에서 사용 합니다. 일반적으로이 명령을 실행할 때 파일 시작 부분에 위치를 지정하려고합니다.

파일이 Emacspeak에 통합되어 있다는 것이 흥미 롭습니다 . Emacspeak를 매일 사용했을 때 xml-reformat-tagsEmacs가 내장되어 있다고 생각했습니다 . 어느 날 나는 그것을 잃어 버리고 그것을 위해 인터넷 검색을해야했고, 따라서 위에서 언급 한 위키 페이지에 들어갔다.

xml-parse를 시작하는 코드도 첨부하고 있습니다. 이것이 Emacs 코드의 가장 좋은 부분인지 확실하지 않지만 나를 위해 작동하는 것 같습니다.

(if (file-exists-p "~/.emacs.d/packages/xml-parse.el")
  (let ((load-path load-path))
    (add-to-list 'load-path "~/.emacs.d/packages")
    (require 'xml-parse))
)

1

spacemacs 를 사용하는 경우 'spacemacs / indent-region-or-buffer'명령을 사용하십시오.

M-x spacemacs/indent-region-or-buffer

1

2017 년부터 emacs에는 이미이 기능이 기본으로 제공되지만이 작은 함수를 다음과 ~/.emacs.d/init.el같이 작성해야합니다 .

(require 'sgml-mode)

(defun reformat-xml ()
  (interactive)
  (save-excursion
    (sgml-pretty-print (point-min) (point-max))
    (indent-region (point-min) (point-max))))

그럼 그냥 전화 해 M-x reformat-xml

출처 : https://davidcapello.com/blog/emacs/reformat-xml-on-emacs/


0

Benjamin Ferrari 버전이 훨씬 더 마음에 들어요. 내부 pretty print는 항상 값 뒤에 새 줄에 끝 태그를 배치하여 태그 값에 원하지 않는 CR을 삽입합니다.

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