我找不到示例,也找不到这些函数的文档:find-recursively
find-recursively-if
假设我想在堆栈溢出的首页找到第一个<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-recursively
和find-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"))
最佳答案
这些函数遍历节点树,并在找到所需节点(在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
函数有点尴尬):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")