Replaced the base URI kludge in generate-id
authorDavid Lichteblau <david@lichteblau.com>
Sun, 27 Apr 2008 14:34:10 +0000 (27 16:34 +0200)
committerDavid Lichteblau <david@radon.(none)>
Sun, 27 Apr 2008 14:34:10 +0000 (27 16:34 +0200)
xslt.lisp

index d074154..b458159 100644 (file)
--- a/xslt.lisp
+++ b/xslt.lisp
     (cxml:parse s handler)))
 
 (defvar *documents*)
+(defvar *document-ids*)
 
 (defun %document (uri-string base-uri)
   (let* ((absolute-uri
               (xslt-error "cannot find referenced document ~A: ~A"
                           resolved-uri c))))
          (xpath-root-node
-          (or (gethash pathname *documents*)
-              (setf (gethash pathname *documents*)
-                    (make-whitespace-stripper
-                     (handler-case
-                         (parse-allowing-microsoft-bom pathname
-                                                       (stp:make-builder))
-                       ((or file-error cxml:xml-parse-error) (c)
-                         (xslt-error "cannot parse referenced document ~A: ~A"
-                                     pathname c)))
-                     (stylesheet-strip-thunk *stylesheet*))))))
+          (gethash pathname *documents*)))
+    (unless xpath-root-node
+      (setf xpath-root-node
+            (make-whitespace-stripper
+             (handler-case
+                 (parse-allowing-microsoft-bom pathname
+                                               (stp:make-builder))
+               ((or file-error cxml:xml-parse-error) (c)
+                 (xslt-error "cannot parse referenced document ~A: ~A"
+                             pathname c)))
+             (stylesheet-strip-thunk *stylesheet*)))
+     (setf (gethash pathname *documents*) xpath-root-node)
+     (setf (gethash xpath-root-node *document-ids*)
+           (hash-table-count *document-ids*)))
     (when (puri:uri-fragment absolute-uri)
       (xslt-error "use of fragment identifiers in document() not supported"))
     xpath-root-node))
   (when (xpath:node-set-p node)
     (setf node (xpath::textually-first-node node)))
   (when node
-    (let ((id (xpath-sys:get-node-id node))
-          (highest-base-uri
-           (loop
-              for parent = node then next
-              for next = (xpath-protocol:parent-node parent)
-              for this-base-uri = (xpath-protocol:base-uri parent)
-              for highest-base-uri = (if (plusp (length this-base-uri))
-                                         this-base-uri
-                                         highest-base-uri)
-              while next
-              finally (return highest-base-uri))))
-      ;; FIXME: Now that we intern documents, we could use a short ID for
-      ;; the document instead of the base URI.
-      (nreverse (concatenate 'string highest-base-uri "//" id)))))
+    (let ((root (xpath:first-node
+                 (xpath:evaluate (xpath:xpath (:path (:root :node))) node))))
+      (format nil "d~D~A"
+              (or (gethash root *document-ids*) (error "bug!"))
+              (xpath-sys:get-node-id node)))))
 
 (xpath-sys:define-xpath-function/lazy xslt :generate-id (&optional node-set-thunk)
   (if node-set-thunk
     (invoke-with-output-sink
      (lambda ()
        (let* ((*documents* (make-hash-table :test 'equal))
+              (*document-ids* (make-hash-table :test 'equal))
               (xpath:*navigator* (or navigator :default-navigator))
               (puri:*strict-parse* nil)
               (*stylesheet* stylesheet)
                 (stylesheet-strip-thunk stylesheet)))
               (ctx (xpath:make-context xpath-root-node)))
          (when (pathnamep source-designator)
-           (setf (gethash source-designator *documents*) xpath-root-node))
+           (setf (gethash source-designator *documents*) xpath-root-node)
+           (setf (gethash xpath-root-node *document-ids*) 0))
          (map nil
               (lambda (chain)
                 (let ((head (car (variable-chain-definitions chain))))