Function: nxml-mode

nxml-mode is an autoloaded, interactive and byte-compiled function defined in nxml-mode.el.gz.

Signature

(nxml-mode)

Documentation

Major mode for editing XML.

C-c / (nxml-finish-element) finishes the current element by inserting an end-tag.

C-c C-i closes a start-tag with > and then inserts a balancing end-tag leaving point between the start-tag and end-tag. C-c C-b (nxml-balanced-close-start-tag-block) is similar but for block rather than inline elements: the start-tag, point, and end-tag are all left on separate lines. If nxml-slash-auto-complete-flag is non-nil, then inserting a </ automatically inserts the rest of the end-tag.

C-M-i (completion-at-point) performs completion on the symbol preceding point.

C-c C-d (nxml-dynamic-markup-word) uses the contents of the current buffer to choose a tag to put around the word preceding point.

Sections of the document can be displayed in outline form. The variable nxml-section-element-name-regexp controls when an element is recognized as a section. The same key sequences that change visibility in outline mode are used except that they start with C-c C-o instead of C-c.

Validation is provided by the related minor-mode rng-validate-mode(var)/rng-validate-mode(fun). This also makes completion schema- and context- sensitive. Element names, attribute names, attribute values and namespace URIs can all be completed. By default, rng-validate-mode(var)/rng-validate-mode(fun) is automatically enabled. You can toggle it using M-x rng-validate-mode (rng-validate-mode) or change the default by customizing rng-nxml-auto-validate-flag.

TAB (indent-for-tab-command) indents the current line appropriately. This can be customized using the variable nxml-child-indent and the variable nxml-attribute-indent.

C-c C-u (nxml-insert-named-char) inserts a character reference using the character's name (by default, the Unicode name). C-u (universal-argument) C-c C-u (nxml-insert-named-char) inserts the character directly.

The Emacs commands that normally operate on balanced expressions will operate on XML markup items. Thus C-M-f (forward-sexp) will move forward across one markup item; C-M-b (backward-sexp) will move backward across one markup item; C-M-k (kill-sexp) will kill the following markup item; C-M-@ (mark-sexp) will mark the following markup item. By default, the complete element is treated as a single markup item; to make each tag be treated as a separate markup item, set the variable nxml-sexp-element-flag to nil. For more details, see the function nxml-forward-balanced-item.

C-M-u (nxml-backward-up-element) and C-M-d (nxml-down-element) move up and down the element structure.

Many aspects this mode can be customized using M-x customize-group (customize-group) nxml RET.

In addition to any hooks its parent mode text-mode might have run, this mode runs the hook nxml-mode-hook, as the final or penultimate step during initialization.

View in manual

Probably introduced at or before Emacs version 27.1.

Key Bindings

Aliases

xml-mode

Source Code

;; Defined in /usr/src/emacs/lisp/nxml/nxml-mode.el.gz
;;;###autoload
(define-derived-mode nxml-mode text-mode "nXML"
  ;; We use C-c C-i instead of \\[nxml-balanced-close-start-tag-inline]
  ;; because Emacs turns C-c C-i into C-c TAB which is hard to type and
  ;; not mnemonic.
  "Major mode for editing XML.
\\<nxml-mode-map>
\\[nxml-finish-element] finishes the current element by inserting an end-tag.

C-c C-i closes a start-tag with `>' and then inserts a balancing end-tag
leaving point between the start-tag and end-tag.
\\[nxml-balanced-close-start-tag-block] is similar but for block rather than inline elements:
the start-tag, point, and end-tag are all left on separate lines.
If `nxml-slash-auto-complete-flag' is non-nil, then inserting a `</'
automatically inserts the rest of the end-tag.

\\[completion-at-point] performs completion on the symbol preceding point.

\\[nxml-dynamic-markup-word] uses the contents of the current buffer
to choose a tag to put around the word preceding point.

Sections of the document can be displayed in outline form.  The
variable `nxml-section-element-name-regexp' controls when an element
is recognized as a section.  The same key sequences that change
visibility in outline mode are used except that they start with C-c C-o
instead of C-c.

Validation is provided by the related minor-mode `rng-validate-mode'.
This also makes completion schema- and context- sensitive.  Element
names, attribute names, attribute values and namespace URIs can all be
completed. By default, `rng-validate-mode' is automatically enabled.
You can toggle it using \\[rng-validate-mode] or change the default by
customizing `rng-nxml-auto-validate-flag'.

\\[indent-for-tab-command] indents the current line appropriately.
This can be customized using the variable `nxml-child-indent'
and the variable `nxml-attribute-indent'.

\\[nxml-insert-named-char] inserts a character reference using
the character's name (by default, the Unicode name).
\\[universal-argument] \\[nxml-insert-named-char] inserts the character directly.

The Emacs commands that normally operate on balanced expressions will
operate on XML markup items.  Thus \\[forward-sexp] will move forward
across one markup item; \\[backward-sexp] will move backward across
one markup item; \\[kill-sexp] will kill the following markup item;
\\[mark-sexp] will mark the following markup item.  By default, the
complete element is treated as a single markup item; to make each tag be
treated as a separate markup item, set the variable `nxml-sexp-element-flag'
to nil.  For more details, see the function `nxml-forward-balanced-item'.

\\[nxml-backward-up-element] and \\[nxml-down-element] move up and down the element structure.

Many aspects this mode can be customized using
\\[customize-group] nxml RET."
  ;; (kill-all-local-variables)
  ;; If encoding does not allow non-break space character, use reference.
  ;; FIXME: This duplicates code from sgml-mode, perhaps derive from it?
  ;; FIXME: Perhaps use &nbsp; if possible (e.g. XHTML)?
  (setq-local tildify-space-string
              (if (equal (decode-coding-string
                          (encode-coding-string " " buffer-file-coding-system)
                          buffer-file-coding-system) " ")
                  " " "&#160;"))
  ;; FIXME: Use the fact that we're parsing the document already
  ;; rather than using regex-based filtering.
  (setq-local tildify-foreach-region-function
              (apply-partially 'tildify-foreach-ignore-environments
                               '(("<! *--" . "-- *>") ("<" . ">"))))
  (setq-local mode-line-process '((nxml-degraded "/degraded")))
  ;; We'll determine the fill prefix ourselves
  (setq-local adaptive-fill-mode nil)
  (setq-local forward-sexp-function #'nxml-forward-balanced-item)
  (setq-local indent-line-function #'nxml-indent-line)
  (setq-local fill-paragraph-function #'nxml-do-fill-paragraph)
  ;; Comment support
  ;; This doesn't seem to work too well;
  ;; I think we should probably roll our own nxml-comment-dwim function.
  (setq-local comment-indent-function #'nxml-indent-line)
  (setq-local comment-start "<!--")
  (setq-local comment-start-skip "<!--[ \t\r\n]*")
  (setq-local comment-end "-->")
  (setq-local comment-end-skip "[ \t\r\n]*-->")
  (setq-local comment-line-break-function #'nxml-newline-and-indent)
  (setq-local comment-quote-nested-function #'nxml-comment-quote-nested)
  (save-excursion
    (save-restriction
      (widen)
      (with-silent-modifications
	(nxml-scan-prolog))))
  (setq-local syntax-ppss-table sgml-tag-syntax-table)
  (setq-local syntax-propertize-function #'nxml-syntax-propertize)
  (add-function :filter-return (local 'filter-buffer-substring-function)
                #'nxml--buffer-substring-filter)
  (add-hook 'change-major-mode-hook #'nxml-cleanup nil t)

  (when (not (and (buffer-file-name) (file-exists-p (buffer-file-name))))
    (when (and nxml-default-buffer-file-coding-system
	       (not (local-variable-p 'buffer-file-coding-system)))
      (setq buffer-file-coding-system nxml-default-buffer-file-coding-system))
    ;; When starting a new file, insert the XML declaration.
    (when (and nxml-auto-insert-xml-declaration-flag
               (zerop (buffer-size)))
      (nxml-insert-xml-declaration)))

  (setq font-lock-defaults
        '(nxml-font-lock-keywords
          nil  ; highlight comments and strings based on syntax-tables
          nil  ; font-lock-keywords-case-fold-search. XML is case sensitive
          nil  ; no special syntax table
          (font-lock-extend-region-functions . (nxml-extend-region))
          (jit-lock-contextually . t)
          (font-lock-unfontify-region-function . nxml-unfontify-region)
          (font-lock-syntactic-face-function
           . sgml-font-lock-syntactic-face)))

  (with-demoted-errors "RNG NXML error: %S"
    (rng-nxml-mode-init)))