Возврат нескольких значений с использованием Clojure XML Zipper - PullRequest
4 голосов
/ 09 января 2010

Предположим, у нас есть какой-то XML-код:

<a>
  <b>
    <c>text</c>
    <d>
      <e>text</e>
      <f>
        ... lots of cruft here ..
      </f>
    </d>
  </b>
  <b>
    ...
  </b>
  <!-- more b sub-trees --> 
</a>

Теперь, просматривая примеры в zip_filter / xml.clj, я выяснил, как получить отдельные значения, которые меня интересуют.

Мне интересно, как бы я мог сделать что-то вроде возврата списка пар текстовых значений (c e).

EDIT:

Вот некоторый рабочий код, но он довольно уродливый. Не требуя тривиального рефакторинга, но есть ли более хороший способ, которым молнии дают нам сделать это?

(defn extract-data [xml] 
  (let [items (x/xml-> xml zf/descendants :Item)     ;items not top-level
        getAttributes  #(x/xml1-> % :ItemAttributes) ;items have itemattributes
        getASIN        #(x/xml1-> % :ASIN x/text)    ;items have ASINs
        getTitle       #(x/xml1-> % :Title x/text)   ;itemattributes have Titles
        getAuthor      #(x/xml1-> % :Author x/text)] ;itemattributes have Authors
    (map 
       ;build a function to get everything we need from the items, and apply
      #(let [attributes (getAttributes %)] ;get the attributes, we'll use it twice
         (list 
           (getASIN %) 
           (getTitle attributes) 
           (getAuthor attributes)))
      items)))

Ответы [ 2 ]

4 голосов
/ 11 января 2010

В зависимости от используемой вами версии clojure функция juxt может оказаться полезной. Ваш опубликованный код (только соответствующие части):

(defn extract-data
  [xml] 
  (let [...]
    (map (juxt getASIN (comp getTitle getAttributes) (comp getAuthor getAttributes)) items))))
2 голосов
/ 11 января 2010

Я уверен, что есть более хороший способ, но это делает работу:

(letfn [(get-tag [tag coll] (:content (first (filter #(= tag (:tag %)) coll))))]
  (map #(list (get-tag :c %) (get-tag :e (get-tag :d %)))
       (map :content (:content (clojure.xml/parse "foo.xml")))))

результаты в

((["ctext1"] ["etext1"]) (["ctext2"] ["etext2"]))
...