如何使用cxml-stp的find-recursively和find-recursively-if

时间:2013-11-25 22:23:08

标签: xml lisp common-lisp

我找不到示例,无法弄清楚这些功能的文档:

说我想在Stack Overflow的首页找到第一个<div class="summary">。我可以这样得到HTML树:

(defun get-page (url)
  "Get STP(DOM alternative) representation of page"
  (chtml:parse
   (drakma:http-request url)
   (cxml-stp:make-builder)))

(get-page "http://stackoverflow.com")

但是,从这里开始,我只是不知道find-recursivelyfind-recursively-if应该是什么样的真实参数。

修改:使用<div class="summary">在SO的首页找到第一个find-recursively-if的解决方案:

(cxml-stp:find-recursively-if
 (lambda (node)
   (and (typep node 'cxml-stp:element)
    (equal (stp:local-name node) "div")
    (equal (stp:attribute-value node "class") "summary")))
 (get-page "http://stackoverflow.com"))

1 个答案:

答案 0 :(得分:1)

当您找到所需节点(在find-recursively的情况下)或满足谓词的节点(在find-recursively-if的情况下)时,这些函数遍历节点树并返回。谓词应该对节点做一些事情,但可能是任意的。例如,这是一种返回第10个节点的方法(通过使用将在其第10次调用时返回true的谓词):

;; return the 10th node
(let ((x 0))
  (cxml-stp:find-recursively-if 
   (lambda (node)
     (= (incf x) 10))
   (get-page "http://stackoverflow.com")))

作为一个更现实的例子,以下是如何检索具有本地名称"title"的元素(请注意,您只能在local-name上使用elements,而不能在node上使用:key 1}} s,所以CL-USER> (cxml-stp:find-recursively "title" (get-page "http://stackoverflow.com") :key (lambda (node) (if (typep node 'cxml-stp:element) (cxml-stp:local-name node) "")) :test 'string-equal) ;=> ;#.(CXML-STP:ELEMENT ; #| :PARENT of type ELEMENT |# ; :CHILDREN '(#.(CXML-STP:TEXT ; #| :PARENT of type ELEMENT |# ; :DATA "Stack Overflow")) ; :LOCAL-NAME "title" ; :NAMESPACE-URI "http://www.w3.org/1999/xhtml") 函数有点尴尬):

{{1}}