سؤال

أستخدم emacs لتحرير ملفات xml الخاصة بي (وضع nxml) والملفات التي تم إنشاؤها بواسطة الجهاز لا تحتوي على أي تنسيق جميل للعلامات.

لقد بحثت عن طريقة جميلة لطباعة الملف بأكمله مع وضع مسافة بادئة وحفظه، لكن لم أتمكن من العثور على طريقة تلقائية.

هل هناك طريقة؟أو على الأقل بعض المحررين على نظام Linux الذي يمكنه القيام بذلك.

هل كانت مفيدة؟

المحلول

أنا أستعمل وضع نكسمل للتحرير و مرتب عندما أرغب في تنسيق XML أو HTML ووضع مسافة بادئة له.يوجد ايضا واجهة Emacs لـ Tidy.

نصائح أخرى

لا تحتاج حتى إلى كتابة وظيفتك الخاصة - يحتوي sgml-mode (وحدة أساسية لـ gnu emacs) على وظيفة طباعة جميلة مدمجة تسمى (sgml-pretty-print ...) والتي تأخذ وسيطات البداية والنهاية للمنطقة.

إذا كنت تقوم بقص ولصق ملف XML وتجد أن جهازك الطرفي يقوم بتقطيع الخطوط في أماكن عشوائية، فيمكنك استخدام هذا طابعة جميلة الذي يعمل على إصلاح الخطوط المكسورة أولاً.

إذا كنت تحتاج فقط إلى مسافة بادئة جيدة دون إدخال أي فواصل أسطر جديدة، فيمكنك تطبيق indent-region الأمر إلى المخزن المؤقت بأكمله باستخدام ضغطات المفاتيح هذه:

C-x h
C-M-\

إذا كنت بحاجة أيضًا إلى تقديم فواصل الأسطر، بحيث تكون علامات الفتح والإغلاق في أسطر منفصلة، ​​فيمكنك استخدام وظيفة 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"))
      (indent-region begin end))
    (message "Ah, much better!"))

وهذا لا يعتمد على أداة خارجية مثل Tidy.

يمكن لـ Emacs تشغيل أوامر عشوائية باستخدام M-|.إذا قمت بتثبيت xmllint:

"M-| xmllint --format -" سيقوم بتنسيق المنطقة المحددة

"C-u M-| xmllint --format -" سيفعل الشيء نفسه، مع استبدال المنطقة بالمخرجات

بفضل تيم هيلمستيدت أعلاه، قمت بعمل مثل هذا:

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

بسرعة وسهولة.تشكرات.

لإدخال فواصل الأسطر ومن ثم الطباعة الجميلة

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

إليك بعض التعديلات التي أجريتها على نسخة بنيامين فيراري:

  • ال 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!"))

طريقة واحدة للقيام بها هي إذا كان لديك شيء في الشكل أدناه

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

في إيماكس، حاول

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=

أتمنى أن يساعدك هذا.

  1. يمكن أن يعمل وضع Emacs nxml على التنسيق المقدم، ولكن سيتعين عليك تقسيم الخطوط.
  2. بالنسبة للملفات الأطول التي لا تستحق العناء.قم بتشغيل ورقة الأنماط هذه (من الناحية المثالية مع Saxon التي تحصل عليها IMHO عن المسافات البادئة حول اليمين) مقابل ملفات أطول للحصول على طباعة جميلة جميلة.لأي عناصر تريد الاحتفاظ بالمساحة البيضاء ، أضف أسمائها إلى جانب "قائمة البرامج" كما هو الحال في "قائمة البرنامج"

هث

أخذت نسخة جيسون فيرس وأضاف منطقًا لوضع إعلانات 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!"))

مرتب يبدو وكأنه وضع جيد.يجب أن ننظر إليها.سأستخدمه إذا كنت حقًا بحاجة إلى جميع الميزات التي يقدمها.

على أية حال، هذه المشكلة كانت تزعجني لمدة أسبوع تقريبا ولم أكن أبحث بشكل صحيح.بعد النشر، بدأت البحث ووجدت موقعًا واحدًا به عنوان وظيفة إليسب الذي يفعل ذلك بشكل جيد.يقترح المؤلف أيضًا استخدام Tidy.

شكرا للإجابة مارسيل (من المؤسف أنه ليس لدي ما يكفي من النقاط لتحديثك).

سوف انشر عنها قريبا على مدونتي هنا أ نشر حول هذا الموضوع (مع رابط لموقع مارسيل).

أنا أستعمل xml-reformat-tags من xml-parse.el.عادةً ما تريد أن تكون النقطة في بداية الملف عند تشغيل هذا الأمر.

ومن المثير للاهتمام أن الملف مدمج في ايماكسبيك.عندما كنت أستخدم Emacspeak على أساس يومي، فكرت xml-reformat-tags هو مدمج إيماكس.وفي أحد الأيام فقدته واضطررت إلى إجراء بحث على الإنترنت عن ذلك، وبالتالي دخلت إلى صفحة الويكي المذكورة أعلاه.

أقوم أيضًا بإرفاق الكود الخاص بي لبدء تحليل XML.لست متأكدًا مما إذا كان هذا هو أفضل جزء من كود 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))
)

إذا كنت تستخدم com.spacemacs, ، ما عليك سوى استخدام الأمر "spacemacs/indent-region-or-buffer".

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

أخشى أنني أحب نسخة بنيامين فيراري أفضل بكثير.تضع الطباعة الجميلة الداخلية دائمًا علامة النهاية في سطر جديد بعد القيمة، مما يؤدي إلى إدراج CR غير المرغوب فيه في قيم العلامة.

اعتبارًا من عام 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/

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top