(in-package :kira) (defun find-element-in-tree (name element) (when (consp element) (if (eq (element-name element) name) element (some (lambda (child) (find-element-in-tree name child)) (rest element))))) (defun find-element-content (name container &optional attribute (type 'string)) (whereas ((element (if name (find name (rest container) :key #'element-name) container)) (string (if attribute (attribute (first element) attribute) (find-if #'stringp (rest element))))) (when (stringp string) (string->type string type)))) (defmacro setf-accessors-from-xml (object xml &rest pairs) (rebinding (object xml) (labels ((expand (field) (cond ((keywordp field) `(find-element-content ,field ,xml)) ((and (symbolp (first field)) (not (keywordp (first field)))) (list* (first field) (mapcar #'expand (rest field)))) (t (destructuring-bind (tag &optional (type 'string)) field (multiple-value-bind (name attribute) (if (consp tag) (values-list tag) (values tag nil)) `(find-element-content ,name ,xml ,attribute ',type))))))) `(setf ,.(loop for (accessor field) on pairs by #'cddr append `((,accessor ,object) ,(expand field)))))))