【问题标题】:clojure.xml/parse: Whitespace-only text nodes ignored in mixed contentclojure.xml/parse:混合内容中忽略的纯空格文本节点
【发布时间】:2011-07-05 02:06:22
【问题描述】:

我是 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>

输出(&lt;z&gt;AAA&lt;/z&gt;&lt;z&gt;AAA&lt;/z&gt; 之间缺少文本节点):

{: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" 属性也不起作用。)

感谢您的帮助!

【问题讨论】:

    标签: xml clojure


    【解决方案1】:

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

    <?xml version="1.0"?>
    <x>
    
      <y>
        <z>AAA</z>
        BBB
        <z>AAA</z>
        <z>AAA</z>
      </y>
    
    </x>
    

    在这个文件中,“x”是一个根元素,它包含“y”元素,“y”元素包含“z”元素和“BBB”作为字符串。 xml文件的逻辑结构可以看xml specification

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

    这是“示例 SAX2 应用程序”的输出,其中 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>
    

    【讨论】:

    • 非常感谢。虽然我仍然想知道 clojure.xml 是否通过从混合内容中去除空白节点来遵守 XML 标准,并且不可接受将 xml:space 添加到每个混合内容节点,但您给了我精确位置问题出在哪里,太好了!注释掉 (some (complement ...)) 表单会保留空格!万岁!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多