diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el
index 3869d0327fd..7317f7186ff 100644
--- a/lisp/nxml/nxml-mode.el
+++ b/lisp/nxml/nxml-mode.el
@@ -1378,60 +1378,35 @@ nxml-compute-indent-from-previous-line
(not (or (= xmltok-start (point))
(eq xmltok-type 'data))))))
(setq ref (point))
- ;; Now scan over tokens until the end of the line to be indented.
- ;; Determine the context before and after the beginning of the
- ;; line.
- (while (< (point) eol)
- (nxml-tokenize-forward)
- (cond ((<= bol xmltok-start)
- (setq after-context
- (nxml-merge-indent-context-type after-context)))
- ((and (<= (point) bol)
- (not (and (eq xmltok-type 'partial-start-tag)
- (= (point) bol))))
- (setq before-context
- (nxml-merge-indent-context-type before-context)))
- ((eq xmltok-type 'data)
- (setq before-context
- (nxml-merge-indent-context-type before-context))
- (setq after-context
- (nxml-merge-indent-context-type after-context)))
- ;; If in the middle of a token that looks inline,
- ;; then indent relative to the previous non-blank line
- ((eq (nxml-merge-indent-context-type before-context)
- 'mixed)
- (goto-char prev-bol)
- (throw 'indent (current-column)))
- (t
- (throw 'indent
- (nxml-compute-indent-in-token bol))))
- (skip-chars-forward " \t\r\n"))
- (goto-char ref)
- (+ (current-column)
- (* nxml-child-indent
- (+ (if (eq before-context 'start-tag) 1 0)
- (if (eq after-context 'end-tag) -1 0))))))))
-
-(defun nxml-merge-indent-context-type (context)
- "Merge the indent context type CONTEXT with the token in `xmltok-type'.
-Return the merged indent context type. An indent context type is
-either nil or one of the symbols `start-tag', `end-tag', `markup',
-`comment', `mixed'."
- (cond ((memq xmltok-type '(start-tag partial-start-tag))
- (if (memq context '(nil start-tag comment))
- 'start-tag
- 'mixed))
- ((memq xmltok-type '(end-tag partial-end-tag))
- (if (memq context '(nil end-tag comment))
- 'end-tag
- 'mixed))
- ((eq xmltok-type 'comment)
- (cond ((memq context '(start-tag end-tag comment))
- context)
- (context 'mixed)
- (t 'comment)))
- (context 'mixed)
- (t 'markup)))
+ ;; scan over the prevous line to determine the additional
+ ;; depth of element nesting. Also collect the depth change at
+ ;; the beginning of the line.
+ (let ((depth-before 0)
+ (depth-bol 0))
+ (nxml-tokenize-forward)
+ (when (> (point) bol) ; one token spans this and the line before
+ (throw 'indent (nxml-compute-indent-in-token bol)))
+ (while (< (point) bol)
+ (cond ((eq xmltok-type 'partial-start-tag)
+ (throw 'indent (nxml-compute-indent-in-token bol)))
+ ((memq xmltok-type '(start-tag))
+ (cl-incf depth-before))
+ ((memq xmltok-type '(end-tag partial-end-tag))
+ (cl-incf depth-before -1)))
+ (skip-chars-forward " \t\r\n")
+ (nxml-tokenize-forward))
+ (when (<= xmltok-start eol)
+ (cond ((memq xmltok-type '(start-tag partial-start-tag data))
+ (setq depth-bol 1))
+ ((memq xmltok-type '(end-tag partial-end-tag))
+ (setq depth-bol -1))))
+ (goto-char ref)
+ (+ (current-column)
+ (* nxml-child-indent
+ ;; never change more than one indent level
+ (cl-signum (if (eq depth-before 0)
+ (min 0 depth-bol)
+ (+ (cl-signum depth-before) depth-bol))))))))))
(defun nxml-compute-indent-in-token (pos)
"Return the indent for a line that starts inside a token.
diff --git a/test/lisp/nxml/nxml-mode-tests.el b/test/lisp/nxml/nxml-mode-tests.el
index 973f2ebb67e..f5a691ee181 100644
--- a/test/lisp/nxml/nxml-mode-tests.el
+++ b/test/lisp/nxml/nxml-mode-tests.el
@@ -31,6 +31,17 @@ nxml-mode-tests-correctly-indented-string
(ert-deftest nxml-indent-line-after-attribute ()
(should (nxml-mode-tests-correctly-indented-string "
+
+
+ ...
+
+
+"))
+ (should (nxml-mode-tests-correctly-indented-string "
+
+ abc
+ 123
+
+
+
+"))
+ (should (nxml-mode-tests-correctly-indented-string "
+
+ abc
+
+
+
+"))
+ (should (nxml-mode-tests-correctly-indented-string "
+
+
+
+ abckde
+
+ e
+
+
+
+
+
+
+ x
+
+ abc
+ abc
+
+ abc
+
+"))))
+x
+
(provide 'nxml-mode-tests)
;;; nxml-mode-tests.el ends here