Emacs पर सुंदर मुद्रण XML फ़ाइलें


84

मैं अपनी xml फ़ाइलों (nxml- मोड) को संपादित करने के लिए emacs का उपयोग करता हूं और मशीन द्वारा उत्पन्न की गई फ़ाइलों में टैग का कोई भी सुंदर प्रारूपण नहीं है।

मैंने पूरी फ़ाइल को इंडेंटेशन के साथ प्रिंट करने और उसे सहेजने के लिए बहुत खोजा है, लेकिन एक स्वचालित तरीका खोजने में सक्षम नहीं था।

क्या उधर रास्ता है? या लिनक्स पर कुछ संपादक को कम से कम जो यह कर सकता है।

जवाबों:


25

जब मैं फॉर्मेट और इंडेंट एक्सएमएल या एचटीएमएल करना चाहता हूं, तो मैं संपादन और सुव्यवस्थित करने के लिए nXML मोड का उपयोग करता हूंTidy के लिए एक Emacs इंटरफ़ेस भी है


2013 के अंत तक tidy.el संस्करण: 20111222.1756 Emacs 24 के साथ चलने में विफल रहता हैwrong type argument: stringp, nil
keew

@keiw यह शायद इसलिए है क्योंकि आप इसे एक बफर में कर रहे हैं जिसमें फ़ाइल नाम नहीं है। एक ही त्रुटि है और यह कम से कम मेरी तरफ से पता लगाया है।
अल्फ

108

आपको अपना स्वयं का फ़ंक्शन लिखने की भी आवश्यकता नहीं है - sgml-mode (एक gnu emacs कोर मॉड्यूल) में एक अंतर्निहित सुंदर प्रिंटिंग फ़ंक्शन होता है जिसे (sgml-pretty-print ...) कहा जाता है जो क्षेत्र की शुरुआत और समाप्ति तर्क लेता है।

यदि आप xml को काट और चिपका रहे हैं और आप पाते हैं कि आपका टर्मिनल मनमाने स्थानों पर लाइनों को काट रहा है तो आप इस सुंदर प्रिंटर का उपयोग कर सकते हैं जो पहले टूटी लाइनों को ठीक करता है।


1
(sgml-pretty-print (क्षेत्र-शुरुआत) (रीजन-एंड)
ScootyPuff

7
मुझे यकीन नहीं है कि sgml-modeसमय के साथ कैसे बदल सकता है। आज, मैंने आह्वान किया C-x C-f foo.xml, M-x sgml-modeफिर, M-x sgml-pretty-printऔर मेरी xml फ़ाइल बहुत सुंदर छपी। (ठीक है, Emacs को पूरा करने से पहले बीस सेकंड या उससे अधिक समय के लिए लटकाया जाता है। यह सुंदर प्रिंट से पहले एक लाइन की फाइल थी और 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-\

यदि आपको भी लाइन-ब्रेक शुरू करने की आवश्यकता है, ताकि खुलने और बंद होने वाले टैग अलग-अलग लाइनों पर हों, तो आप बेंजामिन फेरारी द्वारा लिखित निम्न बहुत अच्छे क्विक फ़ंक्शन का उपयोग कर सकते हैं । मैंने इसे अपने ब्लॉग पर पाया और आशा है कि मेरे लिए इसे फिर से प्रस्तुत करना ठीक है:

(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!"))

यह साफ जैसे बाहरी उपकरण पर निर्भर नहीं करता है।


1
अच्छा डिफ्यूज, धन्यवाद। उपरोक्त सुंदर-प्रिंट डिफॉन से (nxml- मोड) को हटाने से यह 22.2.1 emacs में निर्मित sgml- मोड में काम करने की अनुमति देता है। लेकिन मैंने इसे पूरे बफ़र (बिंदु-मिनट) से (बिंदु-अधिकतम) करने के लिए संशोधित किया क्योंकि यह मेरी मुख्य बात है। इसके अलावा, एक बग: आपके द्वारा डाली गई प्रत्येक नई पंक्ति के लिए, आपको वेतन वृद्धि की आवश्यकता होगी।
Cheeso

मैं Emacs में इस फ़ंक्शन का उपयोग कैसे कर सकता हूं? मैंने स्क्रैच बफर में फ़ंक्शन कोड को कॉपी और पेस्ट किया है और इसका मूल्यांकन किया है। अब, मैं इस फ़ंक्शन को कैसे लागू करूं?
अलेक्जेंड्रे रेडमेकर

1
डिफॉन का मूल्यांकन करने के बाद, आप इसे किसी अन्य फ़ंक्शन की तरह इनवोक कर सकते हैं: एमएक्स बीएफ-सुंदर-प्रिंट-एक्सएमएल-क्षेत्र। (आपको यह सब टाइप करने की ज़रूरत नहीं है, निश्चित रूप से, टैब समापन का उपयोग करें: Mx bf <टैब> पर्याप्त होना चाहिए।) आप हर बार जब आप इसे उपयोग करना चाहते हैं, तो फ़ंक्शन को परिभाषित नहीं करना चाहते हैं, इसलिए इसे कहीं पर रख दें। जहां इसे स्टार्ट-टाइम पर लोड किया जाता है, उदाहरण के लिए ~ / .emacs.d / init.el
क्रिश्चियन बर्ग

1
लंबी विशेषता सूचियों को तोड़ने के बारे में कैसे?
सीवन

यह शानदार है, क्योंकि साफ-सुथरे चरित्र अतिक्रमण के बारे में शिकायत करते हैं और चाहते हैं कि मैं फ़ाइल को सुधारने से पहले उन्हें साफ कर दूं ! कभी-कभी बिंदु एक टूटी हुई xml फ़ाइल की संरचना को देखने के लिए है और साफ मदद करने से इनकार कर देगा।
ताउपन

35

एमएसी के साथ एमएसीएस मनमानी कमांड चला सकते हैं। यदि आपके पास xmllint स्थापित है:

"M- | xmllint --format -" चयनित क्षेत्र को प्रारूपित करेगा

"Cu M- | xmllint --format -" वही करेगा, जो आउटपुट के साथ क्षेत्र को बदल रहा है


प्रक्रिया के लिए क्षेत्र के रूप में संपूर्ण बफर सामग्री को चिह्नित करने के लिए एमएक्स मार्क-संपूर्ण-बफर का उपयोग करें।
हेराल्ड

19

टिम हेल्मेड्ट के ऊपर धन्यवाद, मैंने सेंट को इस तरह बनाया:

(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
इसने मुझे GNU Emacs 24 पर एक त्रुटि दी, इसलिए मैंने अंतिम पंक्ति बदल दी:(indent-region 0 (count-lines (point-min) (point-max)))
John J. Camilleri

19

लाइन ब्रेक और फिर सुंदर छपाई शुरू करने के लिए

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

8

यहाँ मैं बेंजामिन फेरारी के संस्करण के लिए किए गए कुछ ट्विक्स:

  • search-forward-regexpतो यह बफर के समाप्त करने के लिए इस क्षेत्र की शुरुआत से सामान पर काम होता है, एक अंत निर्दिष्ट नहीं किया है (बजाय क्षेत्र के अंत की)
  • अब वेतन वृद्धि end ठीक से , जैसा कि चीज़ो ने उल्लेख किया है।
  • इसके बीच एक विराम डालना होगा <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- मोड प्रस्तुत प्रारूप पर काम कर सकता है, लेकिन आपको लाइनों को विभाजित करना होगा।
  2. लंबे समय तक फाइल के लिए जो इसके लायक नहीं है। इस स्टाइलशीट को चलाएं (आदर्श रूप से सेक्सन के साथ जिसे IMHO को एक सुंदर सुंदर प्रिंट प्राप्त करने के लिए लंबी फ़ाइलों के खिलाफ लाइन इंडेंट मिलता है)। ऐसे किसी भी तत्व के लिए जहाँ आप सफ़ेद स्थान को बनाए रखना चाहते हैं, उनके नाम को 'प्रोग्रामलिस्टिंग' के साथ जोड़ दें, जैसे कि 'आपके प्रोग्रामर को प्रोग्राम करना'

HTH


2

मैंने जेसन वियर्स का संस्करण लिया और अपनी तर्ज पर 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

मैं xml-parse.elxml-reformat-tags से उपयोग करता हूं । आमतौर पर आप इस कमांड को चलाने के दौरान फ़ाइल के आरंभ में बिंदु रखना चाहेंगे।

यह दिलचस्प है कि फ़ाइल Emacspeak में शामिल है । जब मैं दिन-ब-दिन Emacspeak का उपयोग कर रहा था, मुझे लगा कि xml-reformat-tagsयह एक Emacs buildin है। एक दिन मैंने इसे खो दिया और इसके लिए एक इंटरनेट सर्च करना पड़ा, और इस तरह ऊपर उल्लेखित विकी पेज में प्रवेश किया।

मैं 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

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

मुझे डर है कि मैं बेंजामिन फेरारी संस्करण को बेहतर तरीके से पसंद करता हूं। आंतरिक सुंदर प्रिंट हमेशा मूल्य के बाद अंतिम टैग को टैग मानों में अवांछित सीआर सम्मिलित करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.