August 15, 2019
By: 于壮壮

Clojure XML 转 Json

最近在做微信支付这块,微信接口的都是通过XML来进行数据传输。Clojure中有clojure.data.xml库来让我操作XML格式的数据。 例如:

(require '[clojure.data.xml :as xml])

(def xml-str "<student><name>tom</name><age>18</age></student>")

(xml/parse-str xml-str)

可以看到clojure.data.xml帮我们把繁琐的XML数据格式的转成了一种树形结构。但是依然有冗余的key,像其中的:tag :attrs :content,都增加了我们处理数据的难道。 那可以不可把类似xml的数据格式转成json的数据格式,clojure中对json的处理非常方便的。在网上找到了一篇博客

http://rosario.io/2016/12/26/convert-xml-json-clojure

它是把clojure.data.xml解析的树形结构,通过递归转成json的数据结构,在此基础上我做了一点小改动, 有些细节还有待考虑,不过基本可用。

(require '[clojure.data.xml :as xml])

(defn- same-keys? [content]
  (when content
    (= 1 (count (distinct (map :tag content))))))

(defn xml->json
  "xml转化json"
  [element]
  (cond
    (nil? element) nil
    (string? element) element
    (map? element) (if-not (empty? element)
                     {(:tag element) (xml->json (:content element))}
                     {})
    (sequential? element) (cond
                            (= (count element) 1) (xml->json (first element))
                            (same-keys? element) (mapv #(xml->json (:content %)) element)
                            :else (reduce into {} (map #(xml->json %) element)))
    :else nil))

(defn xml-str->json
  "xml字符串转json"
  [xml-str]
  (let [element (xml/parse (java.io.StringReader. xml-str))]
    (println element)
    (xml->json element)))

举几个列子:

(def xml-str "<student><name>tom</name><age>18</age></student>")

(xml-str->json xml-str)
(def xml-str "<student><name>tom</name><age>18</age><numbers><value>1</value><value>2</value></numbers></student>")

(xml-str->json xml-str)
(def xml-str "<student><name>tom</name><age>18</age><products><item><product_id>1</product_id><product_name>西装</product_name></item><item><product_id>1</product_id><product_name>西裤</product_name></item></products></student>")

(xml-str->json xml-str)
Tags: clojure