[plt-scheme] SXML Experience?

From: Matt Jadud (mcj4 at kent.ac.uk)
Date: Mon Apr 25 18:23:50 EDT 2005

One way is to rebuild the document every time you touch it---a fairly 
functional approach. Unfortunately, if you have a large DTD, this could 
be a painful way to implement a transformer, as you end up with a lot of 

Here, I've used Jim Bender's sxml-match. I pull my document apart, and 
rebuild it... better, stronger, faster... and, for less than six million 

(Mostly, I'm just fond of the IU matcher, and wanted to write something 
in it for old times sake.)

Someone else on the list will probably come up with a way to do this 
that doesn't involve pattern matching and rebuilding the entire document 
every time you want to make a change; this is just one way to do it.

;; You can grab the sxml-match standalone from
;; http://celtic.benderweb.net/sxml-match/
;; I ran this in v209 DrScheme, language: MzScheme
;;   with case-sensitivity switched on.

(require "sxml-match.ss"
   (lib "sxml-to-html.ss" "ssax"))

(define example-sxml
     (head (title "The Muppet Show!"))
     (body (@ (bgcolor "white"))
           (h1 "The Muppet Show")
           (p "A work of pure genious")
           (p "The show featured the marvelous creations of Jim Henson")
           (p (em "He rocked.")))))

;; See what it looks like; side-effecting
(sxml->html example-sxml)

;; insert-stuff :: lol -> lol
;; or
;; insert-stuff :: sxml -> sxml
(define insert-stuff
   (let ()
     (define Top
       (lambda (tree)
         (sxml-match tree
           ;; Note the catas for explicit recursion on subparts.
           ;; I'm using a convention here that lists of things are
           ;; stored in variables suffixed with a '*'
           [(html (head ,[Head -> head*] ...) (body ,[Body -> body*] ...))
            ;; After matching (and recurring), I simply rebuild with a 
            ;; expression; after all, SXML is just Scheme lists.
            ;; But, I have to unquote splice to avoid getting extra parens.
              (head , at head*)
              (body , at body*))]
           ;; If it doesn't match, I'll handle the error instead of the 
           ;; dying for me.
           [,else (error 'top "Bad SXML: ~a" else)])))

     (define Head
       (lambda (tree)
         (sxml-match tree
           ;; Lets make sure the title is a string
           [(title ,title)
            (guard (string? title))
            `(title ,title)]
           [,else (error 'head "Bad head-part: ~a" else)])))

     (define Body
       (lambda (tree)
         (sxml-match tree
           ;; Here, I match one anything, but only if that 'anything'
           ;; satisfies the guard. I'll return strings unmolested.
            (guard (string? str))
           ;; Or, I might match a heading containing one element.
           ;; I'll return an h1 element, wrapping a font tag around it.
           ;; Of course, this isn't good XHTML, and furthermore,
           ;; I can't parse the output with the parser I have for my 
           [(h1 ,[Body -> p])
            `(h1 (font (@ (color "red")) ,p))]
           ;; Perhaps a paragraph element
           [(p ,[Body -> p])
            `(p ,p)]
           ;; Or an emphasis element. But, we'll make sure that
           ;; emphasis elements come through as emphasized and bold.
           ;; Again, this is probably bogus HTML after... oh, HTML 3.2
           ;; or something...
           [(em ,[Body -> p])
            `(em (strong ,p))]
           [,else (error 'body "Bad body-part: ~a" else)])))

     ;; Of course, the pattern matcher should consume an SXML tree,
     ;; and return an SXML tree. Someday, I'll start using contracts.
     (lambda (tree)
       (Top tree))))

;; Apply and display
(sxml->html (insert-stuff example-sxml))


Hans Oesterholt-Dijkema wrote:
 >  For list-related administrative tasks:
 >  http://list.cs.brown.edu/mailman/listinfo/plt-scheme
 > Hello,
 > Does anyone have experience with sxml here?
 > I'm able to let sxml/ssax parse my XML files,
 > and can even modify the value of elements,
 > using sxpath, but
 >   how can I insert or append new elements
 >   to an sxml tree?
 > Thanks in advance for answers,
 > Hans Oesterholt

Posted on the users mailing list.