From 111e661f51828dfac8b8d13aba4a2457f60278e3 Mon Sep 17 00:00:00 2001 From: Chris Hanson Date: Wed, 5 Mar 2003 01:14:40 +0000 Subject: [PATCH] Restructure XML output procedures to take a rest argument that is a list of keyword options. At present, there is only one option, 'start-indent, which turns the indentation on or off. --- v7/src/xml/xml-output.scm | 475 +++++++++++++++++++++----------------- 1 file changed, 262 insertions(+), 213 deletions(-) diff --git a/v7/src/xml/xml-output.scm b/v7/src/xml/xml-output.scm index 52c1e172c..3219fc3a5 100644 --- a/v7/src/xml/xml-output.scm +++ b/v7/src/xml/xml-output.scm @@ -1,6 +1,6 @@ #| -*-Scheme-*- -$Id: xml-output.scm,v 1.15 2003/03/01 16:52:53 cph Exp $ +$Id: xml-output.scm,v 1.16 2003/03/05 01:14:40 cph Exp $ Copyright 2001,2002,2003 Massachusetts Institute of Technology @@ -27,114 +27,155 @@ USA. (declare (usual-integrations)) -(define (write-xml-file xml pathname) +(define (write-xml xml port . options) + (write-xml-1 xml port options)) + +(define (write-xml-file xml pathname . options) (call-with-output-file pathname (lambda (port) - (write-xml xml port)))) + (write-xml-1 xml port options)))) -(define (xml->string xml) +(define (xml->string xml . options) (call-with-output-string (lambda (port) - (write-xml xml port)))) + (write-xml-1 xml port options)))) + +(define (xml->wide-string xml . options) + (call-with-wide-output-string + (lambda (port) + (write-xml-1 xml port options)))) + +(define (write-xml-1 xml port options) + (%write-xml xml (make-ctx port options))) + +(define-structure (ctx (type-descriptor ctx-rtd) + (keyword-constructor %make-ctx) + (print-procedure + (standard-unparser-method 'XML-OUTPUT-CONTEXT #f))) + (port #f read-only #t) + ;; Either a non-negative integer (# of columns) or #f. + (start-indent #f read-only #t)) + +(define (make-ctx port options) + (apply %make-ctx 'PORT port options)) + +(define (emit-char char ctx) + (write-char char (ctx-port ctx))) -(define-generic write-xml (object port)) +(define (emit-string string ctx) + (write-string string (ctx-port ctx))) -(define-method write-xml ((document xml-document-rtd) port) +(define (emit-newline ctx) + (newline (ctx-port ctx))) + +(define (ctx-start-col ctx) + (let ((indent (ctx-start-indent ctx)) + (col (output-port/column (ctx-port ctx)))) + (and indent + col + (+ indent col)))) + +(define (ctx-x-size ctx) + (output-port/x-size (ctx-port ctx))) + +(define-generic %write-xml (object ctx)) + +(define-method %write-xml ((document xml-document-rtd) ctx) (if (xml-document-declaration document) - (write-xml (xml-document-declaration document) port)) - (for-each (lambda (object) (write-xml object port)) + (%write-xml (xml-document-declaration document) ctx)) + (for-each (lambda (object) (%write-xml object ctx)) (xml-document-misc-1 document)) (if (xml-document-dtd document) - (write-xml (xml-document-dtd document) port)) - (for-each (lambda (object) (write-xml object port)) + (%write-xml (xml-document-dtd document) ctx)) + (for-each (lambda (object) (%write-xml object ctx)) (xml-document-misc-2 document)) - (write-xml (xml-document-root document) port) - (for-each (lambda (object) (write-xml object port)) + (%write-xml (xml-document-root document) ctx) + (for-each (lambda (object) (%write-xml object ctx)) (xml-document-misc-3 document))) -(define-method write-xml ((declaration xml-declaration-rtd) port) - (write-string "" port)) + (emit-string " standalone=\"" ctx) + (emit-string (xml-declaration-standalone declaration) ctx) + (emit-string "\"" ctx))) + (emit-string "?>" ctx)) -(define-method write-xml ((element xml-element-rtd) port) +(define-method %write-xml ((element xml-element-rtd) ctx) (let ((name (xml-element-name element)) (contents (xml-element-contents element))) - (write-string "<" port) - (write-xml-name name port) + (emit-string "<" ctx) + (write-xml-name name ctx) (write-xml-attributes (xml-element-attributes element) (if (pair? contents) 1 3) - port) + ctx) (if (pair? contents) (begin - (write-string ">" port) - (for-each (lambda (content) (write-xml content port)) + (emit-string ">" ctx) + (for-each (lambda (content) (%write-xml content ctx)) contents) - (write-string "" port)) - (write-string " />" port)))) - -(define-method write-xml ((comment xml-comment-rtd) port) - (write-string "" port)) - -(define-method write-xml ((pi xml-processing-instructions-rtd) port) - (write-string "" port)) + (emit-string "" ctx)) + (emit-string " />" ctx)))) + +(define-method %write-xml ((comment xml-comment-rtd) ctx) + (emit-string "" ctx)) + +(define-method %write-xml ((pi xml-processing-instructions-rtd) ctx) + (emit-string "" ctx)) -(define-method write-xml ((dtd xml-dtd-rtd) port) +(define-method %write-xml ((dtd xml-dtd-rtd) ctx) ;;root external internal - (write-string "" port))) + (emit-string "]" ctx))) + (emit-string ">" ctx))) -(define-method write-xml ((decl xml-!element-rtd) port) - (write-string "" port)) + (emit-string ">" ctx)) -(define-method write-xml ((decl xml-!attlist-rtd) port) - (write-string "" port)) + (emit-string ">" ctx)) -(define-method write-xml ((decl xml-!entity-rtd) port) - (write-string "" port))) - -(define-method write-xml ((decl xml-unparsed-!entity-rtd) port) - (write-string "" port))) - -(define-method write-xml ((decl xml-parameter-!entity-rtd) port) - (write-string "" port))) - -(define-method write-xml ((decl xml-!notation-rtd) port) - (write-string "" port))) - -(define-method write-xml ((string ) port) +(define-method %write-xml ((decl xml-!entity-rtd) ctx) + (emit-string "" ctx))) + +(define-method %write-xml ((decl xml-unparsed-!entity-rtd) ctx) + (emit-string "" ctx))) + +(define-method %write-xml ((decl xml-parameter-!entity-rtd) ctx) + (emit-string "" ctx))) + +(define-method %write-xml ((decl xml-!notation-rtd) ctx) + (emit-string "" ctx))) + +(define-method %write-xml ((string ) ctx) (write-escaped-string string '((#\< . "<") (#\& . "&")) - port)) + ctx)) -(define-method write-xml ((ref xml-entity-ref-rtd) port) - (write-string "&" port) - (write-xml-name (xml-entity-ref-name ref) port) - (write-string ";" port)) +(define-method %write-xml ((ref xml-entity-ref-rtd) ctx) + (emit-string "&" ctx) + (write-xml-name (xml-entity-ref-name ref) ctx) + (emit-string ";" ctx)) -(define-method write-xml ((ref xml-parameter-entity-ref-rtd) port) - (write-string "%" port) - (write-xml-name (xml-parameter-entity-ref-name ref) port) - (write-string ";" port)) +(define-method %write-xml ((ref xml-parameter-entity-ref-rtd) ctx) + (emit-string "%" ctx) + (write-xml-name (xml-parameter-entity-ref-name ref) ctx) + (emit-string ";" ctx)) -(define (write-xml-attributes attributes suffix-cols port) - (let ((start-col (output-port/column port))) - (if (and start-col +(define (write-xml-attributes attributes suffix-cols ctx) + (let ((col (ctx-start-col ctx))) + (if (and col (pair? attributes) (pair? (cdr attributes)) - (>= (+ start-col + (>= (+ col (xml-attributes-columns attributes) suffix-cols) - (output-port/x-size port))) + (ctx-x-size ctx))) (begin - (write-char #\space port) - (write-xml-attribute (car attributes) port) + (emit-char #\space ctx) + (write-xml-attribute (car attributes) ctx) (for-each (lambda (attribute) - (write-indent (+ start-col 1) port) - (write-xml-attribute attribute port)) + (write-indent (+ col 1) ctx) + (write-xml-attribute attribute ctx)) (cdr attributes))) (for-each (lambda (attribute) - (write-char #\space port) - (write-xml-attribute attribute port)) + (emit-char #\space ctx) + (write-xml-attribute attribute ctx)) attributes)))) (define (xml-attributes-columns attributes) @@ -314,19 +355,19 @@ USA. (+ n-cols 1 (xml-attribute-columns (car attributes)))) n-cols))) -(define (write-xml-attribute attribute port) - (write-xml-name (car attribute) port) - (write-char #\= port) - (write-xml-attribute-value (cdr attribute) port)) +(define (write-xml-attribute attribute ctx) + (write-xml-name (car attribute) ctx) + (emit-char #\= ctx) + (write-xml-attribute-value (cdr attribute) ctx)) -(define (write-xml-attribute-value value port) - (write-char #\" port) +(define (write-xml-attribute-value value ctx) + (emit-char #\" ctx) (for-each (lambda (item) (if (string? item) - (write-xml-string item port) - (write-xml item port))) + (write-xml-string item ctx) + (%write-xml item ctx))) value) - (write-char #\" port)) + (emit-char #\" ctx)) (define (xml-attribute-columns attribute) (+ (xml-name-columns (car attribute)) @@ -341,38 +382,38 @@ USA. 2)))) n)))) -(define (write-xml-string string port) +(define (write-xml-string string ctx) (write-escaped-string string '((#\" . """) (#\< . "<") (#\& . "&")) - port)) + ctx)) (define (xml-string-columns string) - (let ((n (utf8-string-length string))) - (for-each-utf8-char string + (let ((n 0)) + (for-each-wide-char string (lambda (char) (set! n (fix:+ n (case char - ((#\") 5) - ((#\<) 3) - ((#\&) 4) - (else 0)))) + ((#\") 6) + ((#\<) 4) + ((#\&) 5) + (else 1)))) unspecific)) n)) -(define (write-xml-name name port) - (write-string (symbol-name name) port)) +(define (write-xml-name name ctx) + (emit-string (symbol-name name) ctx)) (define (xml-name-columns name) (utf8-string-length (symbol-name name))) -(define (write-entity-value value indent port) +(define (write-entity-value value col ctx) (if (xml-external-id? value) - (write-xml-external-id value indent port) + (write-xml-external-id value col ctx) (begin - (write-char #\" port) + (emit-char #\" ctx) (for-each (lambda (item) (if (string? item) @@ -380,58 +421,66 @@ USA. '((#\" . """) (#\& . "&") (#\% . "%")) - port) - (write-xml item port))) + ctx) + (%write-xml item ctx))) value) - (write-char #\" port)))) + (emit-char #\" ctx)))) -(define (write-xml-external-id id indent port) +(define (write-xml-external-id id col ctx) (let ((quoted-string (lambda (string) - (write-char #\" port) - (write-xml-string string port) - (write-char #\" port)))) + (emit-char #\" ctx) + (write-xml-string string ctx) + (emit-char #\" ctx)))) (if (xml-external-id-id id) (begin - (write-indent indent port) - (write-string "PUBLIC " port) + (write-indent col ctx) + (emit-string "PUBLIC " ctx) (quoted-string (xml-external-id-id id)) (if (xml-external-id-uri id) (begin - (write-indent indent port) + (write-indent col ctx) (quoted-string (xml-external-id-uri id))))) (begin - (write-indent indent port) - (write-string "SYSTEM" port) - (write-string " " port) + (write-indent col ctx) + (emit-string "SYSTEM" ctx) + (emit-string " " ctx) (quoted-string (xml-external-id-uri id)))))) - -(define (write-indent n port) - (if n + +(define (write-indent col ctx) + (if col (begin - (newline port) - (let ((q.r (integer-divide n 8))) + (emit-newline ctx) + (let ((q.r (integer-divide col 8))) (do ((i 0 (fix:+ i 1))) ((fix:= i (car q.r))) - (write-char #\tab port)) + (emit-char #\tab ctx)) (do ((i 0 (fix:+ i 1))) ((fix:= i (cdr q.r))) - (write-char #\space port)))) - (write-char #\space port))) + (emit-char #\space ctx)))) + (emit-char #\space ctx))) -(define (write-escaped-string string escapes port) - (for-each-utf8-char string +(define (write-escaped-string string escapes ctx) + (for-each-wide-char string (lambda (char) (let ((e (assq char escapes))) (if e - (write-string (cdr e) port) - (write-utf8-char char port)))))) - -(define (for-each-utf8-char string procedure) - (let ((port (open-input-string string))) - (let loop () - (let ((char (read-utf8-char port))) - (if (not (eof-object? char)) - (begin - (procedure char) - (loop))))))) \ No newline at end of file + (emit-string (cdr e) ctx) + (emit-char char ctx)))))) + +(define (for-each-wide-char string procedure) + (if (wide-string? string) + (let ((port (open-wide-input-string string))) + (let loop () + (let ((char (read-char port))) + (if (not (eof-object? char)) + (begin + (procedure char) + (loop)))))) + (let ((port (open-input-string string))) + (let loop () + (let ((char (read-utf8-char port))) + (if (not (eof-object? char)) + (begin + (procedure char) + (loop)))))))) \ No newline at end of file -- 2.25.1