3

我对clojure.data.xml有一些问题,因为在解析错误的 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
    (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)
4

1 回答 1

2

我认为您看到的问题与parse. 根据其文档字符串 “解析源,可以是 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对象的惰性序列,如函数的文档字符串中所述event-tree。惰性在于:content记录的字段是在访问字段时实现的。我发现强制实现整个树的一种方法是使用该str函数,这感觉很hacky并且看起来很难看,但是任何有更好想法的人都可以提供更好的解决方案。

(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)))
于 2013-07-26T19:15:25.603 回答