我正在为一个简单的项目尝试clojure(第一次)。我需要在给定csv文件的情况下更新xml树。我正在逐行读取csv文件,提取一些值,在给定一些值的情况下循环一个节点并插入另一个值的子节点。
我第一次插入项目时效果很好。第二次我得到一个NullPointerException(没有跟踪)。我从insert-child获得的返回值中查找根,并将该根节点传递给下一个循环。不知何故,第二个插入在该根元素上失败。有谁看到这里出了什么问题?或者对这段代码的一般反馈,因为这是我第一次写一些Clojure。
(require 'clojure.string)
(require '[clojure.java.io :as io])
(require '[clojure.xml :as xml])
(require '[clojure.zip :as zip])
(require '[clojure.data.zip.xml :as zf])
(def business-object-config (xml/parse "BusinessObject.config"))
(def zipped (zip/xml-zip business-object-config ))
(defn sql-table-name [table-name]
(second (re-matches #"(.*?)(Base|ExtensionBase|$)" table-name)))
(defn insert-sqlpropertyname-elem [loc name]
(zip/root (zip/insert-child loc {:tag :SqlPropertyName :content [name]})))
(defn get-entity-node [table-name crm-name business-objects]
(first (zf/xml-> business-objects :Entities
:Entity [:CrmName (zf/text= (clojure.string/lower-case (sql-table-name table-name)))]
:EntityItems
:EntityItem [:CrmPropertyName (zf/text= (clojure.string/lower-case crm-name))])))
(defn process-line [line business-objects]
(let [{crm-name 0 table-name 1 sql-name 6} (clojure.string/split line #";")
node (get-entity-node table-name crm-name business-objects)]
(insert-sqlpropertyname-elem node sql-name)))
(defn process-csv []
(with-open
[rdr (io/reader "input.csv")]
(loop [lines (vec (take 5 (rest (line-seq rdr))))
index (dec (count lines))
boc zipped]
(if (neg? index)
boc
(recur lines (dec index) (process-line (nth lines index) boc))))))
(spit "out.xml" (with-out-str (xml/emit (process-csv)) :pad true))
答案 0 :(得分:0)
不那么有用的NPE通常意味着你在某处跑掉树的一侧。
我怀疑你不需要在insert-sqlpropertyname-elem中调用zip/root
。
答案 1 :(得分:0)
好的,我不知道这是不是正确的方法,但是如果我在insert-child的结果上调用root而不是在root上调用xml-zip一切正常。不知道在每次突变后拉链整个结构是否是最佳做法?