;;;; type-defines-accessors ;;;; Under this implementation strategy, elements would need only implement ;;;; accessors for traversing the node graph. (in-package #:oh-ducks.traversal) ;;; general accessors (defgeneric element-children (element) (:documentation "Returns a sequence of element's child tags.")) (defgeneric element-parent (element) (:documentation "Returns element's parent element.")) (defgeneric element-attribute (attribute element) (:documentation "Returns the value of the attribute of element, or nil if no such attribute exists.")) (defgeneric element-type (element) (:documentation "Returns the tag name (type) of element.")) (defgeneric element-content (element) (:documentation "Returns a string containing the contents of the element, if it contains only textual nodes, or a sequence containing all of the element's child nodes (textual nodes as strings, tag nodes as whatever they'd be under #'element-children).") (:method :around ((element t)) (let ((val (call-next-method))) (if (every #'stringp val) (reduce (curry #'concatenate 'string) val) val)))) ;;; special accessors in case something special needs to happen (defgeneric element-id (element) (:documentation "Equivalent in spirit to (element-attribute :id element).") (:method (element) (element-attribute :id element))) (defgeneric element-classes (element) (:documentation "Equivalent in spirit to (element-attribute :class element), except it returns a sequence of individual classes.") (:method (element) (split-sequence:split-sequence #\Space (element-attribute :class element) :remove-empty-subseqs t))) (defgeneric element-type-equal (element type) (:documentation "Equivalent in spirit to (string-equal (element-type element) type), but not obligated to work under the assumption of string-designators.") (:method (element type) (string-equal type (element-type element)))) (defgeneric element-ancestors (element) (:documentation "The result of calling element-parent repeatedly up the document tree.") (:method (element) (let ((parent (element-parent element))) (when parent (cons parent (element-ancestors parent))))))