fixed node order in apply-templates and for-each
[xuriella.git] / SYNTAX
blob74809daf94f468efc76166491f1a11b94a01f0b2
1 ;;; -*- mode:lisp -*-
3 ;;; Examples of s-expression syntax for XSLT templates.
5 ;;; (Only <template> itself and its instructions so far.
6 ;;; Not sure yet about <stylesheet> and its top level elements.)
8 ;;; I'm using symbols in the XSL package here instead of keywords (but that
9 ;;; doesn't really matter).
10 ;;;
11 ;;; There are currently no xsl:if/xsl:choose with XSLT semantics, only
12 ;;; the lisp-style forms if, when, unless, cond.  We could add the xsl:
13 ;;; forms if users want them, since XSL doesn't import CL anymore.
15 ;;; The tricky part are forms with multiple different kinds of optional
16 ;;; stuff, like xsl:template which has both normal attributes, AND
17 ;;; parameters AND a body.  Or xsl:apply-templates with normal attributes AND
18 ;;; parameters AND sorting rules.  I think body and parameters should
19 ;;; have a syntax and is particularly easy to use, whereas sorting rules
20 ;;; are probably less common.
22 ;;; FIXME: How can we distinguish between:
23 ;;;    (i) a pre-parsed XPath expression
24 ;;;   (ii) an XPath string (for example, in <xsl:variable select="foo"/>)
25 ;;;  (iii) an XSLT fragment (for example, in <xsl:variable>foo</xsl:variable>)
26 ;;; which all end up in the same position of (let ((name OOPS)) ...)
27 ;;;
28 ;;; Right now, we require (iii) to be written as (progn ...) while
29 ;;; (ii) is written literally.
30 ;;;
31 ;;; Alternatively, we could write (ii) as (:xpath ...) and (iii) literally.
32 ;;;
33 ;;; The problem with (i) and (ii) is whether "foo" is an XPath string
34 ;;; (the node test for "foo") or a literal string in a sexp, meaning "'foo'".
35 ;;; Currently we simply don't support (i), which is sad.
37 ((xsl:template :match "xpath" :name "foo" :priority 5 :mode "special")
38     (parameter1 (parameter2 default-value) parameter3)
39   . template-body)
41 (xsl:apply-templates
42     (:select "/" 
43      :mode "special")
44   (declare (sort ...) (sort ...))  ;optional sorting declarations
45   (parameter1 value)
46   (parameter3 value)
47   . and-so-on)
49 (xsl:apply-imports)
51 (xsl:call-template name
52   (parameter1 value)
53   (parameter3 value)
54   . and-so-on)
56 (xsl:element ("qname"
57               :namespace "http://..."
58               :use-attribute-sets ...)
59   . body)
61 (xsl:attribute ("qname" :namespace "http://...")
62   . body)
64 (xsl:text "foo")
65 (xsl:unescaped-text "bar")
67 (xsl:processing-instruction name
68   . body)
70 (xsl:comment "foo")
72 (xsl:copy (:use-attribute-sets ...)
73   . body)
75 (xsl:value-of <xpath>)
76 (xsl:unescaped-value-of <xpath>)
78 (xsl:number :level ... :count ...  :bla bla bla)
80 (xsl:for-each select
81   (declare (sort ...) (sort ...))  ;optional sorting declarations
82   . body)
84 ;; this is called <if> in XSLT, but that would be confusing in lisp
85 (when "/test"
86   . body)
88 ;; XSLT doesn't have this, but it seems useful:
89 (unless "/test"
90   . body)
92 ;; XSLT doesn't have this, but it seems useful:
93 (if "/test"
94     form1
95     form2)
97 ;; XSLT doesn't have this, but it seems useful:
98 (progn
99   . body)
101 ;; in XSLT, the children of <choose> are called <when> and <otherwise>,
102 ;; but we should better use a cond-like syntax:
103 (cond
104   ("/test1" . body)
105   ("/test2" . body)
106   ("/test3" . body)
107   (t . otherwise-body))
109 ;; XSLT does this using Dylan-style <xsl:variable>
110 (let ((var1 "/xpath")
111       (var2 "/xpath")
112       ;; this isn't ideal:
113       (var3 (progn (xsl:text "/xpath"))))
114   . body)
115 (let* ((var1 "/xpath")
116        (var2 "$var1 + 1"))
117   . body)
119 ;; the following is done using xmlns attributes on XSLT elements.
120 ;; We need a similar mechanism to establish namespaces for the XPath
121 ;; strings and other QNames.
122 (xsl:with-namespaces (("prefix1" "uri1")
123                       ("prefix2" "uri2"))
124   . body)
126 (xsl:copy-of "/xpath")
128 (xsl:message
129   . body)
130 (xsl:terminate
131   . body)
133 ;; useful only when reading XSL stylesheets in XML syntax, I think.
134 (xsl::fallback
135   . body)
137 ;; literal element <foo>
138 ;; like xsl:element, but without attribute value template and namespace
139 (xsl:literal-element ("local-name" "http://uri")
140   (xsl:literal-attribute ("name" "ouri")
141     "value")
142   (xsl:literal-attribute ("name")
143     "value")
144   . body)
147 ;;;; Tests
152 (xuriella::test-instruction
153  `(xsl:element ("bla")
154     (xsl:text "number of children: ")
155     (xsl:value-of "count(test/child)"))
156  "<test><child/><child/></test>")
158 (xuriella::test-instruction
159  `(let (("var" "1+2"))
160     (xsl:element ("bla")
161       (xsl:value-of "$var")))
162  "<test><child/><child/></test>")