代码之家  ›  专栏  ›  技术社区  ›  Mark Bolusmjak

使用clojure xml拉链返回多个值

  •  4
  • Mark Bolusmjak  · 技术社区  · 16 年前

    假设我们有这样一些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中的示例,我已经找到了如何获取我感兴趣的单个值。

    我想知道如何返回(ce)的成对文本值的列表。

    这里有一些工作代码,但它非常难看。不要求进行琐碎的重构,但Zipper是否提供了更好的方法来实现这一点?

    (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 回复  |  直到 16 年前
        1
  •  4
  •   kotarak    16 年前

    根据您使用的clojure版本,您可能会发现 juxt

    (defn extract-data
      [xml] 
      (let [...]
        (map (juxt getASIN (comp getTitle getAttributes) (comp getAuthor getAttributes)) items))))
    
        2
  •  2
  •   Timothy Pratley    16 年前

    我相信有更好的方法,但这确实有效:

    (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"]))
    
    推荐文章