;; ;; how to collect the values of specific attributes (in-package :web-user)
20031024
james anderson (c)2003
| [loading] [parsing] [accessor functions] [paths] [combinations] [transformations] |
in addition to the elementary access functions, it is possible to use the xpath module to translate xml path expressions into lisp functions which navigate a document instance graph and operate on matching nodes. this mechanism can be used, for example, to collect those nodes or to change their contents. since the xpath compiler is used in various contexts, its immediate results are a lambda expression. it defines a function which when applied to a target node to return a closure which is called repeatedly to generate the matching nodes. in order to use that, it must be imbedded in an application function and compiled. this is accomplished in two steps. first one defines a utility function to perform the compilation with whatever settings and debugging information might be appropriate
(defun translate-xpath-accessor (string &key trace production pprint) (multiple-value-bind (result index complete) (apply #'xpath-parser string :trace trace (when production (list :start-name production))) (when pprint (pprint result)) (cond (complete result) (t (warn "incomplete parse of xpath expression (@~s): ~s" index string)))))call-with-collector accepts the function result of applying a path function to a target node, repeatedly invokes that function and collects the nodes. it can be used to implement a form which accepts a source node and returns a list of the matching nodes, or to implement a form which binds a set of variables to the designated nodes in specified sources.(?> "//@upc" *dm*), expands to
(XPA::CALL-WITH-COLLECTOR
((LAMBDA (XPA:*CONTEXT-NODE*)
(XPA::APPLY-PATH
(XPA:PATH (XPA:ROOT-STEP)
(XPA:WILD-INFERIOR-STEP)
(XPA:STEP (XPA:ATTRIBUTE)
(XPA:NAME-TEST :NAME (XPA:UNAME :LOCAL-PART "upc"))))
XPA:*CONTEXT-NODE*))
*DM*))
it would be used as follows:((||::|upc| . "123456789") (||::|upc| . "445322344") (||::|upc| . "485672034") (||::|upc| . "132957764"))
(("health" "123456789" "12") ("health" "445322344" "18")
("food" "485672034" "653") ("food" "132957764" "44"))