From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: mah@everybody.org (Mark A. Hershberger) Newsgroups: gmane.emacs.bugs Subject: Re: Adding namespace support to xml.el Date: Thu, 12 Jun 2003 13:28:35 -0500 Sender: bug-gnu-emacs-bounces+gnu-bug-gnu-emacs=m.gmane.org@gnu.org Message-ID: <87u1avnoa4.fsf@superman.everybody.org> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: main.gmane.org 1055442576 28821 80.91.224.249 (12 Jun 2003 18:29:36 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Thu, 12 Jun 2003 18:29:36 +0000 (UTC) Cc: "Jose M. Vidal" Original-X-From: bug-gnu-emacs-bounces+gnu-bug-gnu-emacs=m.gmane.org@gnu.org Thu Jun 12 20:29:31 2003 Return-path: Original-Received: from monty-python.gnu.org ([199.232.76.173]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 19QWpG-0007U6-00 for ; Thu, 12 Jun 2003 20:29:30 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.20) id 19QWpB-0006M7-1i for gnu-bug-gnu-emacs@m.gmane.org; Thu, 12 Jun 2003 14:29:25 -0400 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.20) id 19QWp8-0006Lq-St for bug-gnu-emacs@gnu.org; Thu, 12 Jun 2003 14:29:22 -0400 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.20) id 19QWp7-0006LO-7y for bug-gnu-emacs@gnu.org; Thu, 12 Jun 2003 14:29:22 -0400 Original-Received: from superman.everybody.org ([66.93.249.201]) by monty-python.gnu.org with esmtp (Exim 4.20) id 19QWoS-0006Aa-0P for bug-gnu-emacs@gnu.org; Thu, 12 Jun 2003 14:28:40 -0400 Original-Received: from mah by superman.everybody.org with local (Exim 3.35 #1 (Debian)) id 19QWoN-0001aD-00; Thu, 12 Jun 2003 13:28:35 -0500 Original-To: bug-gnu-emacs@gnu.org X-URL: http://mah.everybody.org/weblog/ User-Agent: Gnus/5.1002 (Gnus v5.10.2) Emacs/21.2 (gnu/linux) Original-cc: Emmanuel Briot X-BeenThere: bug-gnu-emacs@gnu.org X-Mailman-Version: 2.1b5 Precedence: list List-Id: Bug reports for GNU Emacs, the Swiss army knife of text editors List-Help: List-Post: List-Subscribe: , List-Archive: List-Unsubscribe: , Errors-To: bug-gnu-emacs-bounces+gnu-bug-gnu-emacs=m.gmane.org@gnu.org Xref: main.gmane.org gmane.emacs.bugs:5290 X-Report-Spam: http://spam.gmane.org/gmane.emacs.bugs:5290 Here is a cleaned up copy of the patch. I took out a couple of irrelevant changes and added "-b" so it'd be easier to see the actual differences. Also fixed a comment and docstring or two. --- xml.el 30 May 2003 16:02:26 -0000 1.21 +++ xml.el 12 Jun 2003 18:24:30 -0000 @@ -121,11 +121,12 @@ ;;******************************************************************* ;;;###autoload -(defun xml-parse-file (file &optional parse-dtd) +(defun xml-parse-file (file &optional parse-dtd parse-ns) "Parse the well-formed XML file FILE. If FILE is already visited, use its buffer and don't kill it. Returns the top node with all its children. -If PARSE-DTD is non-nil, the DTD is parsed rather than skipped." +If PARSE-DTD is non-nil, the DTD is parsed rather than skipped. +If PARSE-NS is non-nil, then QNAMES are expanded." (let ((keep)) (if (get-file-buffer file) (progn @@ -137,7 +138,7 @@ (let ((xml (xml-parse-region (point-min) (point-max) (current-buffer) - parse-dtd))) + parse-dtd parse-ns))) (if keep (goto-char keep) (kill-buffer (current-buffer))) @@ -184,13 +185,14 @@ ;; prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? ;;;###autoload -(defun xml-parse-region (beg end &optional buffer parse-dtd) +(defun xml-parse-region (beg end &optional buffer parse-dtd parse-ns) "Parse the region from BEG to END in BUFFER. If BUFFER is nil, it defaults to the current buffer. Returns the XML list for the region, or raises an error if the region -is not a well-formed XML file. +is not well-formed XML. If PARSE-DTD is non-nil, the DTD is parsed rather than skipped, -and returned as the first element of the list." +and returned as the first element of the list. +If PARSE-NS is non-nil, then QNAMES are expanded." (save-restriction (narrow-to-region beg end) ;; Use fixed syntax table to ensure regexp char classes and syntax @@ -209,7 +211,7 @@ (if xml ;; translation of rule [1] of XML specifications (error "XML files can have only one toplevel tag") - (setq result (xml-parse-tag parse-dtd)) + (setq result (xml-parse-tag parse-dtd parse-ns)) (cond ((null result)) ((listp (car result)) @@ -224,21 +226,28 @@ (nreverse xml))))))) -(defun xml-parse-tag (&optional parse-dtd) +(defun xml-parse-tag (&optional parse-dtd parse-ns) "Parse the tag at point. If PARSE-DTD is non-nil, the DTD of the document, if any, is parsed and returned as the first element in the list. +If PARSE-NS is non-nil, then QNAMES are expanded. Returns one of: - a list : the matching node - nil : the point is not looking at a tag. - a pair : the first element is the DTD, the second is the node." + (let ((xml-ns (if (consp parse-ns) + parse-ns + (if parse-ns + (list + (cons "" "") + (cons "xmlns" "http://www.w3.org/2000/xmlns/")))))) (cond ;; Processing instructions (like the tag at the ;; beginning of a document). ((looking-at "<\\?") (search-forward "?>") (skip-syntax-forward " ") - (xml-parse-tag parse-dtd)) + (xml-parse-tag parse-dtd xml-ns)) ;; Character data (CDATA) sections, in which no tag should be interpreted ((looking-at "") @@ -270,6 +279,48 @@ (children (list (xml-parse-attlist) (intern node-name))) pos) + ;; add the xmlns:* attrs to our cache + (when (consp xml-ns) + (mapcar + (lambda (attr) + (let* ((splitup (split-string (symbol-name (car attr)) ":")) + (prefix (nth 0 splitup)) + (lname (nth 1 splitup))) + (when (string= "xmlns" prefix) + (setq xml-ns (append (list (cons (if lname + lname + "") + (cdr attr))) + xml-ns))))) + (car children)) + + ;; expand element names + (let* ((splitup (split-string (symbol-name (cadr children)) ":")) + (lname (or (nth 1 splitup) + (nth 0 splitup))) + (prefix (if (nth 1 splitup) + (nth 0 splitup) + ""))) + (setcdr children (list + (intern (concat "{" + (cdr (assoc-string prefix xml-ns)) + "}" lname))))) + + ;; expand attribute names + (mapcar + (lambda (attr) + (let* ((splitup (split-string (symbol-name (car attr)) ":")) + (lname (or (nth 1 splitup) + (nth 0 splitup))) + (prefix (if (nth 1 splitup) + (nth 0 splitup) + (caar xml-ns)))) + + (setcar attr (intern (concat "{" + (cdr (assoc-string prefix xml-ns)) + "}" lname))))) + (car children))) + ;; is this an empty element ? (if (looking-at "/>") (progn @@ -289,7 +340,7 @@ (error "XML: Invalid end tag (expecting %s) at pos %d" node-name (point))) ((= (char-after) ?<) - (let ((tag (xml-parse-tag))) + (let ((tag (xml-parse-tag nil xml-ns))) (when tag (push tag children)))) (t @@ -321,7 +372,7 @@ ;; This was an invalid start tag (error "XML: Invalid attribute list"))))) (t ;; This is not a tag. - (error "XML: Invalid character")))) + (error "XML: Invalid character"))))) (defun xml-parse-attlist () "Return the attribute-list after point.