From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Phil Jackson Newsgroups: gmane.emacs.devel Subject: xmlgen.el: inclusion? Date: Mon, 01 Sep 2008 15:43:57 +0100 Message-ID: <87ljycgc42.fsf@shellarchive.co.uk> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1220280262 782 80.91.229.12 (1 Sep 2008 14:44:22 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 1 Sep 2008 14:44:22 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Sep 01 16:45:15 2008 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1KaAeT-000608-2g for ged-emacs-devel@m.gmane.org; Mon, 01 Sep 2008 16:45:09 +0200 Original-Received: from localhost ([127.0.0.1]:56003 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KaAdU-00070B-7J for ged-emacs-devel@m.gmane.org; Mon, 01 Sep 2008 10:44:08 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KaAdO-0006vo-9G for emacs-devel@gnu.org; Mon, 01 Sep 2008 10:44:02 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KaAdK-0006ms-1b for emacs-devel@gnu.org; Mon, 01 Sep 2008 10:44:01 -0400 Original-Received: from [199.232.76.173] (port=40566 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KaAdJ-0006me-TL for emacs-devel@gnu.org; Mon, 01 Sep 2008 10:43:57 -0400 Original-Received: from b.painless.aaisp.net.uk ([81.187.30.52]:54030) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1KaAdJ-00006u-PM for emacs-devel@gnu.org; Mon, 01 Sep 2008 10:43:58 -0400 Original-Received: from 241.28.187.81.in-addr.arpa ([81.187.28.241] helo=home-desktop) by b.painless.aaisp.net.uk with esmtp (Exim 4.69) (envelope-from ) id 1KaAdA-0006MF-SU for emacs-devel@gnu.org; Mon, 01 Sep 2008 15:43:49 +0100 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) X-Virus-Scanned: Clear (Version: ClamAV 0.93.3/8122/Sun Aug 31 02:04:56 2008, by smtp.aaisp.net.uk) X-detected-kernel: by monty-python.gnu.org: Linux 2.6 (newer, 3) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:103372 Archived-At: --=-=-= Hi, Correct me if emacs already has this functionality, but... I knocked up an xml generation (xmlgen, I have no imagination) tool that I think may be handy enough for inclusion. I only use it for basic stuff, but find I use it a lot: (xmlgen '(html (head (title "Hello")) (body :id "anid" :class "aclass" (h1 "Hello")))) => " Hello

Hello

" (The output isn't indented like that. It'll be on one line.) I expect there are a few modules in emacs itself that might benefit from it making big `format' statements more manageable (erm, and slower). --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=xmlgen.el ;;; xml-gen.el --- A DSL for generating XML. ;; Copyright (C) 2008 Philip Jackson ;; Author: Philip Jackson ;; Version: 0.4 ;; This file is not currently part of GNU Emacs. ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 2, or (at ;; your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program ; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; Generate xml using sexps with the function `xmlgen': ;; (xmlgen '(p :class "big")) => "

") ;; (xmlgen '(p :class "big" "hi")) => "

hi

") ;; (xmlgen '(html ;; (head ;; (title "hello") ;; (meta :something "hi")) ;; (body ;; (h1 "woohhooo") ;; (p "text") ;; (p "more text")))) ;; produces this (though wrapped): ;; ;; ;; hello ;; ;; ;; ;;

woohhooo

;;

text

;;

more text

;; ;; (eval-when-compile (require 'cl)) (defvar xmlgen-escape-attribute-vals t "When non-nil xmlgen will escape the characters <>'\"&' in an attribute value.") (defvar xmlgen-escape-elm-vals t "When non-nil xmlgen will escape the characters <>'\"&' in an elements content.") (defun xmlgen (form) "Convert a sexp to xml: '(p :class \"big\")) => \"

\"" (cond ((numberp form) (number-to-string form)) ((stringp form) (if xmlgen-escape-elm-vals (xmlgen-string-escape form) form)) ((listp form) (destructuring-bind (xml attrs) (xmlgen-extract-plist form) (let ((el (car xml))) (unless (symbolp el) (error "Element must be a symbol (got '%S')." el)) (setq el (symbol-name el)) (concat "<" el (xmlgen-attr-to-string attrs) (if (> (length xml) 1) (concat ">" (mapconcat '(lambda (s) (xmlgen s)) (cdr xml) " ") "") " />"))))))) (defun xmlgen-string-escape (string) "Escape STRING for inclusion in some XML." (let ((escapees '(("&" . "&") ("'" . "'") ("\"" . """) ("<" . "<") (">" . ">")))) (mapc '(lambda (e) (setq string (replace-regexp-in-string (car e) (cdr e) string))) escapees) string)) (defun xmlgen-attr-to-string (plist) "Convert a plist to xml style attributes." (let ((res "")) (while plist (let ((sym (pop plist)) (val (pop plist))) (setq res (concat res " " (substring (symbol-name sym) 1 ) "=\"" (if xmlgen-escape-attribute-vals (xmlgen-string-escape val) val) "\"")))) res)) (defun xmlgen-extract-plist (list) "Extract a plist from LIST returning the original list without the plist and the plist." (let ((nlist '()) (plist '()) (last-keyword nil)) (mapc '(lambda (item) (let ((item (pop list))) (cond (last-keyword (setq plist (append plist (list last-keyword))) (setq plist (append plist (list item))) (setq last-keyword nil)) ((keywordp item) (setq last-keyword item)) (t (setq nlist (append nlist (list item))))))) list) (when last-keyword (error "No value to satisfy keyword '%s'" (symbol-name last-keyword))) (list nlist plist))) (provide 'xmlgen) --=-=-= Cheers, Phil -- Philip Jackson http://www.shellarchive.co.uk --=-=-=--