1 ;;; nxml-ns.el --- XML namespace processing -*- lexical-binding:t -*-
3 ;; Copyright (C) 2003, 2007-2014 Free Software Foundation, Inc.
6 ;; Keywords: wp, hypermedia, languages, XML
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
25 ;; This file uses a prefix of `nxml-ns'.
31 (defvar nxml-ns-state nil
32 "Contains the state of namespace processing.
33 The state is never modified destructively and so can be saved and
34 restored without copying.
36 The value is a stack represented by a list. The list has length
37 N + 1 where N is the number of open elements. Each member of the
38 list represents the bindings in effect for a particular element.
39 Each member is itself a list whose car is the default namespace
40 \(a symbol or nil) and whose cdr is an alist of (PREFIX . NS) pairs
41 where PREFIX is a string (never nil) and NS is the namespace URI
44 (defconst nxml-ns-initial-state
45 (list (list nil
(cons "xml" nxml-xml-namespace-uri
)))
46 "A list to be used as the initial value of `nxml-ns-state'.
47 This represents the state with no open elements and with the default
48 namespace bindings (no default namespace and only the xml prefix bound).")
50 (defsubst nxml-ns-state
() nxml-ns-state
)
52 (defsubst nxml-ns-set-state
(state)
53 (setq nxml-ns-state state
))
55 (defsubst nxml-ns-state-equal
(state)
56 (equal nxml-ns-state state
))
58 (defmacro nxml-ns-save
(&rest body
)
59 (declare (indent 0) (debug t
))
60 `(let ((nxml-ns-state nxml-ns-initial-state
))
63 (defun nxml-ns-init ()
64 (setq nxml-ns-state nxml-ns-initial-state
))
66 (defun nxml-ns-push-state ()
67 "Change the state by starting a new element.
68 Namespace declarations are inherited from the parent state."
69 (setq nxml-ns-state
(cons (car nxml-ns-state
) nxml-ns-state
)))
71 (defun nxml-ns-pop-state ()
72 "Change the state by ending an element.
73 The behavior is undefined if there is no open element."
74 (setq nxml-ns-state
(cdr nxml-ns-state
)))
76 (defun nxml-ns-get-prefix (prefix)
77 "Return the symbol for namespace bound to PREFIX.
78 Return nil if PREFIX is unbound. PREFIX is a string, never nil."
79 (let ((binding (assoc prefix
(cdar nxml-ns-state
))))
80 (and binding
(cdr binding
))))
82 (defun nxml-ns-set-prefix (prefix ns
)
83 "Change the binding of PREFIX.
84 PREFIX is a string (never nil). NS is a symbol (never nil).
85 The change will be in effect until the end of the current element."
87 (let ((bindings (car nxml-ns-state
)))
88 (cons (cons (car bindings
)
89 (cons (cons prefix ns
) (cdr bindings
)))
90 (cdr nxml-ns-state
)))))
92 (defun nxml-ns-get-default ()
93 "Return the current default namespace as a symbol.
94 Return nil if there is no default namespace."
97 (defun nxml-ns-set-default (ns)
98 "Changes the current default namespace.
99 The change will be in effect until the end of the current element.
100 NS is a symbol or nil."
102 (cons (cons ns
(cdar nxml-ns-state
))
103 (cdr nxml-ns-state
))))
105 (defun nxml-ns-get-context ()
108 (defun nxml-ns-prefixes-for (ns &optional attributep
)
109 (let ((current (car nxml-ns-state
))
113 (eq (car current
) ns
))
114 (setq prefixes
'(nil)))
115 (setq current
(cdr current
))
116 (while (let ((binding (rassq ns current
)))
118 (let ((prefix (car binding
)))
119 (when (eq (nxml-ns-get-prefix prefix
) ns
)
120 (unless (member prefix prefixes
)
121 (push prefix prefixes
))))
123 (cdr (member binding current
))))))
126 (defun nxml-ns-prefix-for (ns)
127 (car (rassq ns
(cdar nxml-ns-state
))))
129 (defun nxml-ns-changed-prefixes ()
130 (let ((old (cadr nxml-ns-state
))
131 (new (car nxml-ns-state
))
135 (unless (eq (car new
) (car old
))
136 (setq changed
'(nil)))
139 (while (not (eq new old
))
141 (cons (caar new
) changed
))
142 (setq new
(cdr new
))))
147 ;;; nxml-ns.el ends here