tags:

views:

469

answers:

2

Clojures clojure.xml/parse, clojure.zip/xml-zip and clojure.contrib.zip-filter.xml/xml-> are excellent tools for pulling values out of xml, but what if I want to change the xml (the result of clojure.zip/xml-zip) based on what I learn from xml-> "queries" and write the result back out as xml?

I would have expected that (clojure.contrib.prxml/prxml (clojure.xml/parse xml-content)) spit back xml, but that is not the case.

+3  A: 

Update: Actually, for emitting XML, it's best to use clojure.contrib.lazy-xml/emit, because clojure.xml/emit is currently likely to break things! See my comment below.

(Leaving this answer here for now as a warning.)


If I understand correctly, the main thrust of the question has to do with turning the (possibly mutated) XML representation back into XML text?

If so, have a look at clojure.xml/emit and clojure.xml/emit-element:

user> (with-out-str (xml/emit {:tag :foo :attrs {:bar "quux"}}))
"<?xml version='1.0' encoding='UTF-8'?>\n<foo bar='quux'/>\n"

(with-out-str captures printed output and wraps it up as a string; for some reason xml/emit prints the xml, so it comes in handy here. You'll want to use emit-element if <?xml version='1.0' encoding='UTF-8'?> is not what you want.)

Michał Marczyk
For the benefit of future readers: Apparently this is very limited in its usability, as `clojure.xml/emit` currently takes a very naive approach to its job and e.g. neglects to encode stuff as XML entities... Use `clojure.contrib.lazy-xml/emit` instead. Also see my answer to the follow-up question: http://stackoverflow.com/questions/2463129/roundtripping-xml-in-clojure-using-clojure-xml-parse-and-clojure-xml-emit/2463768#2463768
Michał Marczyk
+7  A: 

You can use the xml-zip library to "mutate" XML just like you would any other of Clojure's immutable structures. It has a full set of "mutating" functions: (api)

They all return an entire "modified" zipper. You can then go to the top of that zipper, and user xml/emit to print the XML.

levand