如何在Clojure中的xml树上组合来自zip-filter查询的结果?

时间:2010-01-13 15:27:12

标签: xml clojure clojure-contrib xml-parsing

我想在xml树上组合三个zip-filter查询的结果。我正在解析的XML看起来像这样:

<someroot>
  <publication>
    <contributors>
      <person_name>
        <surname>Surname A</surname>
      </person_name>
      <person_name>
        <given_name>Given B</given_name>
        <surname>Surname B</surname>
        <suffix>Suffix B</suffix>
      </person_name>
    </contributors>
  </publication>
</someroot>

从此示例中,您可以看到<given_name><suffix>是可选的 - 只需要<surname>。这就是我的问题所在 - 如果我运行三个单独的查询,我得到的答案将会彼此不同:

(xml-> xml :publication :contributors :person_name :given_name text)
(xml-> xml :publication :contributors :person_name :surname text)
(xml-> xml :publication :contributors :person_name :suffix text)

运行这三个查询后,我将留下三个基数不匹配的序列; given_namesuffix的长度为1,而surname的长度为2.这使我无法合并每个名称的组成部分。我需要编写一个查询,在序列构建期间执行此名称连接。

我正在查看clojure.contrib.zip-filter.xml的非常稀疏的文档,并且无法弄清楚我是如何做到的(或者如果可能的话)。不幸的是,我是一个Clojure(和Lisp)的新手!任何人都可以指出我如何编写一个将连接其他三个嵌入式查询的查询?

2 个答案:

答案 0 :(得分:6)

您可以一步获取所有人物子树(xml-&gt; xmlzip:publication:contributors:person_name)然后获取名称部分(如果它们存在)(xml1-&gt; personzip:surname文本)并将它们组合到结果中你想这样:

(use 'clojure.contrib.zip-filter.xml)
(defn format-name
  [surname given suffix]
  (str surname (if given (str ", " given)) (if suffix (str ", " suffix))))
(defn get-names
  [xz] 
  (map (juxt 
         #(xml1-> % :surname text) 
         #(xml1-> % :given_name text) 
         #(xml1-> % :suffix text))
     (xml-> xz :publication :contributors :person_name)))
(let [x (clojure.zip/xml-zip (clojure.xml/parse "foo.xml"))] 
  (map (partial apply format-name) (get-names x)))

结果(“姓氏A”“姓氏B,给定B,后缀B”)

答案 1 :(得分:2)

我认为另一种解决方案是

(xml-> xml :publication :contributors :person_name)

然后稍后处理每个<person_name>