Subject: 24.1.50; Making url-dav work

From: David Engster <[email-masked]>
Date: Wed, 11 Jul 2012 23:00:09 +0200

I'm trying to simply get a listing from a directory on a WebDAV share
using Emacs. I was overjoyed to see that Emacs ships with url-dav.el,
which seemed to do exactly what I needed. However, it seems that url-dav
depends on a specially patched xml.el for namespace expansion which
apparently never made it into Emacs proper. If you look into
`url-dav-supported-p', it looks for a function `xml-expand-namespace'
which I cannot find anywhere in xml.el's history. At least one other
lone soul faced the same problem and came to the same conclusion (see
http://lists.gnu.org/archive/html/help-gnu-emacs/2011-11/msg00158.html).

Now, xml.el can properly deal with namespaces since 2004 or so, but it
returns the QNames through a cons ("DAV:" . "property"), which is kind
of... cumbersome. The url-dav package naturally expects a plain symbol
'DAV:property.

I started rewriting url-dav to work with the cons's returned by xml.el,
but it's tedious work and, more importantly, makes the code really
ugly. Instead, I now just use a small function to replace the cons's in
xml.el's output with the plain symbols the package expects. Please find
the patch attached.

-David

--- url-dav.el	2012-07-11 22:34:49.401721367 +0200
+++ url-dav.el_patched	2012-07-11 22:33:34.504867729 +0200
@@ -395,10 +395,15 @@
 		 url-http-content-type
 		 (string-match "\\`\\(text\\|application\\)/xml"
 			       url-http-content-type))
-		(setq tree (xml-parse-region (point) (point-max)))))
+		(setq tree (xml-parse-region (point) (point-max) nil nil t))))
 	;; Clean up after ourselves.
 	(kill-buffer buffer)))
 
+    ;; This package was initially written for a different kind of
+    ;; QNAMES expansion, hence we have now to rewrite those so that
+    ;; for example ("DAV:" . "foo") becomes the symbol 'DAV:foo.
+    (url-dav-changexml (car tree))
+
     ;; We should now be
     (if (eq (xml-node-name (car tree)) 'DAV:multistatus)
 	(url-dav-dispatch-node (car tree))
@@ -411,6 +416,21 @@
 	;; nobody but us needs to know the difference.
 	(list (cons url properties))))))
 
+(defun url-dav-changexml (node)
+  "Rewrite all expanded names in NODE to plain symbols.
+That means, all cons produced from `xml-parse-region'
+like (\"DAV:\" .  \"foo\") become plain symbols DAV:foo.
+This replacement happens in-place."
+  (when (consp node)
+    (let ((name (xml-node-name node))
+	  (children (xml-node-children node)))
+      (when (and (consp name)
+		 (equal (car name) "DAV:"))
+	(setcar node (intern (concat "DAV:" (cdr name)))))
+      (when children
+	(dolist (cur children)
+	  (url-dav-changexml cur))))))
+
 (defun url-dav-request (url method tag body
 				 &optional depth headers namespaces)
   "Perform WebDAV operation METHOD on URL.  Return the parsed responses.