首先,我对LISP真的很陌生,我试图感受这种语言。
让我们使用以下代码(我使用closure-html和cxml-stop):
(defparameter *document*
(cxml:parse "<test a='1' b='2' xmlns:foo='http://foo'>
<child>hello world</child>
<mommy>hello</mommy>
<father>world</father>
<child>hello world2</child>
<mommy>hello2</mommy>
<father>world2</father>
<child>hello world3</child>
<mommy>hello3</mommy>
<father>world3</father>
<foo:child>bar</foo:child>
</test>"
(stp:make-builder)))
如何获取followind输出:
Child: hello world
Mommy: hello
Father: world
Child: hello world2
Mommy: hello2
Father: world2
Child: hello world3
Mommy: hello3
Father: world3
我已经能够按顺序凝胶所有的Childs,然后按顺序凝胶所有的Mommys,然后是所有的父亲。
但是我现在无法按照它们出现的顺序获取节点。
任何想法?
提前致谢:)
答案 0 :(得分:0)
我不知道LISP,但是如果你正在寻找XPath表达式来获取test元素中的所有child,mommy和father元素,你可以使用它:
/test/*[name()='child' or name()='father' or name()='mommy']
上面的表达式意味着选择元素名称等于'child'或'father'或'mommy'的<test>
的所有子元素。这将返回所有匹配的元素,以便它们以XML格式显示。假设您知道如何在LISP中调用XPath表达式,那么上面的XPath应该会让您知道如何实现该要求。
答案 1 :(得分:0)
首先,我不太了解XML部分,而且我不熟悉cxml的API。
据我了解,问题是将stp:of-name包装成允许按多个名称搜索的东西。
一种解决方案是实现函数of-names
:
(defun of-names (&rest names)
#'(lambda (ch)
(some #'(lambda (n)
(funcall (stp:of-name n) ch)) names)))
另一个解决方案是实现更高阶or
&#39;,i。即编写or
的包装器,它将接受一个参数的多个函数并返回or
个值的函数:
(defun f-or (&rest funs)
#'(lambda (x)
(dolist (f funs)
(let ((y (funcall f x)))
(when y
(return y))))))
现在两种形式
(let ((name-text (mapcar #'(lambda (e)
(list (stp:local-name e)
(stp:data (first (stp:list-children e)))))
(stp:filter-children (f-or (stp:of-name "child")
(stp:of-name "mommy")
(stp:of-name "father"))
(first (stp:list-children *document*))))))
(format nil "~{~{~@(~A~): ~A~}~^~%~}" name-text))
(let ((name-text (mapcar #'(lambda (e)
(list (stp:local-name e)
(stp:data (first (stp:list-children e)))))
(stp:filter-children (of-names "child" "mommy" "father")
(first (stp:list-children *document*))))))
(format nil "~{~{~@(~A~): ~A~}~^~%~}" name-text))
产生字符串
"Child: hello world
Mommy: hello
Father: world
Child: hello world2
Mommy: hello2
Father: world2
Child: hello world3
Mommy: hello3
Father: world3"