2010-01-13 60 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>