From: David Lichteblau Date: Sun, 27 Apr 2008 18:35:12 +0000 (+0200) Subject: Docstrings X-Git-Url: https://repo.or.cz/w/xuriella.git/commitdiff_plain/597e3261a39717ea6937c225486e2263a438ab87 Docstrings --- diff --git a/extensions.lisp b/extensions.lisp index 74b4730..a7fec8b 100644 --- a/extensions.lisp +++ b/extensions.lisp @@ -65,6 +65,14 @@ (push new-ext (gethash uri *extension-groups*)))) (defmacro define-extension-group (name uri &optional documentation) + "@arg[name]{The name of the XSLT extension group (a symbol)} + @arg[uri]{Namespace URI for the extension elements (a string)} + @arg[documentation]{Documentation string for the XPath extension} + @short{Defines an XSLT extension group with specified + short @code{name} and namespace @code{uri}.} + + An XSLT extension group is a collection of XSLT element that are defined + using @fun{define-extension-parser}." (check-type name symbol) `(%define-extension-group ',name ,uri ,documentation)) @@ -83,6 +91,37 @@ (make-extension-element :local-name name))) (defmacro define-extension-parser (ext name (node-var) &body body) + "@arg[ext]{The name of an XSLT extension group (a symbol)} + @arg[name]{Local name of the extension element (a string)} + @arg[node-var]{Variable name for the node to be parsed, a symbol.} + @arg[body]{Lisp forms, an implicit progn} + @short{Defines a parser an extension element.} + + The parser function defined by this macro will be invoked when + an XSLT extension element is encountered that has the namespace URI + of the specified extension group and the local-name of this parser. + + @code{body} should return an XSLT instruction in sexp syntax. + + As a (very hypothetical) example, if the return value is computed using + + @begin{pre} + `(xsl:text ,(princ-to-string node-var)) + @end{pre} + + the stylesheet will emit a text node at run time, with the string + representation of the instruction node as a value. + + Alternatively, a form can be returned that refers to user-specific + compiler extensions: + + @begin{pre} + `(your-package::frob + ,(stp:attribute-value node-var \"frob-arg\")) + @end{pre} + + Use @fun{define-extension-compiler} to implement an extension like + @code{frob}." `(setf (extension-element-parser (ensure-extension-element ',ext ',name)) (lambda (,node-var) @@ -106,6 +145,26 @@ (return (values 'ignore normal-forms))))) (defmacro define-extension-compiler (symbol (&rest lambda-list) &body body) + "@arg[symbol]{The name of the extension, a symbol} + @arg[lambda-list]{A destructuring lambda list, optionaly augmented using + &environment} + @arg[body]{Lisp forms, an implicit progn} + + Defines @code{symbol} as a name to be used in Xuriella's sexp + representation for XSLT. + + It used when XSLT in sexp syntax includes a list of the form: + + @begin{pre}(symbol ...arguments...)@end{pre} + + The list @code{arguments} is then destructured using the specified lambda + list, and @code{body} is invoked during compilation time as an implicit + progn. + + @code{body} should return a function of one argument, which will be called + at run time with a context object as an argument. + + @see{compile-instruction}" (when (find (symbol-package symbol) ;; reserved for built-in instructions: (list (find-package :common-lisp) diff --git a/instructions.lisp b/instructions.lisp index da4ccb9..2c99d91 100644 --- a/instructions.lisp +++ b/instructions.lisp @@ -748,6 +748,19 @@ collect (list name (funcall value-thunk ctx)))))))) (defun compile-instruction (form env) + "@arg[form]{An XSLT instruction in sexp representation} + @arg[env]{An XSLT environment} + @return{A compiled function} + + @short{Compiles an XSLT instruction.} + + This function is for use in XSLT extensions. When defining an + extension using @macro{define-extension-compiler}, pass body forms of + the extension that should be interpreted as XSLT instructions to this + function. + + The environment is an opaque object, which can be obtained using + the @code{&environment} lambda list keyword in the extension compiler." (xslt-trace-thunk (funcall (or (get (car form) 'xslt-instruction) (get (car form) 'extension-compiler) diff --git a/package.lisp b/package.lisp index 1f06d63..97a6560 100644 --- a/package.lisp +++ b/package.lisp @@ -25,9 +25,6 @@ #:fallback #:use-attribute-sets - ;; Extensions - #:document ;fixme: incompatible with XSLT 2.0 - ;; xuriella internals #:with-version #:with-namespaces @@ -43,8 +40,15 @@ (:use :cl) (:export #:parse-stylesheet #:apply-stylesheet + #:stylesheet + #:parameter + #:parameter-uri + #:parameter-local-name + #:parameter-value #:make-parameter + #:xslt-error + #:define-extension-group #:define-extension-parser #:define-extension-compiler @@ -62,6 +66,7 @@ parameter instances created by @fun{make-parameter}. @aboutfun{apply-stylesheet} + @aboutclass{parameter} @aboutfun{make-parameter} @end{section} @begin[Compiling stylesheets explicitly]{section} @@ -71,6 +76,7 @@ compile it first. @aboutfun{parse-stylesheet} + @aboutclass{stylesheet} @end{section} @begin[Defining extension elements]{section} Xuriella can be extended in two ways: diff --git a/parser.lisp b/parser.lisp index 0ea4bcd..7014e24 100644 --- a/parser.lisp +++ b/parser.lisp @@ -61,6 +61,19 @@ exprs)) (defun parse-body (node &optional (start 0) (param-names '())) + "@arg[node]{A node representing part of a stylesheet.} + @arg[start]{An optional integer, defaulting to 0.} + @arg[param-names]{Undocumented.} + @return{An list of XSLT instructions in sexp syntax} + + @short{Parses the children of an XSLT instruction.} + + This function is for use in XSLT extensions. When defining an + extension using @fun{define-extension-parser}, it can be used + to parse the children of the extension node using regular XSLT syntax + recursively. + + Specify @code{start} to skip the first @code{start} child nodes." (let ((n (stp:count-children-if #'identity node))) (labels ((recurse (i) (when (< i n) diff --git a/xslt.lisp b/xslt.lisp index b2f1932..6ed6cb1 100644 --- a/xslt.lisp +++ b/xslt.lisp @@ -50,6 +50,7 @@ (:documentation "The class of recoverable XSLT errors.")) (defun xslt-error (fmt &rest args) + "@unexport{}" (error 'xslt-error :format-control fmt :format-arguments args)) ;; Many errors in XSLT are "recoverable", with a specified action that must @@ -431,6 +432,14 @@ (decimal-formats (make-hash-table :test 'equal)) (initial-global-variable-thunks (make-hash-table :test 'equal))) +(setf (documentation 'stylesheet 'type) + "The class of stylesheets that have been parsed and compiled. + + Pass instances of this class to @fun{apply-stylesheet} to invoke + them. + + @see-constructor{parse-stylesheet}") + (defstruct mode (templates nil) (match-thunk (lambda (ignore) (declare (ignore ignore)) nil))) @@ -708,6 +717,17 @@ (defvar *stylesheet*) (defun parse-stylesheet (designator &key uri-resolver) + "@arg[designator]{an XML designator} + @arg[uri-resolver]{optional function of one argument} + @return{An instance of @class{stylesheet}.} + + @short{Parse a stylesheet.} + + This function parses and compiles an XSLT stylesheet. + The precompiled stylesheet object can then be passed to + @fun{apply-stylesheet}. + + Also refer to @fun{apply-stylesheet} for details on XML designators." (with-resignalled-errors () (xpath:with-namespaces ((nil #.*xsl*)) (let* ((*import-priority* 0) @@ -1230,6 +1250,55 @@ local-name value) +(setf (documentation 'parameter 'type) + "The class of top-level parameters to XSLT stylesheets. + + Parameters are identified by expanded names, i.e. a namespace URI + and local-name. + + Their value is string. + + @see-constructor{make-parameter} + @see-slot{parameter-uri} + @see-slot{parameter-local-name} + @see-slot{parameter-value}") + +(setf (documentation 'make-parameter 'function) + "@arg[value]{The parameter's value, a string.} + @arg[local-name]{The parameter's local name, a string.} + @arg[local-name]{The parameter's namespace URI, a string.} + @return{An instance of @class{parameter}.} + + @short{Creates a paramater.} + + @see{parameter-uri} + @see{parameter-local-name} + @see{parameter-value}") + +(setf (documentation 'parameter-uri 'function) + "@arg[instance]{An instance of @class{parameter}.} + @return{A string} + @return{Returns the parameter's namespace URI.} + + @see{parameter-local-name} + @see{parameter-value}") + +(setf (documentation 'parameter-local-name 'function) + "@arg[instance]{An instance of @class{parameter}.} + @return{A string} + @return{Returns the parameter's local name.} + + @see{parameter-uri} + @see{parameter-value}") + +(setf (documentation 'parameter-value 'function) + "@arg[instance]{An instance of @class{parameter}.} + @return{A string} + @return{Returns the parameter's value.} + + @see{parameter-uri} + @see{parameter-local-name}") + (defun find-parameter-value (local-name uri parameters) (dolist (p parameters) (when (and (equal (parameter-local-name p) local-name) @@ -1455,6 +1524,70 @@ (defun apply-stylesheet (stylesheet source-designator &key output parameters uri-resolver navigator) + "@arg[stylesheet]{a stylesheet designator (see below for details)} + @arg[source-designator]{a source document designator (see below for details)} + @arg[output]{optional output sink designator (see below for details)} + @arg[parameters]{a list of @class{parameter} instances} + @arg[uri-resolver]{optional function of one argument} + @arg[navigator]{optional XPath navigator} + @return{The value returned by sax:end-document when called on the + designated output sink.} + + @short{Apply a stylesheet to a document.} + + This function takes @code{stylesheet} (either a parsed @class{stylesheet} + or a designator for XML file to be parsed) and a source document, specified + using the XML designator @code{source-designator}, and applies the + stylesheet to the document. + + An XML designator is any value accepted by @code{cxml:parse}, in particular: + @begin{ul} + @item{Pathnames -- The file referred to by the pathname will parsed + using cxml.} + @item{Stream -- The stream will be parsed using cxml.} + @item{Xstream -- Similar to the stream case, but using cxml's internal + representation of rune streams.} + @item{String -- The string itself will be parsed as an XML document, + and is assumed to have been decoded into characters already.} + @item{Array of (unsigned-byte 8) -- The array itself will be parsed as + an XML document (which has not been decoded yet).} + @end{ul} + + Note: Since strings are interpreted as documents, namestrings are + not acceptable. Use pathnames instead of namestrings. + + An output sink designator is has the following form: + @begin{ul} + @item{Null -- Designates a string sink. I.e., the result document + of the stylesheet will be returned as a string. This as the default.} + @item{Pathnames -- The file referred to by the pathname will created + and written to.} + @item{Stream -- The stream will be written to.} + @item{SAX or HAX handler -- Events will be sent directly to this sink.} + @end{ul} + + Note: Specificaton of a sink overrides the specification of XML or HTML + output method in the styl.sheet. + + Parameters are identified by names, and have values that are strings. + Top-level parameters of these names are bound accordingly. If a paramater + is not specified, its default value is computed as implemented in the + stylesheet. If parameters are specified that the stylesheet does not + recognize, they will be ignored. + + A @code{uri-resolver} is a function taking a PURI object as an argument + and returning a PURI object as a value. The URI resolver will be invoked + for all references to external files, e.g. at compilation time using + xsl:import and xsl:include, and at run-time using the document() function. + + The URI resolver can be used to rewrite URLs so that file http:// links + are replaced by file:// links, for example. Another application are + URI resolvers that signal an error instead of returning, for example + so that file:// links forbidden. + + The specified @code{navigator} will be passed to XPath protocol functions. + + @see{parse-stylesheet}" (when (typep stylesheet 'xml-designator) (setf stylesheet (handler-bind