common-lispcl-who

How to produce double quotes instead of single quotes for XML attributes in CL-WHO


By default, CL-WHO uses single quotes for quoting XML attributes values (e.g. <h1 id='title'>Hello!</h1>). I am trying to set cl-who:*attribute-quote-char* to #\" so that attribute values use double quotes instead (e.g. <h1 id="title">Hello!</h1>). However, (setq cl-who:*attribute-quote-char #\") does not seem to have any effect when I use it in ASDF like this:

myprog.asd:

(defpackage myprog-asd
  (:use :cl :asdf))
(in-package :myprog-asd)

(defsystem "myprog"
  :depends-on (:cl-who)
  :components ((:file "mypackage")))

mypackage.lisp:

(defpackage :mypackage
  (:use :cl)
  (:export :f))
(in-package :mypackage)

(setq cl-who:*attribute-quote-char* #\")  ;; <- HERE.

(defun f ()
  (cl-who:with-html-output (*standard-output*)
    (:h1 :id "title" "Hello!")))

I am getting single quotes instead of double quotes:

$ sbcl
* (require "asdf")
* (asdf:load-asd (merge-pathnames "myprog.asd" (uiop:getcwd)))
* (asdf:load-system :myprog)
* (mypackage:f)
<h1 id='title'>Hello!</h1>

Why is (setq cl-who:*attribute-quote-char #\") not having any effect? How do I make CL-WHO print double quotes instead of single quotes?

(SBCL version: 2.2.2, CL-WHO version: 1.1.4 [commit: 0d382647])


By the way, I found that I could get double quotes by wrapping the setq in an eval-when:

(eval-when (:compile-toplevel :execute)
  (setq cl-who:*attribute-quote-char* #\"))

However, I have no idea how or why this works.


Solution

  • This is happening because with-html-output is smart enough to spot (some, it necessarily can not spot all) cases where the generated HTML is a constant string. In those cases it just turns the whole thing into a macroexpansion-time constant. and that happens before you have assigned to the variable, which happens at load time. That's why wrapping it with (eval-when (... :compile-toplevel) ...) works.