Welcome! Please see the About page for a little more info on how this works.

0 votes
in data.xml by

I know the current approach to emitting indented output is kind of a hack. I embarked on a quest to make an indenting XMLStreamWriter which is attached. I'm not sure the best way it should be integrated into data.xml so I've not actually done that part, but I have included a demo, which is kind of a hacked version of clojure.data.xml/emit and clojure.data.xml.jvm.emit/write-document. I don't think there is a clean place to insert the wrapping IndentingWriter at the moment so that's something that needs to be resolved. But feel free to use this contribution as you will in implementing this feature.

2 Answers

0 votes

Comment made by: bendlas

Hi Alex,

thanks for bringing this up! The current, horrible implementation of indent has plagued my mind as well.

Thanks, also, for your implementation of an indenting java.xml.stream.XMLStreamWriter. Before going into detail on how your code could be integrated, or what options would suffice to introduce it in configuration, let me frame some solvable problems, that this ticket touches on:
- Being able to efficiently indent xml, ideally platform-independently
- Being able to swap out the XMLStreamWriter, and possibly other nitty-gritties of parse/emit, by configuration

I'll focus on the "efficiently indenting xml" part, for the purposes of this comment (and ticket, hopefully ;-) )

For a jvm-only solution, we should have a report on the possibility of (e.g.) hooking a StAXSource (link: 1) into the indenting-transformer (link: 2), before rolling our own. On the other hand, if cljs could profit as well, rolling our own streaming transformer makes sense, even if this could be achieved by other means in the jvm backend.

If you squint at your c.d.xml.jvm.indent namespace a little, you might already see the transducer, it contains, popping out at you. The XMLStreamWriter interface seems like incidental complexity in a simple text-node transformer, for the want of a streamable data model. Luckily data.xml, from the very beginning, was built on a streaming event model for xml (link: 3). I have been planning to support tree-transformations, in the form of transducers over the event stream, and indentation would be an awesome first use-case for this.

What do you think? If you're interested in taking this further, here is a commit, that defines an :event-xform config-option for emit* (link: 4).

(emit-str (parse-str "bar lala <br/> gag")

      :event-xform (fn [xf]
                       ([s] (xf s))
                       ([s {:as e :keys [str]}]
                        (-> s
                            (cond-> str (xf (clojure.data.xml.event/->CharsEvent "^.^")))
                            (xf e))))))

"<?xml version=\"1.0\" encoding=\"UTF-8\"?>^.^bar lala <br/>^.^ gag"

(link: 1) https://docs.oracle.com/javase/7/docs/api/javax/xml/transform/stax/StAXSource.html
(link: 2) https://github.com/clojure/data.xml/blob/master/src/main/clojure/clojure/data/xml/jvm/pprint.clj#L15
(link: 3) https://github.com/clojure/data.xml/blob/master/src/main/clojure/clojure/data/xml/event.clj
(link: 4) https://github.com/bendlas/data.xml/commit/0c2baa690154bfa731fa1f98a539542a0205e6b1

0 votes
Reference: https://clojure.atlassian.net/browse/DXML-50 (reported by alexmiller)