(require (lib "xml.ss" "xml")) (define i (open-input-file "forecast.xml")) (define doc-elem (document-element(read-xml i))) ;****************** xml data definitions ;Element = (make-element Location Location ; Symbol ; (listof Attribute) ; (listof Content)) ;Content = Pcdata ; | Element ; | Entity ; | Misc ;Pcdata = (make-pcdata Location Location String) ;Entity = (make-entity (U Nat Symbol)) ;Misc = Comment ; | Processing-instruction ;******************** ;******************** forecast internal data definition ; A forecast is ; (make-forecast date/string num num '(num num)) (define-struct forecast (target-date low-temp high-temp pair-of-pop)) ;******************** templates ;f-of-element : element -> ... ;(define (f-of-element el) ; ... (f-of-name (element-name el)) ; ... (f-of-listof-content (element-content el)) ; ) ;f-of-listofcontent : content -> ... ;(define (f-of-listofcontent l) ; ... (f-of-pcdata (car l)) ; ... (f-of-element (car l)) ; ... (f-of-entity (car l)) ; ... (f-of-listofcontent (cdr l)) ; ) ; the two functions below extract and translate xml data ; return listof-X for all elements satisfying COMP ; get-content-from-element : (element->bool) (listof-content->listof-X) element -> listof-X (define (get-content-from-element COMP F el) (cond [(COMP el) (F (element-content el))] [else (get-content-from-listof-content COMP F (element-content el))]) ) ; get-content-from-listof-content : (element->bool) (content->X) listof-content -> listof-X (define (get-content-from-listof-content COMP F l) (cond [(eq? l '()) l] [(element? (car l)) (append (get-content-from-element COMP F (car l)) (get-content-from-listof-content COMP F (cdr l)))] ; don't care about entity or pcdata ... just process rest of list [else (get-content-from-listof-content COMP F (cdr l))] ) ) ;**************************** utilities (define (curry f) (lambda (v1) (lambda (v2) (f v1 v2)))) ; strip-string : string -> string ; strip whitespace characters from s (define (strip-string s) (letrec ((strip-c (lambda(c l) (cond [(char-whitespace? c) l] [else (cons c l)])))) (list->string (foldr strip-c '() (string->list s))))) ; name=? symbol element -> bool (define (name=? name el) (eq? name (element-name el))) ;******************************* ; test cases (specific to forecast.xml) ; forecastCreationTime (define (content->fcd l) (list (pcdata-string (car l)))) (get-content-from-element ((curry name=?) '|forecastCreationTime|) content->fcd doc-elem) "should be " '("Mon Feb 9 23:13:40 2004") ; target date (define (content->date l) (list (pcdata-string (car l)))) (get-content-from-element ((curry name=?) '|validDate|) content->date doc-elem) "should be" '("Feb 10" "Feb 11" "Feb 12" "Feb 13" "Feb 14" "Feb 15" "Feb 16") ; temperature (define (content->number l) (list (string->number (strip-string (pcdata-string (car l)))))) (get-content-from-element ((curry name=?) '|maxTemp|) content->number doc-elem) "should be" '(28 30 26 29 35 37 29) ; forecast (define (content->forecast l) (letrec ((g (lambda (name F) (get-content-from-listof-content ((curry name=?) name) F l)))) (list (make-forecast (car (g '|validDate| content->date)) (car (g '|minTemp| content->number)) (car (g '|maxTemp| content->number)) (g '|pop| content->number))))) (get-content-from-element ((curry name=?) '|forecastDay|) content->forecast doc-elem)