Fork me on GitHub
#specter
<
2019-01-06
>
zlrth20:01:13

i have some xml:

'({:tag :CategoryName_1, :attrs {}, :content ("cats")}
  {:tag :CategoryId_1, :attrs {}, :content ("cat260062")}
  {:tag :Items,
   :attrs {},
   :content
   ({:tag :ItemId, :attrs {}, :content ("1000388464506500")}
    {:tag :ItemId, :attrs {}, :content ("1000388464506405")})})
that i'd like to turn into into this map:
{:CategoryName_1 "cats", :CategoryId_1 "cat260062", :Items ["1000388464506500" "1000388464506405"]}
that is, for recursive :contents, i'd like them collected into a vector, and for non-recursive, their tags and contents are key value pairs

zlrth20:01:45

the following works, but i'm using glue code to compensate for my lack of specter experience:

(let [top-level-tags [:CategoryName_1 :CategoryId_1]
      xml '({:tag :CategoryName_1, :attrs {}, :content ("cats")}
            {:tag :CategoryId_1, :attrs {}, :content ("cat260062")}
            {:tag :Items,
             :attrs {},
             :content
             ({:tag :ItemId, :attrs {}, :content ("1000388464506500")}
              {:tag :ItemId, :attrs {}, :content ("1000388464506405")})})
      map-by-tags (group-by :tag xml)
      top-level (sp/transform
                  [sp/MAP-VALS]
                  (fn [v] (-> v first :content first))
                  (select-keys map-by-tags top-level-tags))
      Items (sp/select
             [:Items sp/ALL :content sp/ALL :content sp/FIRST]
             map-by-tags)]
  (merge top-level {:Items Items}))

zlrth20:01:15

i didn't find an example in the docs of "collecting a deeper value and putting it upward", but that could be my user error. i would thank you very much for tips!

zlrth22:01:07

ok i have something i'm happier with via cond-path and collect. why is the third element of the :Items vector the complete {:tag :Items ... map?