clojure.xml / parse:混合内容中忽略的仅限空白的文本节点

时间:2011-07-05 02:06:22

标签: xml clojure

我是clojure.xml的新手,以及一般的Java XML库。

我对clojure.xml / parse的输出感到惊讶。仅由空格构成的文本节点将被忽略。如果有一个DOCTYPE声明表明该元素不能具有PCDATA,但是在没有DOCTYPES且的情况下即使在混合内容节点中也没有丢弃空白,那么在仅元素节点中这可能是正确的。忽略了空白。

test.clj:

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

(prn (x/parse "test.xml"))

的test.xml:

<?xml version="1.0"?>
<x>

<y><z>AAA</z> BBB <z>AAA</z> <z>AAA</z></y>

</x>

输出(<z>AAA</z><z>AAA</z>之间缺少文本节点):

{:tag :x, :attrs {:xml:space "preserve"}, :content
  [{:tag :y, :attrs nil, :content
    [{:tag :z, :attrs nil, :content ["AAA"]}
     " BBB "
     {:tag :z, :attrs nil, :content ["AAA"]}
     {:tag :z, :attrs nil, :content ["AAA"]}]}]}

我正在使用Clojure 1.2.0。这是一个错误,还是以某种方式应该如何表现? (即使添加xml:space =“preserve”属性也不起作用。)

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

这不是一个错误。我将重新排列test.xml文件,使其看起来像test.clj的输出:

<?xml version="1.0"?>
<x>

  <y>
    <z>AAA</z>
    BBB
    <z>AAA</z>
    <z>AAA</z>
  </y>

</x>

在此文件中,'x'是一个根元素,其中包含'y'元素,其中包含'z'元素,“BBB”作为字符串。您可以查看xml specification有关xml文件的逻辑结构。

回到基于事件驱动系统的Clojure,Clojure uses SAX parser。如果您熟悉java(如果不熟悉的话),请尝试使用"Sample SAX2 application"

这是“Sample SAX2 application”的输出,其中test.xml作为参数:

Start document
Start element: x
Characters:    "\n\n"
Start element: y
Start element: z
Characters:    "AAA"
End element: z
Characters:    " BBB "
Start element: z
Characters:    "AAA"
End element: z
Characters:    " "
Start element: z
Characters:    "AAA"
End element: z
End element: y
Characters:    "\n\n"
End element: x
End document

你的test.clj输出的副本:

{:tag :x, :attrs {:xml:space "preserve"}, :content
  [{:tag :y, :attrs nil, :content
    [{:tag :z, :attrs nil, :content ["AAA"]}
     " BBB "
     {:tag :z, :attrs nil, :content ["AAA"]}
     {:tag :z, :attrs nil, :content ["AAA"]}]}]}

可以看出clojure.xml/parse(来自test.clj输出)只是从xml文档中删除'\ n'(\ newline)和''(\ space)elements但其他元素是相同。如果您对删除元素的原因感兴趣,可以查看clojure.xml/content-handler来源并查看push-chars函数:

push-chars (fn []
             (when (and (= *state* :chars)
                        (some (complement #(Character/isWhitespace (char %))) (str *sb*)))
               (set! *current* (push-content *current* (str *sb*)))))

user> (map (complement #(Character/isWhitespace (char %))) [\newline \space \a])
(false false true)

更新:如果你想保留空格,试着安排像这样的xml文件。 (对我而言,它有效):

<?xml version="1.0" ?>
<x>

<y xml:space="preserve"><z>AAA</z> BBB <z>AAA</z> <z>AAA</z></y>

</x>