Thank you everyone for your advice, I found it useful and think that I am part-way to a solution using clojure.data.xml/source-seq as suggested by dannue.
I'll post what I have done so far in the hope it might help someone else... comments on style welcome.
Solution:
Given the following XML,
<head>
<title>This is some text</title>
<body>
<h1>This is a header</h1>
</body>
</head>
data.xml/source-seq will return a lazy seq of data.xml.Event items
#clojure.data.xml.Event{:type :start-element, :name :head, :attrs nil, :str nil}
#clojure.data.xml.Event{:type :characters, :name nil, :attrs nil, :str nil}
#clojure.data.xml.Event{:type :start-element, :name :title, :attrs nil, :str nil}
#clojure.data.xml.Event{:type :characters, :name nil, :attrs nil, :str This is some text}
#clojure.data.xml.Event{:type :end-element, :name :title, :attrs nil, :str nil}
#clojure.data.xml.Event{:type :start-element, :name :body, :attrs nil, :str nil}
#clojure.data.xml.Event{:type :start-element, :name :h1, :attrs nil, :str nil}
#clojure.data.xml.Event{:type :characters, :name nil, :attrs nil, :str This is a header}
#clojure.data.xml.Event{:type :end-element, :name :h1, :attrs nil, :str nil}
#clojure.data.xml.Event{:type :end-element, :name :body, :attrs nil, :str nil}
#clojure.data.xml.Event{:type :end-element, :name :head, :attrs nil, :str nil}
This is perfect for finding elements with a particular name, but completely useless if I want to find an element based on its location. So I maintain a stack where each :start-element causes the element name to be pushed, and each :end-element to invoke a pop.
(filter (fn [x] (complement (nil? x)))
(let [stack (atom [])
search-pattern "vmware/collectionHost/Object/Property/Property"]
(doseq[x (take 100 xml)] ; just test with the first 100 elements in seq.
(do
(cond
(= (:type x) :start-element) (swap! stack conj (name (get x :name)))
(= (:type x) :end-element) (swap! stack pop)
)
(when (= search-pattern (clojure.string/join "/" @stack)) (println (clojure.string/join "/" @stack)))
)
)
)
)
This is a work in progress and does not take account of attributes on the elements, but I would appreciate any comments.
Thanks
Pete