2017-06-07 15 views
0

xmlファイルを解析する際に、値を正規化してスワップで保存します!原子に追加私は元の構造を反映するためにツリーを構築します。スワップ!値が解決しない

関数を呼び出すと、データの一部だけが返されますが、正規化された値は返されません。原子を逆変換すると、データは完全に書き込まれます。

ここでコードの部分は、その動作に不可欠であるようです。

(defn normalize-values 
    "Save the dataset to the atom and returns the reference" 
    [tour-id key value] 
    (swap! db assoc-in [tour-id (query-key key :name) value] {:title value}) 
    {key [(query-key key) value]}) 


(defn extract-tags 
    "Differs between unique and normalizable values" 
    [node tour-id] 
    (let [data (zip/xml-zip node) 
     key (:tag node) 
     value (zx/xml1-> data key zx/text) 
     res (if (some #{key} [:sound :map :video :creator]) 
       (normalize-values tour-id key value) 
       {key value})] 
    res)) 

(defn panorama->map 
    "Creates a panorama map from the xml data" 
    [node tour-id] 
    (let [xml-node (zip/node node) 
     tag-values (into {} (map #(extract-tags % tour-id) (:content xml-node)))] 
    (merge tag-values 
      {:id  (get-file-id (:file tag-values)) 
      :hidden (read-string (get-in xml-node [:attrs :hidden]))}))) 


(defn menu->map 
    "Loops over the xml tree and builds the structure" 
    [tour-id menu] 
    (for [entry menu] 
    (let [children (childs-of-child entry)] 
     (if (not-empty children) 
     (let [{:keys [id] :as category-map} (category->map entry)] 
      (swap! db assoc-in [tour-id (query-key :categorie :id) id] category-map) 
      {:loc  [:categories/by-id id] 
      :children (menu->map tour-id children)}) 

     (let [{:keys [id] :as panorama-map} (panorama->map entry tour-id)] 
      (swap! db assoc-in [tour-id (query-key :pano :id) id] panorama-map) 

      {:loc [:panos/by-id id]}))))) 

(defn parse-menu 
    "Starting function which resets the db and saves all data to the atom " 
    [path id] 
    (swap! db dissoc id) 
    (logging/debug "Parse Menu: " path) 

    (let [xml (xml->map path) 
     menu-data (menu->map id (:content xml))] 

    (swap! db assoc-in [id :title] (tour-title xml)) 
    (swap! db assoc-in [id :tree] menu-data) 

    (get @db id))) 

原子は正しく解決されていますか?

+1

正確に何かが間違っているのか、デバッグ中に見たことが分かりますか?また、 'xml-> map'のソースを投稿できますか? –

+2

まれにしか稀にしか怠惰な結果を無効にするには、常に '(vec(for ...))'構造体を使うことをお勧めします。 Tupeloライブラリでは、この目的のために 'forv'を定義しました(clojure.coreの' mapv'に似ています)。 –

+0

ありがとう、vecへのヒントは、ソリューションをもたらした。私は怠けていることも忘れていました。 – DanielderGrosse

答えて

1

forは怠惰なので、生成するシーケンスの要素を理解するまで、体に忍び込んだ副作用はしません。あなたの説明 "私が原子を逆参照すると、データは完全に書き込まれます。"私はあなたがreplでそれを逆参照することを意味していると考えています。その値が表示され、遅延セグが埋め込まれ、副作用が発生します。

0

@ Alan Thompsonがコメントしたように、エラーの原因は遅延評価です。 (for)ループの前に(vec)を追加した後、問題はなくなりました。

(defn menu->map 
    "Loops over the xml tree and builds the structure" 
    [tour-id menu] 

    (vec ;;forcing the evaluation of the loop 

    (for [entry menu] 
    (let [children (childs-of-child entry)] 
     (if (not-empty children) 
     (let [{:keys [id] :as category-map} (category->map entry)] 
      (swap! db assoc-in [tour-id (query-key :categorie :id) id] category-map) 
      {:loc  [:categories/by-id id] 
      :children (menu->map tour-id children)}) 

     (let [{:keys [id] :as panorama-map} (panorama->map entry tour-id)] 
      (swap! db assoc-in [tour-id (query-key :pano :id) id] panorama-map) 

      {:loc [:panos/by-id id]})))))) 
関連する問題