diff options
| author | Stefan Monnier | 2001-12-14 22:12:30 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2001-12-14 22:12:30 +0000 |
| commit | 971489ea0073e704738b2d8ed9d3175b9434fb43 (patch) | |
| tree | f4e9a9f134d2c529fdc3da2187b5ba427b714b75 | |
| parent | 7a06b25076fe26a4975da834dd97912bc70c3c32 (diff) | |
| download | emacs-971489ea0073e704738b2d8ed9d3175b9434fb43.tar.gz emacs-971489ea0073e704738b2d8ed9d3175b9434fb43.zip | |
Use setq rather than (set 'foo bar).
Use push+nreverse rather than append.
(xml-node-name, xml-node-attributes, xml-node-children):
Use defsubst rather than macros.
(xml-parse-region): Handle a nil return value from xml-parse-tag.
(xml-parse-tag): Don't skip white space. Return nil for a comment.
Concat the two strings surrounding a comment into a single string.
| -rw-r--r-- | lisp/xml.el | 197 |
1 files changed, 90 insertions, 107 deletions
diff --git a/lisp/xml.el b/lisp/xml.el index b2831c6ac54..d6d6d80efa9 100644 --- a/lisp/xml.el +++ b/lisp/xml.el | |||
| @@ -73,32 +73,30 @@ | |||
| 73 | ;;** | 73 | ;;** |
| 74 | ;;******************************************************************* | 74 | ;;******************************************************************* |
| 75 | 75 | ||
| 76 | (defmacro xml-node-name (node) | 76 | (defsubst xml-node-name (node) |
| 77 | "Return the tag associated with NODE. | 77 | "Return the tag associated with NODE. |
| 78 | The tag is a lower-case symbol." | 78 | The tag is a lower-case symbol." |
| 79 | (list 'car node)) | 79 | (car node)) |
| 80 | 80 | ||
| 81 | (defmacro xml-node-attributes (node) | 81 | (defsubst xml-node-attributes (node) |
| 82 | "Return the list of attributes of NODE. | 82 | "Return the list of attributes of NODE. |
| 83 | The list can be nil." | 83 | The list can be nil." |
| 84 | (list 'nth 1 node)) | 84 | (nth 1 node)) |
| 85 | 85 | ||
| 86 | (defmacro xml-node-children (node) | 86 | (defsubst xml-node-children (node) |
| 87 | "Return the list of children of NODE. | 87 | "Return the list of children of NODE. |
| 88 | This is a list of nodes, and it can be nil." | 88 | This is a list of nodes, and it can be nil." |
| 89 | (list 'cddr node)) | 89 | (cddr node)) |
| 90 | 90 | ||
| 91 | (defun xml-get-children (node child-name) | 91 | (defun xml-get-children (node child-name) |
| 92 | "Return the children of NODE whose tag is CHILD-NAME. | 92 | "Return the children of NODE whose tag is CHILD-NAME. |
| 93 | CHILD-NAME should be a lower case symbol." | 93 | CHILD-NAME should be a lower case symbol." |
| 94 | (let ((children (xml-node-children node)) | 94 | (let ((match ())) |
| 95 | match) | 95 | (dolist (child (xml-node-children node)) |
| 96 | (while children | 96 | (if child |
| 97 | (if (car children) | 97 | (if (equal (xml-node-name child) child-name) |
| 98 | (if (equal (xml-node-name (car children)) child-name) | 98 | (push child match)))) |
| 99 | (set 'match (append match (list (car children)))))) | 99 | (nreverse match))) |
| 100 | (set 'children (cdr children))) | ||
| 101 | match)) | ||
| 102 | 100 | ||
| 103 | (defun xml-get-attribute (node attribute) | 101 | (defun xml-get-attribute (node attribute) |
| 104 | "Get from NODE the value of ATTRIBUTE. | 102 | "Get from NODE the value of ATTRIBUTE. |
| @@ -155,10 +153,11 @@ and returned as the first element of the list" | |||
| 155 | (forward-char -1) | 153 | (forward-char -1) |
| 156 | (if (null xml) | 154 | (if (null xml) |
| 157 | (progn | 155 | (progn |
| 158 | (set 'result (xml-parse-tag end parse-dtd)) | 156 | (setq result (xml-parse-tag end parse-dtd)) |
| 159 | (cond | 157 | (cond |
| 158 | ((null result)) | ||
| 160 | ((listp (car result)) | 159 | ((listp (car result)) |
| 161 | (set 'dtd (car result)) | 160 | (setq dtd (car result)) |
| 162 | (add-to-list 'xml (cdr result))) | 161 | (add-to-list 'xml (cdr result))) |
| 163 | (t | 162 | (t |
| 164 | (add-to-list 'xml result)))) | 163 | (add-to-list 'xml result)))) |
| @@ -197,7 +196,7 @@ Returns one of: | |||
| 197 | ((looking-at "<!DOCTYPE") | 196 | ((looking-at "<!DOCTYPE") |
| 198 | (let (dtd) | 197 | (let (dtd) |
| 199 | (if parse-dtd | 198 | (if parse-dtd |
| 200 | (set 'dtd (xml-parse-dtd end)) | 199 | (setq dtd (xml-parse-dtd end)) |
| 201 | (xml-skip-dtd end)) | 200 | (xml-skip-dtd end)) |
| 202 | (skip-chars-forward " \t\n") | 201 | (skip-chars-forward " \t\n") |
| 203 | (if dtd | 202 | (if dtd |
| @@ -206,36 +205,31 @@ Returns one of: | |||
| 206 | ;; skip comments | 205 | ;; skip comments |
| 207 | ((looking-at "<!--") | 206 | ((looking-at "<!--") |
| 208 | (search-forward "-->" end) | 207 | (search-forward "-->" end) |
| 209 | (skip-chars-forward " \t\n") | 208 | nil) |
| 210 | (xml-parse-tag end)) | ||
| 211 | ;; end tag | 209 | ;; end tag |
| 212 | ((looking-at "</") | 210 | ((looking-at "</") |
| 213 | '()) | 211 | '()) |
| 214 | ;; opening tag | 212 | ;; opening tag |
| 215 | ((looking-at "<\\([^/> \t\n]+\\)") | 213 | ((looking-at "<\\([^/> \t\n]+\\)") |
| 216 | (let* ((node-name (match-string 1)) | 214 | (goto-char (match-end 1)) |
| 217 | (children (list (intern node-name))) | 215 | (let* ((case-fold-search nil) ;; XML is case-sensitive. |
| 218 | (case-fold-search nil) ;; XML is case-sensitive | 216 | (node-name (match-string 1)) |
| 217 | ;; Parse the attribute list. | ||
| 218 | (children (list (xml-parse-attlist end) (intern node-name))) | ||
| 219 | pos) | 219 | pos) |
| 220 | (goto-char (match-end 1)) | ||
| 221 | |||
| 222 | ;; parses the attribute list | ||
| 223 | (set 'children (append children (list (xml-parse-attlist end)))) | ||
| 224 | 220 | ||
| 225 | ;; is this an empty element ? | 221 | ;; is this an empty element ? |
| 226 | (if (looking-at "/>") | 222 | (if (looking-at "/>") |
| 227 | (progn | 223 | (progn |
| 228 | (forward-char 2) | 224 | (forward-char 2) |
| 229 | (skip-chars-forward " \t\n") | 225 | (nreverse (cons '("") children))) |
| 230 | (append children '(""))) | ||
| 231 | 226 | ||
| 232 | ;; is this a valid start tag ? | 227 | ;; is this a valid start tag ? |
| 233 | (if (eq (char-after) ?>) | 228 | (if (eq (char-after) ?>) |
| 234 | (progn | 229 | (progn |
| 235 | (forward-char 1) | 230 | (forward-char 1) |
| 236 | (skip-chars-forward " \t\n") | 231 | ;; Now check that we have the right end-tag. Note that this |
| 237 | ;; Now check that we have the right end-tag. Note that this one might | 232 | ;; one might contain spaces after the tag name |
| 238 | ;; contain spaces after the tag name | ||
| 239 | (while (not (looking-at (concat "</" node-name "[ \t\n]*>"))) | 233 | (while (not (looking-at (concat "</" node-name "[ \t\n]*>"))) |
| 240 | (cond | 234 | (cond |
| 241 | ((looking-at "</") | 235 | ((looking-at "</") |
| @@ -244,9 +238,11 @@ Returns one of: | |||
| 244 | node-name | 238 | node-name |
| 245 | ") at pos " (number-to-string (point))))) | 239 | ") at pos " (number-to-string (point))))) |
| 246 | ((= (char-after) ?<) | 240 | ((= (char-after) ?<) |
| 247 | (set 'children (append children (list (xml-parse-tag end))))) | 241 | (let ((tag (xml-parse-tag end))) |
| 242 | (when tag | ||
| 243 | (push tag children)))) | ||
| 248 | (t | 244 | (t |
| 249 | (set 'pos (point)) | 245 | (setq pos (point)) |
| 250 | (search-forward "<" end) | 246 | (search-forward "<" end) |
| 251 | (forward-char -1) | 247 | (forward-char -1) |
| 252 | (let ((string (buffer-substring-no-properties pos (point))) | 248 | (let ((string (buffer-substring-no-properties pos (point))) |
| @@ -256,18 +252,21 @@ Returns one of: | |||
| 256 | ;; Not done, since as per XML specifications, the XML processor | 252 | ;; Not done, since as per XML specifications, the XML processor |
| 257 | ;; should always pass the whole string to the application. | 253 | ;; should always pass the whole string to the application. |
| 258 | ;; (while (string-match "\\s +" string pos) | 254 | ;; (while (string-match "\\s +" string pos) |
| 259 | ;; (set 'string (replace-match " " t t string)) | 255 | ;; (setq string (replace-match " " t t string)) |
| 260 | ;; (set 'pos (1+ (match-beginning 0)))) | 256 | ;; (setq pos (1+ (match-beginning 0)))) |
| 261 | 257 | ||
| 262 | (set 'children (append children | 258 | (setq string (xml-substitute-special string)) |
| 263 | (list (xml-substitute-special string)))))))) | 259 | (setq children |
| 260 | (if (stringp (car children)) | ||
| 261 | ;; The two strings were separated by a comment. | ||
| 262 | (cons (concat (car children) string) | ||
| 263 | (cdr children)) | ||
| 264 | (cons string children))))))) | ||
| 264 | (goto-char (match-end 0)) | 265 | (goto-char (match-end 0)) |
| 265 | (skip-chars-forward " \t\n") | ||
| 266 | (if (> (point) end) | 266 | (if (> (point) end) |
| 267 | (error "XML: End tag for %s not found before end of region" | 267 | (error "XML: End tag for %s not found before end of region" |
| 268 | node-name)) | 268 | node-name)) |
| 269 | children | 269 | (nreverse children)) |
| 270 | ) | ||
| 271 | 270 | ||
| 272 | ;; This was an invalid start tag | 271 | ;; This was an invalid start tag |
| 273 | (error "XML: Invalid attribute list") | 272 | (error "XML: Invalid attribute list") |
| @@ -280,11 +279,11 @@ Returns one of: | |||
| 280 | "Return the attribute-list that point is looking at. | 279 | "Return the attribute-list that point is looking at. |
| 281 | The search for attributes end at the position END in the current buffer. | 280 | The search for attributes end at the position END in the current buffer. |
| 282 | Leaves the point on the first non-blank character after the tag." | 281 | Leaves the point on the first non-blank character after the tag." |
| 283 | (let ((attlist '()) | 282 | (let ((attlist ()) |
| 284 | name) | 283 | name) |
| 285 | (skip-chars-forward " \t\n") | 284 | (skip-chars-forward " \t\n") |
| 286 | (while (looking-at "\\([a-zA-Z_:][-a-zA-Z0-9._:]*\\)[ \t\n]*=[ \t\n]*") | 285 | (while (looking-at "\\([a-zA-Z_:][-a-zA-Z0-9._:]*\\)[ \t\n]*=[ \t\n]*") |
| 287 | (set 'name (intern (match-string 1))) | 286 | (setq name (intern (match-string 1))) |
| 288 | (goto-char (match-end 0)) | 287 | (goto-char (match-end 0)) |
| 289 | 288 | ||
| 290 | ;; Do we have a string between quotes (or double-quotes), | 289 | ;; Do we have a string between quotes (or double-quotes), |
| @@ -297,15 +296,13 @@ Leaves the point on the first non-blank character after the tag." | |||
| 297 | (if (assoc name attlist) | 296 | (if (assoc name attlist) |
| 298 | (error "XML: each attribute must be unique within an element")) | 297 | (error "XML: each attribute must be unique within an element")) |
| 299 | 298 | ||
| 300 | (set 'attlist (append attlist | 299 | (push (cons name (match-string-no-properties 1)) attlist) |
| 301 | (list (cons name (match-string-no-properties 1))))) | ||
| 302 | (goto-char (match-end 0)) | 300 | (goto-char (match-end 0)) |
| 303 | (skip-chars-forward " \t\n") | 301 | (skip-chars-forward " \t\n") |
| 304 | (if (> (point) end) | 302 | (if (> (point) end) |
| 305 | (error "XML: end of attribute list not found before end of region")) | 303 | (error "XML: end of attribute list not found before end of region")) |
| 306 | ) | 304 | ) |
| 307 | attlist | 305 | (nreverse attlist))) |
| 308 | )) | ||
| 309 | 306 | ||
| 310 | ;;******************************************************************* | 307 | ;;******************************************************************* |
| 311 | ;;** | 308 | ;;** |
| @@ -335,15 +332,15 @@ This follows the rule [28] in the XML specifications." | |||
| 335 | (defun xml-parse-dtd (end) | 332 | (defun xml-parse-dtd (end) |
| 336 | "Parse the DTD that point is looking at. | 333 | "Parse the DTD that point is looking at. |
| 337 | The DTD must end before the position END in the current buffer." | 334 | The DTD must end before the position END in the current buffer." |
| 338 | (let (dtd type element end-pos) | 335 | (forward-char (length "<!DOCTYPE")) |
| 339 | (forward-char (length "<!DOCTYPE")) | 336 | (skip-chars-forward " \t\n") |
| 340 | (skip-chars-forward " \t\n") | 337 | (if (looking-at ">") |
| 341 | (if (looking-at ">") | 338 | (error "XML: invalid DTD (excepting name of the document)")) |
| 342 | (error "XML: invalid DTD (excepting name of the document)")) | 339 | |
| 343 | 340 | ;; Get the name of the document | |
| 344 | ;; Get the name of the document | 341 | (looking-at "\\sw+") |
| 345 | (looking-at "\\sw+") | 342 | (let ((dtd (list (match-string-no-properties 0) 'dtd)) |
| 346 | (set 'dtd (list 'dtd (match-string-no-properties 0))) | 343 | type element end-pos) |
| 347 | (goto-char (match-end 0)) | 344 | (goto-char (match-end 0)) |
| 348 | 345 | ||
| 349 | (skip-chars-forward " \t\n") | 346 | (skip-chars-forward " \t\n") |
| @@ -367,16 +364,16 @@ The DTD must end before the position END in the current buffer." | |||
| 367 | 364 | ||
| 368 | (setq element (intern (match-string-no-properties 1)) | 365 | (setq element (intern (match-string-no-properties 1)) |
| 369 | type (match-string-no-properties 2)) | 366 | type (match-string-no-properties 2)) |
| 370 | (set 'end-pos (match-end 0)) | 367 | (setq end-pos (match-end 0)) |
| 371 | 368 | ||
| 372 | ;; Translation of rule [46] of XML specifications | 369 | ;; Translation of rule [46] of XML specifications |
| 373 | (cond | 370 | (cond |
| 374 | ((string-match "^EMPTY[ \t\n]*$" type) ;; empty declaration | 371 | ((string-match "^EMPTY[ \t\n]*$" type) ;; empty declaration |
| 375 | (set 'type 'empty)) | 372 | (setq type 'empty)) |
| 376 | ((string-match "^ANY[ \t\n]*$" type) ;; any type of contents | 373 | ((string-match "^ANY[ \t\n]*$" type) ;; any type of contents |
| 377 | (set 'type 'any)) | 374 | (setq type 'any)) |
| 378 | ((string-match "^(\\(.*\\))[ \t\n]*$" type) ;; children ([47]) | 375 | ((string-match "^(\\(.*\\))[ \t\n]*$" type) ;; children ([47]) |
| 379 | (set 'type (xml-parse-elem-type (match-string-no-properties 1 type)))) | 376 | (setq type (xml-parse-elem-type (match-string-no-properties 1 type)))) |
| 380 | ((string-match "^%[^;]+;[ \t\n]*$" type) ;; substitution | 377 | ((string-match "^%[^;]+;[ \t\n]*$" type) ;; substitution |
| 381 | nil) | 378 | nil) |
| 382 | (t | 379 | (t |
| @@ -388,9 +385,8 @@ The DTD must end before the position END in the current buffer." | |||
| 388 | (symbol-name element))) | 385 | (symbol-name element))) |
| 389 | 386 | ||
| 390 | ;; Store the element in the DTD | 387 | ;; Store the element in the DTD |
| 391 | (set 'dtd (append dtd (list (list element type)))) | 388 | (push (list element type) dtd) |
| 392 | (goto-char end-pos) | 389 | (goto-char end-pos)) |
| 393 | ) | ||
| 394 | 390 | ||
| 395 | 391 | ||
| 396 | (t | 392 | (t |
| @@ -400,8 +396,7 @@ The DTD must end before the position END in the current buffer." | |||
| 400 | 396 | ||
| 401 | ;; Skip the end of the DTD | 397 | ;; Skip the end of the DTD |
| 402 | (search-forward ">" end) | 398 | (search-forward ">" end) |
| 403 | dtd | 399 | (nreverse dtd))) |
| 404 | )) | ||
| 405 | 400 | ||
| 406 | 401 | ||
| 407 | (defun xml-parse-elem-type (string) | 402 | (defun xml-parse-elem-type (string) |
| @@ -413,11 +408,11 @@ The DTD must end before the position END in the current buffer." | |||
| 413 | (setq elem (match-string 1 string) | 408 | (setq elem (match-string 1 string) |
| 414 | modifier (match-string 2 string)) | 409 | modifier (match-string 2 string)) |
| 415 | (if (string-match "|" elem) | 410 | (if (string-match "|" elem) |
| 416 | (set 'elem (append '(choice) | 411 | (setq elem (cons 'choice |
| 417 | (mapcar 'xml-parse-elem-type | 412 | (mapcar 'xml-parse-elem-type |
| 418 | (split-string elem "|")))) | 413 | (split-string elem "|")))) |
| 419 | (if (string-match "," elem) | 414 | (if (string-match "," elem) |
| 420 | (set 'elem (append '(seq) | 415 | (setq elem (cons 'seq |
| 421 | (mapcar 'xml-parse-elem-type | 416 | (mapcar 'xml-parse-elem-type |
| 422 | (split-string elem ",")))) | 417 | (split-string elem ",")))) |
| 423 | ))) | 418 | ))) |
| @@ -425,19 +420,18 @@ The DTD must end before the position END in the current buffer." | |||
| 425 | (setq elem (match-string 1 string) | 420 | (setq elem (match-string 1 string) |
| 426 | modifier (match-string 2 string)))) | 421 | modifier (match-string 2 string)))) |
| 427 | 422 | ||
| 428 | (if (and (stringp elem) | 423 | (if (and (stringp elem) (string= elem "#PCDATA")) |
| 429 | (string= elem "#PCDATA")) | 424 | (setq elem 'pcdata)) |
| 430 | (set 'elem 'pcdata)) | ||
| 431 | 425 | ||
| 432 | (cond | 426 | (cond |
| 433 | ((string= modifier "+") | 427 | ((string= modifier "+") |
| 434 | (list '+ elem)) | 428 | (list '+ elem)) |
| 435 | ((string= modifier "*") | 429 | ((string= modifier "*") |
| 436 | (list '* elem)) | 430 | (list '* elem)) |
| 437 | ((string= modifier "?") | 431 | ((string= modifier "?") |
| 438 | (list '? elem)) | 432 | (list '? elem)) |
| 439 | (t | 433 | (t |
| 440 | elem)))) | 434 | elem)))) |
| 441 | 435 | ||
| 442 | 436 | ||
| 443 | ;;******************************************************************* | 437 | ;;******************************************************************* |
| @@ -449,15 +443,15 @@ The DTD must end before the position END in the current buffer." | |||
| 449 | (defun xml-substitute-special (string) | 443 | (defun xml-substitute-special (string) |
| 450 | "Return STRING, after subsituting special XML sequences." | 444 | "Return STRING, after subsituting special XML sequences." |
| 451 | (while (string-match "&" string) | 445 | (while (string-match "&" string) |
| 452 | (set 'string (replace-match "&" t nil string))) | 446 | (setq string (replace-match "&" t nil string))) |
| 453 | (while (string-match "<" string) | 447 | (while (string-match "<" string) |
| 454 | (set 'string (replace-match "<" t nil string))) | 448 | (setq string (replace-match "<" t nil string))) |
| 455 | (while (string-match ">" string) | 449 | (while (string-match ">" string) |
| 456 | (set 'string (replace-match ">" t nil string))) | 450 | (setq string (replace-match ">" t nil string))) |
| 457 | (while (string-match "'" string) | 451 | (while (string-match "'" string) |
| 458 | (set 'string (replace-match "'" t nil string))) | 452 | (setq string (replace-match "'" t nil string))) |
| 459 | (while (string-match """ string) | 453 | (while (string-match """ string) |
| 460 | (set 'string (replace-match "\"" t nil string))) | 454 | (setq string (replace-match "\"" t nil string))) |
| 461 | string) | 455 | string) |
| 462 | 456 | ||
| 463 | ;;******************************************************************* | 457 | ;;******************************************************************* |
| @@ -468,50 +462,39 @@ The DTD must end before the position END in the current buffer." | |||
| 468 | ;;******************************************************************* | 462 | ;;******************************************************************* |
| 469 | 463 | ||
| 470 | (defun xml-debug-print (xml) | 464 | (defun xml-debug-print (xml) |
| 471 | (while xml | 465 | (dolist (node xml) |
| 472 | (xml-debug-print-internal (car xml) "") | 466 | (xml-debug-print-internal node ""))) |
| 473 | (set 'xml (cdr xml))) | ||
| 474 | ) | ||
| 475 | 467 | ||
| 476 | (defun xml-debug-print-internal (xml &optional indent-string) | 468 | (defun xml-debug-print-internal (xml indent-string) |
| 477 | "Outputs the XML tree in the current buffer. | 469 | "Outputs the XML tree in the current buffer. |
| 478 | The first line indented with INDENT-STRING." | 470 | The first line indented with INDENT-STRING." |
| 479 | (let ((tree xml) | 471 | (let ((tree xml) |
| 480 | attlist) | 472 | attlist) |
| 481 | (unless indent-string | ||
| 482 | (set 'indent-string "")) | ||
| 483 | |||
| 484 | (insert indent-string "<" (symbol-name (xml-node-name tree))) | 473 | (insert indent-string "<" (symbol-name (xml-node-name tree))) |
| 485 | 474 | ||
| 486 | ;; output the attribute list | 475 | ;; output the attribute list |
| 487 | (set 'attlist (xml-node-attributes tree)) | 476 | (setq attlist (xml-node-attributes tree)) |
| 488 | (while attlist | 477 | (while attlist |
| 489 | (insert " ") | 478 | (insert " ") |
| 490 | (insert (symbol-name (caar attlist)) "=\"" (cdar attlist) "\"") | 479 | (insert (symbol-name (caar attlist)) "=\"" (cdar attlist) "\"") |
| 491 | (set 'attlist (cdr attlist))) | 480 | (setq attlist (cdr attlist))) |
| 492 | 481 | ||
| 493 | (insert ">") | 482 | (insert ">") |
| 494 | 483 | ||
| 495 | (set 'tree (xml-node-children tree)) | 484 | (setq tree (xml-node-children tree)) |
| 496 | 485 | ||
| 497 | ;; output the children | 486 | ;; output the children |
| 498 | (while tree | 487 | (dolist (node tree) |
| 499 | (cond | 488 | (cond |
| 500 | ((listp (car tree)) | 489 | ((listp node) |
| 501 | (insert "\n") | 490 | (insert "\n") |
| 502 | (xml-debug-print-internal (car tree) (concat indent-string " ")) | 491 | (xml-debug-print-internal node (concat indent-string " "))) |
| 503 | ) | 492 | ((stringp node) (insert node)) |
| 504 | ((stringp (car tree)) | ||
| 505 | (insert (car tree)) | ||
| 506 | ) | ||
| 507 | (t | 493 | (t |
| 508 | (error "Invalid XML tree"))) | 494 | (error "Invalid XML tree")))) |
| 509 | (set 'tree (cdr tree)) | ||
| 510 | ) | ||
| 511 | 495 | ||
| 512 | (insert "\n" indent-string | 496 | (insert "\n" indent-string |
| 513 | "</" (symbol-name (xml-node-name xml)) ">") | 497 | "</" (symbol-name (xml-node-name xml)) ">"))) |
| 514 | )) | ||
| 515 | 498 | ||
| 516 | (provide 'xml) | 499 | (provide 'xml) |
| 517 | 500 | ||