2013-07-07 1 views
3

Я пытаюсь применить функцию для извлечения содержимого одного тега из xml в коллекции тегов. В принципе, я пытаюсь сделать функцию, которая будет извлекать содержимое из XML, как этотВ Clojure как применять функцию в коллекции

(defn get-events 
[xz] 
(map (juxt 
    #(zf/xml1-> % :title zf/text) 
    #(zf/xml1-> % :performers :performer :name zf/text) 
    #(zf/xml1-> % :start_time zf/text) 
    #(zf/xml1-> % :stop_time zf/text)) 
(zf/xml-> xz :events :event))) 

И мое решение до сих пор выглядит как этот

(ns datamodel 

(:use 
[net.cgrand.enlive-html :as en-html ]) 
(:require 
[clojure.zip :as z] 
[clojure.xml :as xml ] 
[clojure.data.zip.xml :as zf] 
[clojure.java.io :as io] 
)) 


(def data-url "http://api.eventful.com/rest/events/search? app_key=4H4Vff4PdrTGp3vV&keywords=music&location=Belgrade&date=Future") 

(defn xz [url](z/xml-zip (xml/parse url))) 

(defn xml-zipper [& tags](zf/xml-> (xz data-url) tags)) 

(defn func [& tags]#(zf/xml1-> (xml-zipper tags) % zf/text)) 

(def tags [:title :venue_name]) 

и в REPL, когда я пытаюсь применить FUNC к Теги:

(map #((apply comp (reverse(func :events :event))) %) tags) 

Я получаю пустую коллекцию().

ответ

3

Когда def ining tags вы фактически не строите литерал, а вызываете :title с :venue_name в качестве аргумента. Попробуйте объявить tags в виде списка или вектора следующим образом:

(def tags '(:title :venue_name)) ;list 
(def tags [:title :venue_name]) ; vector 

Я предлагаю вам очистить ваш код немного, так как кажется, есть ряд проблем с ним:

  1. Double требование clojure.data.zip.xml.
  2. Дополнительные круглые скобки в определении функции xz.
  3. xz используется как псевдоним для пространства имен и имени функции.
  4. Удалить заключенную скобку func анонимную функцию (#(zf/xml1-> (xml-zipper tags) % zf/text)), вы создаете и звоните, что fn в то же время.

Надеюсь, что это поможет.


EDIT

Я думаю, теперь я получаю то, что вы пытаетесь сделать. Вот рабочая версия для функции генератора селектора: selector. Обратите внимание, что аргумент tag может быть либо одним ключевым словом, либо последовательностью ключевых слов, и в этом случае apply используется при вызове xml1->.

(ns datamodel 
    (:require [clojure.zip :as z] 
      [clojure.xml :as xml] 
      [clojure.data.zip.xml :as zf] 
      [clojure.java.io :as io])) 

(def data-url "http://api.eventful.com/rest/events/search?app_key=4H4Vff4PdrTGp3vV&keywords=music&location=Belgrade&date=Future") 

(defn parse [url] 
    (z/xml-zip (xml/parse url))) 

(defn selector [tag] 
    (if (sequential? tag) 
    #(apply zf/xml1-> % (concat tag [zf/text])) 
    #(zf/xml1-> % tag zf/text))) 

(defn get-events 
    [xml & tags] 
    (let [events (zf/xml-> xml :events :event) 
     fs  (map selector tags)] 
    (map (apply juxt fs) events))) 

(-> data-url 
    parse 
    (get-events :title :start_time [:performers :performer :name] :stop_time) 
    first 
    prn) 
+0

Благодаря хуан, но теперь я получаю java.lang.IllegalArgumentException: Неверное число аргументов (0) передается: DataModel $ $ FUNC Fn :( – Vesna

+0

@Vesna я добавил пункт 4 в списке проблем, которые я думаю, обращается к ошибке, которую вы видите сейчас. –

+0

Я изменил ее, до сих пор не повезло, мне интересно, можно ли создать список функций – Vesna