aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorEli Zaretskii2003-11-01 17:56:08 +0000
committerEli Zaretskii2003-11-01 17:56:08 +0000
commit346389962981d01a6d020819e15f6d7384a3d2bf (patch)
tree53dddbcb57fe15ea5abf7d79983098d21847d407 /lisp
parentcfc8b2640f4ae202cc437ed18f46aff2b94066d5 (diff)
downloademacs-346389962981d01a6d020819e15f6d7384a3d2bf.tar.gz
emacs-346389962981d01a6d020819e15f6d7384a3d2bf.zip
Allow comments following the top-level element.
Separate out namespace parsing into special functions. Change namespace parsing to return ('ns-uri . "local-name") instead of '{ns-uri}local-name.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/xml.el153
1 files changed, 94 insertions, 59 deletions
diff --git a/lisp/xml.el b/lisp/xml.el
index 27363f7ee2d..279fe48b16b 100644
--- a/lisp/xml.el
+++ b/lisp/xml.el
@@ -208,13 +208,14 @@ If PARSE-NS is non-nil, then QNAMES are expanded."
208 (if (search-forward "<" nil t) 208 (if (search-forward "<" nil t)
209 (progn 209 (progn
210 (forward-char -1) 210 (forward-char -1)
211 (if xml 211 (setq result (xml-parse-tag parse-dtd parse-ns))
212 (if (and xml result)
212 ;; translation of rule [1] of XML specifications 213 ;; translation of rule [1] of XML specifications
213 (error "XML files can have only one toplevel tag") 214 (error "XML files can have only one toplevel tag")
214 (setq result (xml-parse-tag parse-dtd parse-ns))
215 (cond 215 (cond
216 ((null result)) 216 ((null result))
217 ((listp (car result)) 217 ((and (listp (car result))
218 parse-dtd)
218 (setq dtd (car result)) 219 (setq dtd (car result))
219 (if (cdr result) ; possible leading comment 220 (if (cdr result) ; possible leading comment
220 (add-to-list 'xml (cdr result)))) 221 (add-to-list 'xml (cdr result))))
@@ -225,6 +226,73 @@ If PARSE-NS is non-nil, then QNAMES are expanded."
225 (cons dtd (nreverse xml)) 226 (cons dtd (nreverse xml))
226 (nreverse xml))))))) 227 (nreverse xml)))))))
227 228
229(defun xml-ns-parse-ns-attrs (attr-list &optional xml-ns)
230 "Parse the namespace attributes and return a list of cons in the form:
231\(namespace . prefix)"
232
233 (mapcar
234 (lambda (attr)
235 (let* ((splitup (split-string (car attr) ":"))
236 (prefix (nth 0 splitup))
237 (lname (nth 1 splitup)))
238 (when (string= "xmlns" prefix)
239 (push (cons (if lname
240 lname
241 "")
242 (cdr attr))
243 xml-ns)))) attr-list)
244 xml-ns)
245
246;; expand element names
247(defun xml-ns-expand-el (el xml-ns)
248 "Expand the XML elements from \"prefix:local-name\" to a cons in the form
249\"(namespace . local-name)\"."
250
251 (let* ((splitup (split-string el ":"))
252 (lname (or (nth 1 splitup)
253 (nth 0 splitup)))
254 (prefix (if (nth 1 splitup)
255 (nth 0 splitup)
256 (if (string= lname "xmlns")
257 "xmlns"
258 "")))
259 (ns (cdr (assoc-string prefix xml-ns))))
260 (if (string= "" ns)
261 lname
262 (cons (intern (concat ":" ns))
263 lname))))
264
265;; expand attribute names
266(defun xml-ns-expand-attr (attr-list xml-ns)
267 "Expand the attribute list for a particular element from the form
268\"prefix:local-name\" to the form \"{namespace}:local-name\"."
269
270 (mapcar
271 (lambda (attr)
272 (let* ((splitup (split-string (car attr) ":"))
273 (lname (or (nth 1 splitup)
274 (nth 0 splitup)))
275 (prefix (if (nth 1 splitup)
276 (nth 0 splitup)
277 (if (string= (car attr) "xmlns")
278 "xmlns"
279 "")))
280 (ns (cdr (assoc-string prefix xml-ns))))
281 (setcar attr
282 (if (string= "" ns)
283 lname
284 (cons (intern (concat ":" ns))
285 lname)))))
286 attr-list)
287 attr-list)
288
289
290(defun xml-intern-attrlist (attr-list)
291 "Convert attribute names to symbols for backward compatibility."
292 (mapcar (lambda (attr)
293 (setcar attr (intern (car attr))))
294 attr-list)
295 attr-list)
228 296
229(defun xml-parse-tag (&optional parse-dtd parse-ns) 297(defun xml-parse-tag (&optional parse-dtd parse-ns)
230 "Parse the tag at point. 298 "Parse the tag at point.
@@ -276,53 +344,22 @@ Returns one of:
276 ;; opening tag 344 ;; opening tag
277 ((looking-at "<\\([^/>[:space:]]+\\)") 345 ((looking-at "<\\([^/>[:space:]]+\\)")
278 (goto-char (match-end 1)) 346 (goto-char (match-end 1))
347
348 ;; Parse this node
279 (let* ((node-name (match-string 1)) 349 (let* ((node-name (match-string 1))
280 ;; Parse the attribute list. 350 (attr-list (xml-parse-attlist))
281 (children (list (xml-parse-attlist) (intern node-name))) 351 (children (if (consp xml-ns) ;; take care of namespace parsing
352 (progn
353 (setq xml-ns (xml-ns-parse-ns-attrs
354 attr-list xml-ns))
355 (list (xml-ns-expand-attr
356 attr-list xml-ns)
357 (xml-ns-expand-el
358 node-name xml-ns)))
359 (list (xml-intern-attrlist attr-list)
360 (intern node-name))))
282 pos) 361 pos)
283 362
284 ;; add the xmlns:* attrs to our cache
285 (when (consp xml-ns)
286 (mapcar
287 (lambda (attr)
288 (let* ((splitup (split-string (symbol-name (car attr)) ":"))
289 (prefix (nth 0 splitup))
290 (lname (nth 1 splitup)))
291 (when (string= "xmlns" prefix)
292 (setq xml-ns (append (list (cons (if lname
293 lname
294 "")
295 (cdr attr)))
296 xml-ns)))))
297 (car children))
298
299 ;; expand element names
300 (let* ((splitup (split-string (symbol-name (cadr children)) ":"))
301 (lname (or (nth 1 splitup)
302 (nth 0 splitup)))
303 (prefix (if (nth 1 splitup)
304 (nth 0 splitup)
305 "")))
306 (setcdr children (list
307 (intern (concat "{"
308 (cdr (assoc-string prefix xml-ns))
309 "}" lname)))))
310
311 ;; expand attribute names
312 (mapcar
313 (lambda (attr)
314 (let* ((splitup (split-string (symbol-name (car attr)) ":"))
315 (lname (or (nth 1 splitup)
316 (nth 0 splitup)))
317 (prefix (if (nth 1 splitup)
318 (nth 0 splitup)
319 (caar xml-ns))))
320
321 (setcar attr (intern (concat "{"
322 (cdr (assoc-string prefix xml-ns))
323 "}" lname)))))
324 (car children)))
325
326 ;; is this an empty element ? 363 ;; is this an empty element ?
327 (if (looking-at "/>") 364 (if (looking-at "/>")
328 (progn 365 (progn
@@ -377,13 +414,14 @@ Returns one of:
377 (error "XML: Invalid character"))))) 414 (error "XML: Invalid character")))))
378 415
379(defun xml-parse-attlist () 416(defun xml-parse-attlist ()
380 "Return the attribute-list after point.Leave point at the first non-blank character after the tag." 417 "Return the attribute-list after point. Leave point at the
418first non-blank character after the tag."
381 (let ((attlist ()) 419 (let ((attlist ())
382 start-pos name) 420 end-pos name)
383 (skip-syntax-forward " ") 421 (skip-syntax-forward " ")
384 (while (looking-at (eval-when-compile 422 (while (looking-at (eval-when-compile
385 (concat "\\(" xml-name-regexp "\\)\\s-*=\\s-*"))) 423 (concat "\\(" xml-name-regexp "\\)\\s-*=\\s-*")))
386 (setq name (intern (match-string 1))) 424 (setq name (match-string 1))
387 (goto-char (match-end 0)) 425 (goto-char (match-end 0))
388 426
389 ;; See also: http://www.w3.org/TR/2000/REC-xml-20001006#AVNormalize 427 ;; See also: http://www.w3.org/TR/2000/REC-xml-20001006#AVNormalize
@@ -391,9 +429,9 @@ Returns one of:
391 ;; Do we have a string between quotes (or double-quotes), 429 ;; Do we have a string between quotes (or double-quotes),
392 ;; or a simple word ? 430 ;; or a simple word ?
393 (if (looking-at "\"\\([^\"]*\\)\"") 431 (if (looking-at "\"\\([^\"]*\\)\"")
394 (setq start-pos (match-beginning 0)) 432 (setq end-pos (match-end 0))
395 (if (looking-at "'\\([^']*\\)'") 433 (if (looking-at "'\\([^']*\\)'")
396 (setq start-pos (match-beginning 0)) 434 (setq end-pos (match-end 0))
397 (error "XML: Attribute values must be given between quotes"))) 435 (error "XML: Attribute values must be given between quotes")))
398 436
399 ;; Each attribute must be unique within a given element 437 ;; Each attribute must be unique within a given element
@@ -407,9 +445,7 @@ Returns one of:
407 (replace-regexp-in-string "\\s-\\{2,\\}" " " string) 445 (replace-regexp-in-string "\\s-\\{2,\\}" " " string)
408 (push (cons name (xml-substitute-special string)) attlist)) 446 (push (cons name (xml-substitute-special string)) attlist))
409 447
410 (goto-char start-pos) 448 (goto-char end-pos)
411 (forward-sexp) ; we have string syntax
412
413 (skip-syntax-forward " ")) 449 (skip-syntax-forward " "))
414 (nreverse attlist))) 450 (nreverse attlist)))
415 451
@@ -490,7 +526,7 @@ This follows the rule [28] in the XML specifications."
490 ((looking-at 526 ((looking-at
491 "<!ELEMENT\\s-+\\([[:alnum:].%;]+\\)\\s-+\\([^>]+\\)>") 527 "<!ELEMENT\\s-+\\([[:alnum:].%;]+\\)\\s-+\\([^>]+\\)>")
492 528
493 (setq element (intern (match-string 1)) 529 (setq element (match-string 1)
494 type (match-string-no-properties 2)) 530 type (match-string-no-properties 2))
495 (setq end-pos (match-end 0)) 531 (setq end-pos (match-end 0))
496 532
@@ -510,7 +546,7 @@ This follows the rule [28] in the XML specifications."
510 ;; rule [45]: the element declaration must be unique 546 ;; rule [45]: the element declaration must be unique
511 (if (assoc element dtd) 547 (if (assoc element dtd)
512 (error "XML: element declarations must be unique in a DTD (<%s>)" 548 (error "XML: element declarations must be unique in a DTD (<%s>)"
513 (symbol-name element))) 549 element)
514 550
515 ;; Store the element in the DTD 551 ;; Store the element in the DTD
516 (push (list element type) dtd) 552 (push (list element type) dtd)
@@ -523,8 +559,7 @@ This follows the rule [28] in the XML specifications."
523 559
524 ;; Skip the end of the DTD 560 ;; Skip the end of the DTD
525 (search-forward ">")))) 561 (search-forward ">"))))
526 (nreverse dtd))) 562 (nreverse dtd))))
527
528 563
529(defun xml-parse-elem-type (string) 564(defun xml-parse-elem-type (string)
530 "Convert element type STRING into a Lisp structure." 565 "Convert element type STRING into a Lisp structure."