/ traversal /
/traversal/xmls.lisp
 1 ;;; WARNING: This conflicts with lhtml.
 2 (in-package #:oh-ducks.traversal)
 3 
 4 (defvar *xmls-family-tree* nil)
 5 
 6 (defun in-hash (key hash)
 7   (multiple-value-bind (val present-p) (gethash key hash)
 8     (declare (ignore val))
 9     present-p))
10 
11 (defun %mark-parents (parent children)
12   (dolist (item children)
13     (setf (gethash item *xmls-family-tree*) parent)
14     (%mark-parents item (element-children item))))
15 
16 ;; WARNING: This won't produce sane results for nested (match)es, because we
17 ;;          have no way to bind in a large enough scope.
18 (defmethod unify:unify ((template oh-ducks::css-selector-template)
19                         (element list)
20                         &optional (env (unify:make-empty-environment))
21                         &key)
22   (if (and *xmls-family-tree*
23 	   (in-hash element *xmls-family-tree*))
24       (call-next-method)
25       (let ((*xmls-family-tree* (make-hash-table :test 'eq)))
26         (%mark-parents nil (list element))
27         (%mark-parents element (element-children element))
28         (call-next-method))))
29 
30 (defmethod unify:unify ((document list) (template oh-ducks::css-selector-template)
31                         &optional (env (unify:make-empty-environment))
32                         &key)
33   (unify:unify template document env))
34 
35 ;;; general accessors
36 
37 (defmethod element-children ((element list))
38   (remove-if-not (lambda (x) (and (listp x) (stringp (car x))))
39                  (cddr element)))
40 
41 (defmethod element-parent ((element list))
42   (multiple-value-bind (parent present?)
43       (gethash element *xmls-family-tree*)
44     (if present?
45         parent
46         (error "unable to determine parent"))))
47 
48 #+(or)
49 (defmethod element-attribute ((attribute symbol) (element list))
50   (cadr (assoc attribute (cadr element))))
51 (defmethod element-attribute ((attribute string) (element list))
52   (cadr (assoc attribute (cadr element) :test #'string=)))
53 
54 (defmethod element-type ((element list))
55   (car element))
56 
57 (defmethod element-content ((element list))
58   (cddr element))