2012-05-30 5 views
2

간단한 프로젝트에서 clojure (처음으로)를 사용하고 있습니다. csv 파일이 주어진 xml 트리를 업데이트해야합니다. CSV 파일을 한 줄씩 읽고, 값을 추출하고, 주어진 값의 노드를 반복하고 다른 값을 가진 자식 노드를 삽입합니다.Clojure에서 XML 문서에 여러 개의 변이가 발생했습니다.

처음 항목을 삽입 할 때 제대로 작동합니다. 두 번째로 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

별로 도움이되지 않는 NPE는 일반적으로 어딘가에서 나무의면을 벗어 났음을 의미합니다.

insert-sqlpropertyname-elem에 zip/root을 호출 할 필요가 없다고 생각됩니다.

+0

문제는 insert-child 함수의 반환 값과 관련이 있습니다. 구조체에서 zip/root를 호출하지 않고 get-entity-node 함수를 사용하여 쿼리를 수행하면 nil을 반환합니다. zip/root를 호출하면 NPE를 얻습니다. 따라서 insert-child의 반환 값은 원래 지퍼 트리와 다른 데이터 구조입니다. 좀 더 정확히 말하자면, insert-child에서 반환되는 데이터 구조를 xml->로 쿼리 할 수있는 데이터 형식으로 변환하는 방법은 무엇입니까? – Jeroen

+0

'(반복 행 (dec 인덱스) (프로세스 행 (n 번째 행 인덱스) boc))'(행 (프로세스 행 (n 번째 행 인덱스) boc) (반복 행 (dec 인덱스) boc) ' – Ankur

0

그래, 내가 올바른 방법인지는 모르겠지만, 내가 insert-child의 결과에 root를 호출하고 루트에서 xml-zip을 호출하면 모든 것이 잘 동작한다. 모든 돌연변이 이후에 전체 구조물을 지퍼로 만드는 것이 가장 좋은 방법인지는 모르겠다.

관련 문제