Hello, I am trying to write a (simple) function to convert s-expressions to XML. I've come up with following function, which (somehow) works:
(use-modules (ice-9 rdelim)) (use-modules (ice-9 pretty-print)) (define atom? (lambda (x) (and (not (pair? x)) (not (null? x))))) (define (indent string count) (if (< count 1) "" (string-append string (indent string (- count 1))))) (define (walklist expr level) (if (null? expr) '() (begin (sexp->xml (car expr) (+ level 1)) (walklist (cdr expr) level)))) (define (unknown->string expr) (let ((s (open-output-string))) (display expr s) (get-output-string s))) (define (sexp->xml expr . params) (let ((level (if (null? params) 0 (car params)))) (cond ((atom? expr) (simple-format #t "~A~A\n" (indent " " level) expr)) ((list? (car expr)) (sexp->xml (car expr) (+ level 1)) (walklist (cdr expr) level)) ; ((pair? expr) ; (simple-format #t "~A~A\n" (indent " " level) (car expr)) ; (simple-format #t "~A~A\n" (indent " " level) (cdr expr))) (#t (let ((s (unknown->string (car expr)))) (simple-format #t "~A~A~A~A\n" (indent " " level) "<" s ">") (walklist (cdr expr) level) (simple-format #t "~A~A~A~A\n" (indent " " level) "</" s ">")))))) (sexp->xml '(person (name "myself") (address (street "somestreet" 2) (town 1234 "thistown") (country "wonderland") (test 'a b) ; (test1 . asd) (test2 '(asd "asd"))))) While this seems to work, it has some drawbacks, which I can not figure out how to get rid of them: - It doesn't work on pairs. When I uncomment the case which checks for pairs, the result is no longer XML. Instead, it looks more like the output of (display) - There is no way to tell symbols from strings in the XML output. - I'd like atoms to be enclosed into its tags without any whitespace. While it is easy to get rid of the indentation and the trailing newline, I can't figure out how to get rid of the newline that comes behind the opening tag Any hints? BTW: In addition, I'd appreciate any hints how to make this thing more scheme'ish. I think there is lots of potential for improvement here.