使用Clojure删除特定的XML节点 [英] Remove specific XML nodes using Clojure

查看:64
本文介绍了使用Clojure删除特定的XML节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下XML结构:

I have the following XML structure:

(def xmlstr
"<ROOT>
  <Items>
    <Item><Type>A</Type><Note>AA</Note></Item>
    <Item><Type>B</Type><Note>BB</Note></Item>
    <Item><Type>C</Type><Note>CC</Note></Item>
    <Item><Type>A</Type><Note>AA</Note></Item>
  </Items>
</ROOT>")

在其中要删除任何具有B型或C型的项目。结果应为类似:

where I want to remove any Item, if it has a Type B or C. The result should be something like:

<ROOT>
  <Items>
    <Item><Type>A</Type><Note>AA</Note></Item>
    <Item><Type>A</Type><Note>AA</Note></Item>
  </Items>
</ROOT>

我发现使用data.xml和data.xml.zip查询此类结构非常简单,例如:

I've found it pretty trivial to query such structures using data.xml and data.xml.zip, e.g:

;; lein try org.clojure/data.xml org.clojure/data.zip
(def xmldoc (clojure.data.xml/parse-str xmlstr))
(def zipxml (clojure.zip/xml-zip xmldoc))

(clojure.data.zip.xml/xml-> zipxml :Items :Item [:Type "A"] :Note clojure.data.zip.xml/text)
;; => ("AA" "AA")

,但是没有找到类似的声明性功能来删除/编辑子级

but didn't find similar declarative features for removing/editing children.

推荐答案

Clojure标准API提供了方便的函数来处理XML和其他树结构。可以使用 clojure.walk <进行深度优先遍历来删除(叶)节点/ a>:

The Clojure standard APIs provide convenient functions for manipulating XML and other tree structures. Removing (leaf) nodes can be done on depth-first traversal using clojure.walk:

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

(def xmlstr
"<ROOT>
  <Items>
    <Item><Type>A</Type><Note>AA</Note></Item>
    <Item><Type>B</Type><Note>BB</Note></Item>
    <Item><Type>C</Type><Note>CC</Note></Item>
    <Item><Type>A</Type><Note>AA</Note></Item>
  </Items>
</ROOT>")

(def xmldoc (xml/parse (java.io.ByteArrayInputStream. (.getBytes xmlstr))))

(defn tag-matches [item tag]
  (= (:tag item) tag))

(defn content-matches [item to-match]
  ((into #{} to-match)
   (apply str (:content item))))

(defn match-criteria [item to-match]
  (some #(and (tag-matches % :Type)
              (content-matches % to-match))
        (:content item)))

(defn mk-xml-walker [& to-remove]
  (fn [form]
    (if (and (vector? form)
             (some #(tag-matches % :Item) form))
      (filter (complement #(match-criteria % to-remove)) form)
      form)))

(xml/emit (walk/postwalk (mk-xml-walker "B" "C") xmldoc))

对于神奇的一线客,您可能还想看看 Specter ,它为处理嵌套数据结构(例如XML)提供了非常简洁的语法。

For magical one-liners, you may also want to check out Specter which provides a very concise syntax for manipulating nested data structures, like XML.

这篇关于使用Clojure删除特定的XML节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆