Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 171 lines (137 sloc) 5.68 kb
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
1 ; Copyright (c) Chris Houser, April 2008. All rights reserved.
2 ; The use and distribution terms for this software are covered by the
dfd1a7a Chris Houser Switch my libs to EPL
Chouser authored
3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 ; which can be found in the file epl-v10.html at the root of this distribution.
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
5 ; By using this software in any fashion, you are agreeing to be bound by
6 ; the terms of this license.
7 ; You must not remove this notice, or any other, from this software.
8
8d7dfc3 Chris Houser Updated zip-filter and zip-filter.xml for new clojure.contrib layout.
Chouser authored
9 ; Specialization of zip-filter for xml trees.
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
10
12ca085 Chris Houser Update zip-filter to use ns plus other changes to work with Clojure rev ...
Chouser authored
11 (ns clojure.contrib.zip-filter.xml
12 (:require [clojure.contrib.zip-filter :as zf]
13 [clojure.zip :as zip]
14 [clojure.xml :as xml]))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
15
f01069d Chris Houser Use 'declare' instead of 'def' for forward declaration.
Chouser authored
16 (declare xml->)
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
17
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
18 (defn attr
19 "Returns the xml attribute named attrname, of the xml node at location loc."
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
20 ([attrname] (fn [loc] (attr loc attrname)))
ca68d8d Chris Houser Catch a couple error conditions.
Chouser authored
21 ([loc attrname] (when (zip/branch? loc) (-> loc zip/node :attrs attrname))))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
22
23 (defn attr=
24 "Returns a query predicate that matches a node when it has an
25 attribute named attrname whose value is attrval."
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
26 [attrname attrval] (fn [loc] (= attrval (attr loc attrname))))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
27
28 (defn tag=
29 "Returns a query predicate that matches a node when its is a tag
30 named tagname."
31 [tagname]
32 (fn [loc]
8d7dfc3 Chris Houser Updated zip-filter and zip-filter.xml for new clojure.contrib layout.
Chouser authored
33 (filter #(and (zip/branch? %) (= tagname ((zip/node %) :tag)))
34 (if (zf/auto? loc)
35 (zf/children-auto loc)
36 (list (zf/auto true loc))))))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
37
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
38 (defn text
39 "Returns the textual contents of the given location, similar to
40 xpaths's value-of"
41 [loc]
8d7dfc3 Chris Houser Updated zip-filter and zip-filter.xml for new clojure.contrib layout.
Chouser authored
42 (.replaceAll
b8d2743 use the 1.2 metadata reader macro ^ instead of #^
Aaron Bedra and Stuart Halloway authored
43 ^String (apply str (xml-> loc zf/descendants zip/node string?))
8d7dfc3 Chris Houser Updated zip-filter and zip-filter.xml for new clojure.contrib layout.
Chouser authored
44 (str "[\\s" (char 160) "]+") " "))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
45
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
46 (defn text=
47 "Returns a query predicate that matches a node when its textual
48 content equals s."
49 [s] (fn [loc] (= (text loc) s)))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
50
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
51 (defn seq-test
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
52 "Returns a query predicate that matches a node when its xml content
53 matches the query expresions given."
b8d2743 use the 1.2 metadata reader macro ^ instead of #^
Aaron Bedra and Stuart Halloway authored
54 ^{:private true}
81b9e71 Chris Houser Batch of changes for lazier clojure.
Chouser authored
55 [preds] (fn [loc] (and (seq (apply xml-> loc preds)) (list loc))))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
56
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
57 (defn xml->
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
58 "The loc is passed to the first predicate. If the predicate returns
59 a collection, each value of the collection is passed to the next
60 predicate. If it returns a location, the location is passed to the
61 next predicate. If it returns true, the input location is passed to
62 the next predicate. If it returns false or nil, the next predicate
63 is not called.
64
65 This process is repeated, passing the processed results of each
66 predicate to the next predicate. xml-> returns the final sequence.
67 The entire chain is evaluated lazily.
68
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
69 There are also special predicates: keywords are converted to tag=,
70 strings to text=, and vectors to sub-queries that return true if
71 they match.
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
72
73 See the footer of zip-query.clj for examples."
74 [loc & preds]
8d7dfc3 Chris Houser Updated zip-filter and zip-filter.xml for new clojure.contrib layout.
Chouser authored
75 (zf/mapcat-chain loc preds
76 #(cond (keyword? %) (tag= %)
77 (string? %) (text= %)
78 (vector? %) (seq-test %))))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
79
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
80 (defn xml1->
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
81 "Returns the first item from loc based on the query predicates
82 given. See xml->"
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
83 [loc & preds] (first (apply xml-> loc preds)))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
84
85
86 ; === examples ===
87
88 (comment
89
90 (defn parse-str [s]
91 (zip/xml-zip (xml/parse (new org.xml.sax.InputSource
92 (new java.io.StringReader s)))))
93
94 (def atom1 (parse-str "<?xml version='1.0' encoding='UTF-8'?>
95 <feed xmlns='http://www.w3.org/2005/Atom'>
96 <id>tag:blogger.com,1999:blog-28403206</id>
97 <updated>2008-02-14T08:00:58.567-08:00</updated>
98 <title type='text'>n01senet</title>
99 <link rel='alternate' type='text/html' href='http://n01senet.blogspot.com/'/>
100 <entry>
101 <id>1</id>
102 <published>2008-02-13</published>
103 <title type='text'>clojure is the best lisp yet</title>
104 <author><name>Chouser</name></author>
105 </entry>
106 <entry>
107 <id>2</id>
108 <published>2008-02-07</published>
109 <title type='text'>experimenting with vnc</title>
110 <author><name>agriffis</name></author>
111 </entry>
112 </feed>
113 "))
114
115 ; simple single-function filter
116 (assert (= (xml-> atom1 #((zip/node %) :tag))
117 '(:feed)))
118
119 ; two-stage filter using helpful query prediates
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
120 (assert (= (xml-> atom1 (tag= :title) text)
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
121 '("n01senet")))
122
123 ; same filter as above, this time using keyword shortcut
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
124 (assert (= (xml-> atom1 :title text)
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
125 '("n01senet")))
126
127 ; multi-stage filter
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
128 (assert (= (xml-> atom1 :entry :author :name text)
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
129 '("Chouser" "agriffis")))
130
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
131 ; test xml1->
132 (assert (= (xml1-> atom1 :entry :author :name text)
133 "Chouser"))
134
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
135 ; multi-stage filter with subquery specified using a vector
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
136 (assert (= (xml-> atom1 :entry [:author :name (text= "agriffis")]
137 :id text)
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
138 '("2")))
139
140 ; same filter as above, this time using a string shortcut
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
141 (assert (= (xml-> atom1 :entry [:author :name "agriffis"] :id text)
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
142 '("2")))
143
144 ; attribute access
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
145 (assert (= (xml-> atom1 :title (attr :type))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
146 '("text")))
147
148 ; attribute filtering
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
149 (assert (= (xml-> atom1 :link [(attr= :rel "alternate")] (attr :type))
093d86d Chris Houser Clean up namespaces and function names.
Chouser authored
150 '("text/html")))
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
151
152 ; ancestors
8d7dfc3 Chris Houser Updated zip-filter and zip-filter.xml for new clojure.contrib layout.
Chouser authored
153 (assert (= (xml-> atom1 zf/descendants :id "2" zf/ancestors zip/node #(:tag %))
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
154 '(:id :entry :feed)))
155
156 ; ancestors with non-auto tag= (:entry), followed by auto tag= (:id)
8d7dfc3 Chris Houser Updated zip-filter and zip-filter.xml for new clojure.contrib layout.
Chouser authored
157 (assert (= (xml-> atom1 zf/descendants :name "Chouser" zf/ancestors
158 :entry :id text)
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
159 '("1")))
160
161 ; left-locs and detection of returning a single loc (zip/up)
8d7dfc3 Chris Houser Updated zip-filter and zip-filter.xml for new clojure.contrib layout.
Chouser authored
162 (assert (= (xml-> atom1 zf/descendants :name "Chouser" zip/up
163 zf/left-locs :id text)
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
164 '("1")))
165
166 ; right-locs
8d7dfc3 Chris Houser Updated zip-filter and zip-filter.xml for new clojure.contrib layout.
Chouser authored
167 (assert (= (xml-> atom1 zf/descendants :id zf/right-locs :author text)
26995ac Chris Houser Add more axis, remove all macro definitions, and simplify implementation...
Chouser authored
168 '("Chouser" "agriffis")))
169
170 )
Something went wrong with that request. Please try again.