2013-07-26 144 views
3

我有與該clojure.data.xml一些問題解析XML不好時,拋出的異常沒有被捕獲。我發現了一些可能與運行時包裝有關的問題,但是我解開它的嘗試並未成功,任何人都可以向我指出爲什麼會發生這種情況?Clojure的異常處理

(defn parse-xml-from-string 
    "takes in valid xml as a string and turns it into 
    #clojure.data.xml data, if bad xml returns false" 
    [xml] 
    (try 
    (do (parse (java.io.StringReader. xml))) 
    (catch javax.xml.stream.XMLStreamException e false) 
    (catch Exception ex 
     (cond (isa? (class (.getCause ex)) javax.xml.stream.XMLStreamException) false)))) 

方法調用

(viva-api.helpers.validation/parse-xml-from-string "<?xml version=\"1.0\"encoding=\"UTF-8\"?><foo><bar><baz>The baz value</baz></bar></foos>") 

輸出

#clojure.data.xml.Element{:tag :foo, :attrs {}, :content (user=> XMLStreamException ParseError at [row,col]:[1,84] 
Message: The end-tag for element type "foo" must end with a '>' delimiter. com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next (XMLStreamReaderImpl.java:598) 
+0

你爲什麼試圖捕捉異常兩次?此外,(do)塊在內部只有一個表達式時不是必需的。編輯爲 –

+0

以顯示輸入/輸出。兩次捕獲的原因是爲了展示我發現的可能解決方案。 – ChadJPetersen

回答

2

我認爲你所看到的問題與由parse返回值的懶惰。據其docstring「解析源,它可以是一個InputStream或Reader,以及回報的元素記錄的懶漢樹。[...]」

(ns xml 
    (:use clojure.data.xml)) 

(defn parse-xml-from-string 
    "takes in valid xml as a string and turns it into 
    #clojure.data.xml data, if bad xml returns false" 
    [xml] 
    (try 
    (parse (java.io.StringReader. xml)) 
    (catch javax.xml.stream.XMLStreamException ex 
     false))) 

(parse-xml-from-string "<bla/>") ;= #clojure.data.xml.Element{:tag :bla, :attrs {}, :content()} 

(parse-xml-from-string "<bla") ;= false 

(parse-xml-from-string "<bla>") ; throws XMLStreamException 

(def x (parse-xml-from-string "<bla>")) ; doesn't throw an exception unless it's evaluated 

x ; throws XMLStreamException 

編輯

parse返回的值是一個懶惰的樹建造從Element記錄自上而下和基於Event對象的懶惰序列,如docstring的提及功能event-tree功能。懶惰在於該字段被訪問時實現的記錄的:content字段。我發現強制實現整棵樹的一種方法是使用str函數,這感覺很難看,看起來很醜,但任何有更好想法的人都可以提供更好的解決方案。

(defn parse-xml-from-string 
    "takes in valid xml as a string and turns it into 
    #clojure.data.xml data, if bad xml returns false" 
    [xml] 
    (try 
    (let [x (parse-str xml)] 
     (str x) 
     x) 
    (catch javax.xml.stream.XMLStreamException ex 
     false))) 

這似乎是要竭盡全力避免懶惰是,據我瞭解,主要的原因之一來使用clojure.data.xml。由於您似乎希望一次解析您的整個XML字符串,可能clojure.xml/parse函數更適合您的需求。

(defn my-parse-str 
    [s] 
    (try 
    (xml/parse (java.io.ByteArrayInputStream. (.getBytes s))) 
    (catch Exception e false))) 
+0

在這種情況下,他應該用doall取代他的做法。 –

+0

with doall我得到這個輸出 XMLStreamException [row,col]處的ParseError:[1,84] 消息:元素類型「foo」的結束標記必須以'>'定界符結束。 com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:598) #clojure.data.xml.Element {:標籤:FOO,:ATTRS {},:內容(用戶=> – ChadJPetersen

+1

@ user1944838我使用'doall'嘗試,但它不工作,用'parse'返回的數據結構不是一個簡單的懶惰序列。 –