2010-01-13 55 views
8

我想在xml树上结合三个zip-filter查询的结果。我解析XML看起来是这样的:如何在Clojure的xml树上合并来自zip-filter查询的结果?

<someroot> 
    <publication> 
    <contributors> 
     <person_name> 
     <surname>Surname A</surname> 
     </person_name> 
     <person_name> 
     <given_name>Given B</given_name> 
     <surname>Surname B</surname> 
     <suffix>Suffix B</suffix> 
     </person_name> 
    </contributors> 
    </publication> 
</someroot> 

从这个例子可以看出,<given_name><suffix>是可选的 - 只有<surname>是必需的。就在于此我的问题 - 如果我运行三个单独的查询,我得到的答复会出失衡与对方:

(xml-> xml :publication :contributors :person_name :given_name text) 
(xml-> xml :publication :contributors :person_name :surname text) 
(xml-> xml :publication :contributors :person_name :suffix text) 

运行这三个疑问我将会留下它的基数不匹配的三个序列之后; given_namesuffix的长度为1,而surname的长度为2.这使得我无法合并每个名称的组件。我需要编写一个将在序列构建过程中执行此名称连接的查询。

我正在查看clojure.contrib.zip-filter.xml的非常稀疏的文档,无法弄清楚我可以如何做到这一点(或者甚至可能)。不幸的是,我是Clojure(和Lisp)新手!任何人都可以指出我可以写一个将连接其他三个嵌入式查询的查询吗?

+1

检查最近这次SO问出:http://stackoverflow.com/questions/2034550 /返回-多值 - 使用 - 的Clojure-XML的拉链 – 2010-01-13 23:46:43

回答

6

您可以一步获取所有人员子树(xml-> xmlzip:publication:contributors:person_name),然后获取名称部分(xml1-> personzip:surname text)并将它们结合到您的结果中希望像这样:

(use 'clojure.contrib.zip-filter.xml) 
(defn format-name 
    [surname given suffix] 
    (str surname (if given (str ", " given)) (if suffix (str ", " suffix)))) 
(defn get-names 
    [xz] 
    (map (juxt 
     #(xml1-> % :surname text) 
     #(xml1-> % :given_name text) 
     #(xml1-> % :suffix text)) 
    (xml-> xz :publication :contributors :person_name))) 
(let [x (clojure.zip/xml-zip (clojure.xml/parse "foo.xml"))] 
    (map (partial apply format-name) (get-names x))) 

结果( “姓A” “姓B,鉴于B,后缀B”)

2

我假设一个替代解决方案是

(xml-> xml :publication :contributors :person_name) 

再后来就处理每个<person_name>