Mercurial > lasercutter
view src/clojure/contrib/test_contrib/pprint/examples/xml.clj @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
line wrap: on
line source
1 ;;; xml.clj -- a pretty print dispatch version of prxml.clj -- a compact syntax for generating XML3 ;; by Tom Faulhaber, based on the original by Stuart Sierra, http://stuartsierra.com/4 ;; May 13, 20096 ;; Copyright (c) 2009 Tom Faulhaber/Stuart Sierra. All rights reserved. The use and7 ;; distribution terms for this software are covered by the Eclipse8 ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)9 ;; which can be found in the file epl-v10.html at the root of this10 ;; distribution. By using this software in any fashion, you are11 ;; agreeing to be bound by the terms of this license. You must not12 ;; remove this notice, or any other, from this software.15 ;; See function "prxml" at the bottom of this file for documentation.18 (ns19 #^{:author "Tom Faulhaber, based on the original by Stuart Sierra",20 :doc "A version of prxml that uses a pretty print dispatch function."}21 clojure.contrib.pprint.examples.xml22 (:use [clojure.contrib.string :only (as-str escape)]23 [clojure.contrib.pprint :only (formatter-out write)]24 [clojure.contrib.pprint.utilities :only (prlabel)]))26 (def27 #^{:doc "If true, empty tags will have a space before the closing />"}28 *html-compatible* false)30 (def31 #^{:doc "The number of spaces to indent sub-tags."}32 *prxml-indent* 2)34 (defmulti #^{:private true} print-xml-tag (fn [tag attrs content] tag))36 (defmethod print-xml-tag :raw! [tag attrs contents]37 (doseq [c contents] (print c)))39 (defmethod print-xml-tag :comment! [tag attrs contents]40 (print "<!-- ")41 (doseq [c contents] (print c))42 (print " -->"))44 (defmethod print-xml-tag :decl! [tag attrs contents]45 (let [attrs (merge {:version "1.0" :encoding "UTF-8"}46 attrs)]47 ;; Must enforce ordering of pseudo-attributes:48 ((formatter-out "<?xml version=\"~a\" encoding=\"~a\"~@[ standalone=\"~a\"~]?>")49 (:version attrs) (:encoding attrs) (:standalone attrs))))51 (defmethod print-xml-tag :cdata! [tag attrs contents]52 ((formatter-out "<[!CDATA[~{~a~}]]>") contents))54 (defmethod print-xml-tag :doctype! [tag attrs contents]55 ((formatter-out "<[!DOCTYPE [~{~a~}]]>") contents))57 (defmethod print-xml-tag :default [tag attrs contents]58 (let [tag-name (as-str tag)59 xlated-attrs (map #(vector (as-str (key %)) (as-str (val %))) attrs)]60 (if (seq contents)61 ((formatter-out "~<~<<~a~1:i~{ ~:_~{~a=\"~a\"~}~}>~:>~vi~{~_~w~}~0i~_</~a>~:>")62 [[tag-name xlated-attrs] *prxml-indent* contents tag-name])63 ((formatter-out "~<<~a~1:i~{~:_ ~{~a=\"~a\"~}~}/>~:>") [tag-name xlated-attrs]))))66 (defmulti xml-dispatch class)68 (defmethod xml-dispatch clojure.lang.IPersistentVector [x]69 (let [[tag & contents] x70 [attrs content] (if (map? (first contents))71 [(first contents) (rest contents)]72 [{} contents])]73 (print-xml-tag tag attrs content)))75 (defmethod xml-dispatch clojure.lang.ISeq [x]76 ;; Recurse into sequences, so we can use (map ...) inside prxml.77 (doseq [c x] (xml-dispatch c)))79 (defmethod xml-dispatch clojure.lang.Keyword [x]80 (print-xml-tag x {} nil))83 (defmethod xml-dispatch String [x]84 (print (escape {\< "<"85 \> ">"86 \& "&"87 \' "'"88 \" """} x)))90 (defmethod xml-dispatch nil [x])92 (defmethod xml-dispatch :default [x]93 (print x))96 (defn prxml97 "Print XML to *out*. Vectors become XML tags: the first item is the98 tag name; optional second item is a map of attributes.100 Sequences are processed recursively, so you can use map and other101 sequence functions inside prxml.103 (prxml [:p {:class \"greet\"} [:i \"Ladies & gentlemen\"]])104 ; => <p class=\"greet\"><i>Ladies & gentlemen</i></p>106 PSEUDO-TAGS: some keywords have special meaning:108 :raw! do not XML-escape contents109 :comment! create an XML comment110 :decl! create an XML declaration, with attributes111 :cdata! create a CDATA section112 :doctype! create a DOCTYPE!114 (prxml [:p [:raw! \"<i>here & gone</i>\"]])115 ; => <p><i>here & gone</i></p>117 (prxml [:decl! {:version \"1.1\"}])118 ; => <?xml version=\"1.1\" encoding=\"UTF-8\"?>"119 [& args]120 (doseq [arg args] (write arg :dispatch xml-dispatch))121 (when (pos? (count args)) (newline)))