[plt-scheme] SXML Experience?
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
code.
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
dollars.
(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
'(html
(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
quasiquoted
;; expression; after all, SXML is just Scheme lists.
;; But, I have to unquote splice to avoid getting extra parens.
`(html
(head , at head*)
(body , at body*))]
;; If it doesn't match, I'll handle the error instead of the
matcher
;; 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.
[,str
(guard (string? str))
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
input...
[(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
>
>