various docstrings; release
This commit is contained in:
committed by
David Lichteblau
parent
a1a95a4d03
commit
3aada6fb89
3
cxml.asd
3
cxml.asd
@ -45,7 +45,8 @@
|
|||||||
(:file "xmlns-normalizer" :depends-on ("xml-parse"))
|
(:file "xmlns-normalizer" :depends-on ("xml-parse"))
|
||||||
(:file "space-normalizer" :depends-on ("xml-parse"))
|
(:file "space-normalizer" :depends-on ("xml-parse"))
|
||||||
(:file "catalog" :depends-on ("xml-parse"))
|
(:file "catalog" :depends-on ("xml-parse"))
|
||||||
(:file "sax-proxy" :depends-on ("xml-parse")))
|
(:file "sax-proxy" :depends-on ("xml-parse"))
|
||||||
|
(:file "atdoc-configuration" :depends-on ("package")))
|
||||||
:depends-on (:closure-common :puri #-scl :trivial-gray-streams))
|
:depends-on (:closure-common :puri #-scl :trivial-gray-streams))
|
||||||
|
|
||||||
(defclass utf8dom-file (closure-source-file) ((of)))
|
(defclass utf8dom-file (closure-source-file) ((of)))
|
||||||
|
|||||||
41
dist.sh
41
dist.sh
@ -1,8 +1,10 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh -e
|
||||||
|
set -x
|
||||||
|
|
||||||
cd $(dirname $0)
|
cd $(dirname $0)
|
||||||
home=$(pwd)
|
home=$(pwd)
|
||||||
name=$(basename $home)
|
name=$(basename $home)
|
||||||
dir=${name}-$(date --iso)
|
name_and_date=${name}-$(date --iso)
|
||||||
|
|
||||||
TMPDIR=`mktemp -d /tmp/dist.XXXXXXXXXX`
|
TMPDIR=`mktemp -d /tmp/dist.XXXXXXXXXX`
|
||||||
cleanup() {
|
cleanup() {
|
||||||
@ -11,13 +13,36 @@ cleanup() {
|
|||||||
}
|
}
|
||||||
trap cleanup exit
|
trap cleanup exit
|
||||||
|
|
||||||
|
make -C doc
|
||||||
|
|
||||||
|
git tag -f $name_and_date
|
||||||
|
git archive --prefix=$name_and_date/ $name_and_date | \
|
||||||
|
( cd $TMPDIR && tar xvf - )
|
||||||
|
|
||||||
|
# echo '(progn (load "dist.lisp") (quit))' | clbuild lisp
|
||||||
|
|
||||||
|
rsync -a doc $TMPDIR/$name_and_date
|
||||||
|
|
||||||
cd $TMPDIR
|
cd $TMPDIR
|
||||||
cvs -d "`cat $home/CVS/Root`" export -r HEAD -d "$dir" "$name"
|
|
||||||
|
|
||||||
make -C $dir/doc
|
tgz=$TMPDIR/${name_and_date}.tgz
|
||||||
|
tar czf $tgz $name_and_date
|
||||||
tgz=$TMPDIR/${dir}.tgz
|
|
||||||
tar czf $tgz $dir
|
|
||||||
gpg -b -a $tgz
|
gpg -b -a $tgz
|
||||||
|
|
||||||
mv $tgz $tgz.asc $home/
|
mkdir -p ~/clnet/project/cxml/public_html/
|
||||||
|
|
||||||
|
rsync -av \
|
||||||
|
$name_and_date/doc/ \
|
||||||
|
~/clnet/project/cxml/public_html/
|
||||||
|
|
||||||
|
rsync $tgz $tgz.asc ~/clnet/project/cxml/public_html/download/
|
||||||
|
|
||||||
|
rm -f ~/clnet/project/cxml/public_html/download/cxml.tar.gz
|
||||||
|
rm -f ~/clnet/project/cxml/public_html/download/cxml.tar.gz.asc
|
||||||
|
|
||||||
|
ln -sf ${name_and_date}.tgz ~/clnet/project/cxml/public_html/download/cxml.tar.gz
|
||||||
|
ln -sf ${name_and_date}.tgz.asc ~/clnet/project/cxml/public_html/download/cxml.tar.gz.asc
|
||||||
|
|
||||||
|
echo done
|
||||||
|
exit 0
|
||||||
|
rsync -av ~/bob/public_html bob.askja.de
|
||||||
|
|||||||
@ -2,5 +2,5 @@ all: dom.html index.html installation.html klacks.html quickstart.html sax.html
|
|||||||
|
|
||||||
%.html: %.xml html.xsl
|
%.html: %.xml html.xsl
|
||||||
xsltproc html.xsl $< >$@.tmp
|
xsltproc html.xsl $< >$@.tmp
|
||||||
mv $@.tmp $@
|
mv -f $@.tmp $@
|
||||||
chmod -w $@
|
chmod -w $@
|
||||||
|
|||||||
@ -70,7 +70,7 @@
|
|||||||
Please refer to the <a href="installation.html#download">
|
Please refer to the <a href="installation.html#download">
|
||||||
installation instructions</a> for details.
|
installation instructions</a> for details.
|
||||||
</div>
|
</div>
|
||||||
<p class="nomargin"><tt>rel-2008-xx-yy</tt></p>
|
<p class="nomargin"><tt>rel-2008-11-30</tt></p>
|
||||||
<ul class="nomargin">
|
<ul class="nomargin">
|
||||||
<li>
|
<li>
|
||||||
Support for user-specified output encodings
|
Support for user-specified output encodings
|
||||||
|
|||||||
7
xml/atdoc-configuration.lisp
Normal file
7
xml/atdoc-configuration.lisp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
(in-package :cxml)
|
||||||
|
|
||||||
|
(defun atdoc-directory ()
|
||||||
|
"doc/atdoc/")
|
||||||
|
|
||||||
|
(defun atdoc-title ()
|
||||||
|
"Closure XML")
|
||||||
@ -11,19 +11,62 @@
|
|||||||
(defclass broadcast-handler (sax:abstract-handler)
|
(defclass broadcast-handler (sax:abstract-handler)
|
||||||
((handlers :initform nil
|
((handlers :initform nil
|
||||||
:initarg :handlers
|
:initarg :handlers
|
||||||
:accessor broadcast-handler-handlers)))
|
:accessor broadcast-handler-handlers))
|
||||||
|
(:documentation
|
||||||
|
"A SAX handler which passes every event it receives on to each of several
|
||||||
|
chained handlers, somewhat similar to the way a @foo{broadcast-stream}
|
||||||
|
works.
|
||||||
|
|
||||||
|
You can subclass @foo{broadcast-handler} to modify the events
|
||||||
|
before they are being passed on. Define methods on your handler
|
||||||
|
class for the events to be modified. All other events will pass
|
||||||
|
through to the chained handlers unmodified.
|
||||||
|
|
||||||
|
Broadcast handler functions return the result of calling the event
|
||||||
|
function on the last handler in the list. In particular,
|
||||||
|
the overall result from @foo{sax:end-document} will be ignored
|
||||||
|
for all other handlers.
|
||||||
|
|
||||||
|
@see-slot{broadcast-handler-handlers}"))
|
||||||
|
|
||||||
|
(setf (documentation #'broadcast-handler-handlers 'function)
|
||||||
|
"@arg[instance]{A @class{broadcast-handler}}
|
||||||
|
@return{A list of @class{SAX handler}s.}
|
||||||
|
|
||||||
|
Returns the list of SAX handlers that arechained to this broadcast
|
||||||
|
handler.")
|
||||||
|
|
||||||
(defun make-broadcast-handler (&rest handlers)
|
(defun make-broadcast-handler (&rest handlers)
|
||||||
|
"@arg[handlers]{A list of @class{SAX handler}s.}
|
||||||
|
@return{A @class{broadcast-handler}.}
|
||||||
|
|
||||||
|
Creates a SAX handler which passes every event it receives on to each
|
||||||
|
handler specified as an argument to this function.
|
||||||
|
|
||||||
|
See @class{broadcast-handler} for details. "
|
||||||
(make-instance 'broadcast-handler :handlers handlers))
|
(make-instance 'broadcast-handler :handlers handlers))
|
||||||
|
|
||||||
(defclass sax-proxy (broadcast-handler)
|
(defclass sax-proxy (broadcast-handler)
|
||||||
())
|
()
|
||||||
|
(:documentation
|
||||||
|
"@class{sax-proxy} is a subclass of @class{broadcast-handler} which
|
||||||
|
sends events to exactly one chained handler.
|
||||||
|
|
||||||
|
This class is still included for compatibility with older versions of
|
||||||
|
CXML which did not include the more general @class{broadcast-handler}
|
||||||
|
yet, but has been retrofitted as a subclass of the latter.
|
||||||
|
|
||||||
|
@see-slot{proxy-chained-handler}"))
|
||||||
|
|
||||||
(defmethod initialize-instance
|
(defmethod initialize-instance
|
||||||
:after ((instance sax-proxy) &key chained-handler)
|
:after ((instance sax-proxy) &key chained-handler)
|
||||||
(setf (proxy-chained-handler instance) chained-handler))
|
(setf (proxy-chained-handler instance) chained-handler))
|
||||||
|
|
||||||
(defmethod proxy-chained-handler ((instance sax-proxy))
|
(defmethod proxy-chained-handler ((instance sax-proxy))
|
||||||
|
"@arg[instance]{A @class{sax-proxy}.}
|
||||||
|
@return{A @class{SAX handler}s.}
|
||||||
|
|
||||||
|
Returns the SAX handler that is chained to this SAX proxy."
|
||||||
(car (broadcast-handler-handlers instance)))
|
(car (broadcast-handler-handlers instance)))
|
||||||
|
|
||||||
(defmethod (setf proxy-chained-handler) (newval (instance sax-proxy))
|
(defmethod (setf proxy-chained-handler) (newval (instance sax-proxy))
|
||||||
|
|||||||
275
xml/unparse.lisp
275
xml/unparse.lisp
@ -142,13 +142,108 @@
|
|||||||
stream))
|
stream))
|
||||||
|
|
||||||
#+rune-is-character
|
#+rune-is-character
|
||||||
(defun make-string-sink (&rest args) (apply #'make-rod-sink args))
|
(defun make-string-sink (&rest args)
|
||||||
|
"@return{A serialization sink, i.e. a @class{SAX handler}}
|
||||||
|
|
||||||
|
Returns a handler that writes processes SAX events by writing an
|
||||||
|
equivalent XML document to a newly allocated string of unicode
|
||||||
|
characters.
|
||||||
|
|
||||||
|
The sink will return the string as a result from
|
||||||
|
@fun{sax:end-document}.
|
||||||
|
|
||||||
|
All sink creation functions share the same keyword arguments.
|
||||||
|
Refer to @fun{make-octet-vector-sink} for details on keyword
|
||||||
|
arguments."
|
||||||
|
(apply #'make-rod-sink args))
|
||||||
|
|
||||||
|
|
||||||
(defmethod sax:end-document ((sink sink))
|
(defmethod sax:end-document ((sink sink))
|
||||||
(close-ystream (sink-ystream sink)))
|
(close-ystream (sink-ystream sink)))
|
||||||
|
|
||||||
|
|
||||||
|
(setf (documentation #'make-octet-vector-sink 'function)
|
||||||
|
"@arg[canonical]{canonical form, one of NIL, T, 1, 2. If specified,
|
||||||
|
serialization in canonical form is enabled. The two canonical
|
||||||
|
forms are useful to allow comparisons of XML documents and their
|
||||||
|
content model by character-by-character comparisons of
|
||||||
|
their serialized representation.}
|
||||||
|
@arg[indentation]{indentation level. An integer or nil. If
|
||||||
|
specified, a pretty-printing indentation mode is enabled. Note
|
||||||
|
that indentation as implemented currently changes the content model
|
||||||
|
unconditionally, and is usually helpful only for debugging purposes.}
|
||||||
|
@arg[encoding]{the character encoding to use. A string or
|
||||||
|
keyword. Values are interpreted by Babel. nil is also allowed
|
||||||
|
and means UTF-8.}
|
||||||
|
@arg[omit-xml-declaration]{Boolean. If true, no XML declaration
|
||||||
|
is written.}
|
||||||
|
@return{A serialization sink, i.e. a @class{SAX handler}}
|
||||||
|
|
||||||
|
Returns a handler that writes processes SAX events by writing an
|
||||||
|
equivalent XML document to a newly allocated vector of
|
||||||
|
@code{(unsigned-byte 8)}.
|
||||||
|
|
||||||
|
The following values for @code{canonical} are allowed:
|
||||||
|
|
||||||
|
@begin{itemize}
|
||||||
|
@item{t or 1: Canonical XML}
|
||||||
|
@item{2: Second Canonical Form}
|
||||||
|
@item{NIL: Use a more readable non-canonical representation.}
|
||||||
|
@end{itemize}
|
||||||
|
|
||||||
|
The sink will return the vector as a result from
|
||||||
|
@fun{sax:end-document}.
|
||||||
|
|
||||||
|
An internal subset will be included in the result regardless of the
|
||||||
|
canonical setting. It is the responsibility of the caller to not
|
||||||
|
report an internal subset for canonical <= 1, or only notations as
|
||||||
|
required for canonical = 2. For example, the include-doctype argument
|
||||||
|
to dom:map-document should be set to nil for the former behaviour and
|
||||||
|
:canonical-notations for the latter. ")
|
||||||
|
|
||||||
|
(setf (documentation #'make-octet-stream-sink 'function)
|
||||||
|
"@arg[stream]{An (unsigned-byte 8) stream.}
|
||||||
|
@return{A serialization sink, i.e. a @class{SAX handler}}
|
||||||
|
|
||||||
|
Returns a handler that writes processes SAX events by writing an
|
||||||
|
equivalent XML document to @var{stream}.
|
||||||
|
|
||||||
|
The sink will return @var{stream} as a result from
|
||||||
|
@fun{sax:end-document}.
|
||||||
|
|
||||||
|
All sink creation functions share the same keyword arguments.
|
||||||
|
Refer to @fun{make-octet-vector-sink} for details on keyword
|
||||||
|
arguments.")
|
||||||
|
|
||||||
|
(setf (documentation #'make-rod-sink 'function)
|
||||||
|
"@return{A serialization sink, i.e. a @class{SAX handler}}
|
||||||
|
|
||||||
|
Returns a handler that writes processes SAX events by writing an
|
||||||
|
equivalent XML document to a newly allocated string of unicode
|
||||||
|
characters (or on implementations without unicode support: a rod).
|
||||||
|
|
||||||
|
The sink will return the string (or rod) as a result from
|
||||||
|
@fun{sax:end-document}.
|
||||||
|
|
||||||
|
All sink creation functions share the same keyword arguments.
|
||||||
|
Refer to @fun{make-octet-vector-sink} for details on keyword
|
||||||
|
arguments.")
|
||||||
|
|
||||||
|
(setf (documentation #'make-character-stream-sink 'function)
|
||||||
|
"@arg[stream]{A character stream.}
|
||||||
|
@return{A serialization sink, i.e. a @class{SAX handler}}
|
||||||
|
|
||||||
|
Returns a handler that writes processes SAX events by writing an
|
||||||
|
equivalent XML document to @var{stream}.
|
||||||
|
|
||||||
|
The sink will return @var{stream} as a result from
|
||||||
|
@fun{sax:end-document}.
|
||||||
|
|
||||||
|
All sink creation functions share the same keyword arguments.
|
||||||
|
Refer to @fun{make-octet-vector-sink} for details on keyword
|
||||||
|
arguments.")
|
||||||
|
|
||||||
|
|
||||||
;;;; doctype and notations
|
;;;; doctype and notations
|
||||||
|
|
||||||
(defmethod sax:start-document ((sink sink))
|
(defmethod sax:start-document ((sink sink))
|
||||||
@ -627,9 +722,54 @@
|
|||||||
(defvar *current-namespace-bindings*)
|
(defvar *current-namespace-bindings*)
|
||||||
|
|
||||||
(defmacro with-xml-output (sink &body body)
|
(defmacro with-xml-output (sink &body body)
|
||||||
|
"@arg[sink]{A @class{SAX handler}, evaluated}
|
||||||
|
@arg[body]{forms}
|
||||||
|
@return{The result of calling @code{sax:end-document} on @code{sink}.}
|
||||||
|
|
||||||
|
Evaluates sink and establishes it as the current output sink for
|
||||||
|
the following \"convenience serialization\" macros and functions:
|
||||||
|
@fun{with-element}, @fun{with-namespace}, @fun{doctype},
|
||||||
|
@fun{with-element*}, @fun{attribute}, @fun{attribute*}, @fun{text}
|
||||||
|
@fun{comment}, @fun{processing-instruction}, @fun{unescaped}.
|
||||||
|
|
||||||
|
Before @code{body} is evaluated, @fun{sax:start-document} is signalled
|
||||||
|
to the @code{sink}. Afterwards, @fun{sax:end-document} is signalled.
|
||||||
|
|
||||||
|
Note that convenience serialization delays some serialization events.
|
||||||
|
For example, @fun{with-element} delays signalling an opening tag
|
||||||
|
using @fun{sax:start-element} until it has information about all
|
||||||
|
possible attributes of the element. Because of this delay, it is
|
||||||
|
not usually safe to signal SAX events to the sink during the extent
|
||||||
|
of @code{with-xml-output}. However, @fun{with-output-sink} can be
|
||||||
|
used to force output of delayed events, allowing direct use of the
|
||||||
|
sink.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
@pre{(with-xml-output (make-octet-stream-sink stream)
|
||||||
|
(with-element \"foo\"
|
||||||
|
(attribute \"xyz\" \"abc\")
|
||||||
|
(with-element \"bar\"
|
||||||
|
(attribute \"blub\" \"bla\"))
|
||||||
|
(text \"Hi there.\")))}"
|
||||||
`(invoke-with-xml-output (lambda () ,@body) ,sink))
|
`(invoke-with-xml-output (lambda () ,@body) ,sink))
|
||||||
|
|
||||||
(defmacro with-output-sink ((var) &body body)
|
(defmacro with-output-sink ((var) &body body)
|
||||||
|
"@arg[var]{A symbol, not evaluated.}
|
||||||
|
@arg[body]{forms, an implicit progn}
|
||||||
|
@return{The result of @code{body}.}
|
||||||
|
|
||||||
|
Allows safe use of manual calls to SAX functions during the extent
|
||||||
|
of @fun{with-xml-output},
|
||||||
|
|
||||||
|
Determines the current output sink established by @fun{with-xml-output},
|
||||||
|
as used by convenience serialization functions. Writes delayed
|
||||||
|
serialization events to the sink. Binds local variable @code{var} to the
|
||||||
|
sink and evaluates @code{body} as an implicit progn.
|
||||||
|
|
||||||
|
The consequences are undefined if this macro is used outside of the
|
||||||
|
extent of a call to @fun{with-xml-output}.
|
||||||
|
|
||||||
|
See @fun{with-xml-output} for details on delayed events."
|
||||||
`(invoke-with-output-sink (lambda (,var) ,@body)))
|
`(invoke-with-output-sink (lambda (,var) ,@body)))
|
||||||
|
|
||||||
(defun invoke-with-xml-output (fn sink)
|
(defun invoke-with-xml-output (fn sink)
|
||||||
@ -646,15 +786,74 @@
|
|||||||
(funcall fn *sink*))
|
(funcall fn *sink*))
|
||||||
|
|
||||||
(defmacro with-element (qname &body body)
|
(defmacro with-element (qname &body body)
|
||||||
|
"@arg[qname]{A string, evaluated.}
|
||||||
|
@arg[body]{forms, an implicit progn}
|
||||||
|
@return{The result of @code{body}.}
|
||||||
|
|
||||||
|
Writes an element to the current output sink.
|
||||||
|
|
||||||
|
This macro is a convenience wrapper around @fun{with-element*}.
|
||||||
|
|
||||||
|
@var{qname} is parsed to determine the element's namespace prefix
|
||||||
|
and local name. Then @fun{with-element*} is called on @var{body} using
|
||||||
|
the resulting values."
|
||||||
`(invoke-with-element (lambda () ,@body) ,qname))
|
`(invoke-with-element (lambda () ,@body) ,qname))
|
||||||
|
|
||||||
(defmacro with-element* ((prefix lname) &body body)
|
(defmacro with-element* ((prefix lname) &body body)
|
||||||
|
"@arg[prefix]{Namespace prefix, a string (evaluated).}
|
||||||
|
@arg[lname]{Local name, a string (evaluated).}
|
||||||
|
@arg[body]{forms, an implicit progn}
|
||||||
|
@return{The result of @code{body}.}
|
||||||
|
|
||||||
|
Writes an element to the current output sink.
|
||||||
|
|
||||||
|
First, @var{prefix} is resolved to a namespace URI using the bindings
|
||||||
|
established by @fun{with-namespace}.
|
||||||
|
|
||||||
|
Next, body is evaluated as an implicit progn. During this time,
|
||||||
|
attributes for the element can be specified using @fun{attribute}.
|
||||||
|
|
||||||
|
Once information on the start tag is complete, @fun{start-element}
|
||||||
|
on the current output sink, using the specified namespace prefix and
|
||||||
|
local name specified by the arguments, the namespace URI computed as
|
||||||
|
described above,and including all attributes collected so far.
|
||||||
|
|
||||||
|
Information on the start tag is considered complete once the first of
|
||||||
|
the following situations occurs:
|
||||||
|
@begin{itemize}
|
||||||
|
@item{Before any child node of the element is written, e.g. using an
|
||||||
|
inner call of @fun{with-element},}
|
||||||
|
@item{Before the body of @fun{with-ouptut-sink} is evaluated.}
|
||||||
|
@item{After the end of @var{body} has been reached.}
|
||||||
|
@end{itemize}
|
||||||
|
|
||||||
|
Finally, sax:end-element is used to write an end tag, using the same
|
||||||
|
qualified name and namespace information as above."
|
||||||
`(invoke-with-element* (lambda () ,@body) ,prefix ,lname))
|
`(invoke-with-element* (lambda () ,@body) ,prefix ,lname))
|
||||||
|
|
||||||
(defmacro with-namespace ((prefix uri) &body body)
|
(defmacro with-namespace ((prefix uri) &body body)
|
||||||
|
"@arg[prefix]{Namespace prefix, a string (evaluated).}
|
||||||
|
@arg[uri]{Namespace URI, a string (evaluated).}
|
||||||
|
@arg[body]{forms, an implicit progn}
|
||||||
|
@return{The result of @code{body}.}
|
||||||
|
|
||||||
|
Registers @code{prefix} as a name for the namespace URI @code{uri}
|
||||||
|
for the extent of body.
|
||||||
|
|
||||||
|
Namespace bindings established by @code{with-namespace} are used by
|
||||||
|
@fun{with-element} and @fun{with-element*} as well as @fun{attribute}
|
||||||
|
and @fun{attribute*}."
|
||||||
`(invoke-with-namespace (lambda () ,@body) ,prefix ,uri))
|
`(invoke-with-namespace (lambda () ,@body) ,prefix ,uri))
|
||||||
|
|
||||||
(defun doctype (name public-id system-id &optional internal-subset)
|
(defun doctype (name public-id system-id &optional internal-subset)
|
||||||
|
"@arg[name]{Element name, a string.}
|
||||||
|
@arg[public-id]{String}
|
||||||
|
@arg[system-id]{A system ID as a @class{puri:uri}.}
|
||||||
|
@arg[internal-subset]{nil or a string}
|
||||||
|
@return{undocumented}
|
||||||
|
|
||||||
|
Writes a doctype declaration to the current output sink, using the
|
||||||
|
specified name, public ID, system ID, and optionally an internal subset."
|
||||||
(sax:start-dtd *sink* name public-id system-id)
|
(sax:start-dtd *sink* name public-id system-id)
|
||||||
(when internal-subset
|
(when internal-subset
|
||||||
(sax:unparsed-internal-subset *sink* internal-subset))
|
(sax:unparsed-internal-subset *sink* internal-subset))
|
||||||
@ -717,12 +916,43 @@
|
|||||||
(defmethod unparse-attribute ((value integer)) (write-to-string value))
|
(defmethod unparse-attribute ((value integer)) (write-to-string value))
|
||||||
|
|
||||||
(defun attribute (qname value)
|
(defun attribute (qname value)
|
||||||
|
"@arg[qname]{Qualified name, a string.}
|
||||||
|
@arg[value]{Any value understood by @fun{unparse-attribute}, in particular
|
||||||
|
strings.}
|
||||||
|
@return{undocumented}
|
||||||
|
|
||||||
|
Collects an attribute for the start tag that is currently being written.
|
||||||
|
|
||||||
|
This function may only be called during the extent of a use of
|
||||||
|
@fun{with-element} or @fun{with-element*}, and only before the first
|
||||||
|
child node has been written.
|
||||||
|
|
||||||
|
An attribute for the current element is recorded using the namespace prefix
|
||||||
|
and local name specified by @var{qname}. The attribute's namespace prefix
|
||||||
|
is resolved to a namespace URI using the bindings established by
|
||||||
|
@fun{with-namespace},and that namespace URI is used for the attribute."
|
||||||
(setf qname (rod qname))
|
(setf qname (rod qname))
|
||||||
(multiple-value-bind (prefix lname)
|
(multiple-value-bind (prefix lname)
|
||||||
(split-qname qname)
|
(split-qname qname)
|
||||||
(attribute* prefix lname value qname)))
|
(attribute* prefix lname value qname)))
|
||||||
|
|
||||||
(defun attribute* (prefix lname value &optional qname)
|
(defun attribute* (prefix lname value &optional qname)
|
||||||
|
"@arg[prefix]{Namespace prefix, a string.}
|
||||||
|
@arg[lname]{Local name, a string.}
|
||||||
|
@arg[value]{Any value understood by @fun{unparse-attribute}, in particular
|
||||||
|
strings.}
|
||||||
|
@return{undocumented}
|
||||||
|
|
||||||
|
Collects an attribute for the start tag that is currently being written.
|
||||||
|
|
||||||
|
This function may only be called during the extent of a use of
|
||||||
|
@fun{with-element} or @fun{with-element*}, and only before the first
|
||||||
|
child node has been written.
|
||||||
|
|
||||||
|
An attribute for the current element is recorded using the namespace prefix
|
||||||
|
and local name specified by arguments. @var{prefix} is resolved to a
|
||||||
|
namespace URI using the bindings established by @fun{with-namespace},
|
||||||
|
and that namespace URI is used for the attribute."
|
||||||
(setf value (unparse-attribute value))
|
(setf value (unparse-attribute value))
|
||||||
(when value
|
(when value
|
||||||
(setf prefix (when prefix (rod prefix)))
|
(setf prefix (when prefix (rod prefix)))
|
||||||
@ -736,6 +966,14 @@
|
|||||||
(cdr *current-element*))))
|
(cdr *current-element*))))
|
||||||
|
|
||||||
(defun cdata (data)
|
(defun cdata (data)
|
||||||
|
"@arg[data]{String.}
|
||||||
|
@return{undocumented}
|
||||||
|
|
||||||
|
Writes a CDATA section to the current output sink, using @code{data} as
|
||||||
|
its contents.
|
||||||
|
|
||||||
|
Note: It is currently the caller's responsibily to ensure that the CDATA
|
||||||
|
section will not contain forbidden character sequences."
|
||||||
(maybe-emit-start-tag)
|
(maybe-emit-start-tag)
|
||||||
(sax:start-cdata *sink*)
|
(sax:start-cdata *sink*)
|
||||||
(sax:characters *sink* (rod data))
|
(sax:characters *sink* (rod data))
|
||||||
@ -743,20 +981,55 @@
|
|||||||
data)
|
data)
|
||||||
|
|
||||||
(defun text (data)
|
(defun text (data)
|
||||||
|
"@arg[data]{String.}
|
||||||
|
@return{undocumented}
|
||||||
|
|
||||||
|
Writes a text node to the current output sink, using @code{data} as
|
||||||
|
its contents.
|
||||||
|
|
||||||
|
Note: It is currently the caller's responsibily to ensure that @code{data}
|
||||||
|
does not contain characters forbidden for character data."
|
||||||
(maybe-emit-start-tag)
|
(maybe-emit-start-tag)
|
||||||
(sax:characters *sink* (rod data))
|
(sax:characters *sink* (rod data))
|
||||||
data)
|
data)
|
||||||
|
|
||||||
(defun comment (data)
|
(defun comment (data)
|
||||||
|
"@arg[data]{String.}
|
||||||
|
@return{undocumented}
|
||||||
|
|
||||||
|
Writes a comment to the current output sink, using @code{data} as
|
||||||
|
its contents.
|
||||||
|
|
||||||
|
Note: It is currently the caller's responsibily to ensure that @code{data}
|
||||||
|
does not contain character sequences forbidden for comments."
|
||||||
(maybe-emit-start-tag)
|
(maybe-emit-start-tag)
|
||||||
(sax:comment *sink* (rod data))
|
(sax:comment *sink* (rod data))
|
||||||
data)
|
data)
|
||||||
|
|
||||||
(defun processing-instruction (target data)
|
(defun processing-instruction (target data)
|
||||||
|
"@arg[target]{String.}
|
||||||
|
@arg[data]{String.}
|
||||||
|
@return{undocumented}
|
||||||
|
|
||||||
|
Writes a processing instruction to the current output sink, using
|
||||||
|
@code{target} and @code{data} as its contents.
|
||||||
|
|
||||||
|
Note: It is currently the caller's responsibily to ensure that
|
||||||
|
@code{target} and @code{data} do not contain character sequences
|
||||||
|
forbidden for processing instruction contents."
|
||||||
(maybe-emit-start-tag)
|
(maybe-emit-start-tag)
|
||||||
(sax:processing-instruction *sink* (rod target) (rod data))
|
(sax:processing-instruction *sink* (rod target) (rod data))
|
||||||
data)
|
data)
|
||||||
|
|
||||||
(defun unescaped (str)
|
(defun unescaped (str)
|
||||||
|
"@arg[data]{String.}
|
||||||
|
@return{undocumented}
|
||||||
|
|
||||||
|
If supported by the current output sink, writes character data directly
|
||||||
|
to the sink's target.
|
||||||
|
|
||||||
|
Use of this function is often an indicator of bad design. Avoid it
|
||||||
|
if you can. (Implementation note: This function is supported because
|
||||||
|
XSLT's XML output method requires it.)"
|
||||||
(maybe-emit-start-tag)
|
(maybe-emit-start-tag)
|
||||||
(sax:unescaped *sink* (rod str)))
|
(sax:unescaped *sink* (rod str)))
|
||||||
|
|||||||
@ -598,9 +598,22 @@
|
|||||||
;;;; DTD
|
;;;; DTD
|
||||||
;;;;
|
;;;;
|
||||||
|
|
||||||
(define-condition xml-parse-error (simple-error) ())
|
(define-condition xml-parse-error (simple-error) ()
|
||||||
(define-condition well-formedness-violation (xml-parse-error) ())
|
(:documentation
|
||||||
(define-condition validity-error (xml-parse-error) ())
|
"Superclass of all conditions signalled by the CXML parser."))
|
||||||
|
|
||||||
|
(define-condition well-formedness-violation (xml-parse-error) ()
|
||||||
|
(:documentation
|
||||||
|
"This condition is signalled for all well-formedness violations.
|
||||||
|
|
||||||
|
Note for validating mode: Sometimes violations of well-formedness are
|
||||||
|
first detected as validity errors by the parser and signalled as
|
||||||
|
instances of @class{validity-error} rather
|
||||||
|
than well-formedness-violation."))
|
||||||
|
|
||||||
|
(define-condition validity-error (xml-parse-error) ()
|
||||||
|
(:documentation
|
||||||
|
"Reports the violation of a validity constraint."))
|
||||||
|
|
||||||
;; We make some effort to signal end of file as a special condition, but we
|
;; We make some effort to signal end of file as a special condition, but we
|
||||||
;; don't actually try very hard. Not sure whether we should. Right now I
|
;; don't actually try very hard. Not sure whether we should. Right now I
|
||||||
@ -912,6 +925,33 @@
|
|||||||
(public nil :type (or rod null))
|
(public nil :type (or rod null))
|
||||||
(system (error "missing argument") :type (or puri:uri null)))
|
(system (error "missing argument") :type (or puri:uri null)))
|
||||||
|
|
||||||
|
(setf (documentation 'extid 'type)
|
||||||
|
"Represents an External ID, consisting of a Public ID and a System ID.
|
||||||
|
|
||||||
|
@see-constructor{make-extiid}
|
||||||
|
@see-slot{exitid-system}
|
||||||
|
@see-slot{exitid-public}")
|
||||||
|
|
||||||
|
(setf (documentation #'make-extid 'function)
|
||||||
|
"@arg[publicid]{string or nil}
|
||||||
|
@arg[systemid]{@class{puri:uri} or nil}
|
||||||
|
@return{an instance of @class{extid}}
|
||||||
|
|
||||||
|
Create an object representing the External ID composed
|
||||||
|
of the specified Public ID and System ID.")
|
||||||
|
|
||||||
|
(setf (documentation #'extid-public 'function)
|
||||||
|
"@arg[extid]{A @class{extid}}
|
||||||
|
@return[publicid]{string or nil}
|
||||||
|
|
||||||
|
Returns the Public ID part of this External ID.")
|
||||||
|
|
||||||
|
(setf (documentation #'extid-system 'function)
|
||||||
|
"@arg[extid]{A @class{extid}}
|
||||||
|
@return[sytemid]{puri:uri or nil}
|
||||||
|
|
||||||
|
Returns the System ID part of this External ID.")
|
||||||
|
|
||||||
(defun absolute-extid (source-stream extid)
|
(defun absolute-extid (source-stream extid)
|
||||||
(let ((sysid (extid-system extid))
|
(let ((sysid (extid-system extid))
|
||||||
(result (copy-extid extid)))
|
(result (copy-extid extid)))
|
||||||
@ -3099,6 +3139,49 @@
|
|||||||
(input handler &rest args
|
(input handler &rest args
|
||||||
&key validate dtd root entity-resolver disallow-internal-subset
|
&key validate dtd root entity-resolver disallow-internal-subset
|
||||||
recode pathname)
|
recode pathname)
|
||||||
|
"@arg[input]{A string, pathname, octet vector, or stream.}
|
||||||
|
@arg[handler]{A @class{SAX handler}}
|
||||||
|
@arg[validate]{Boolean. Defaults to @code{nil}. If true, parse in
|
||||||
|
validating mode, i.e. assert that the document contains a DOCTYPE
|
||||||
|
declaration and conforms to the DTD declared.}
|
||||||
|
@arg[dtd]{unless @code{nil}, an extid instance specifying the external
|
||||||
|
subset to load. This options overrides the extid specified in the
|
||||||
|
document type declaration, if any. See below for @fun{make-extid}.
|
||||||
|
This option is useful for verification purposes together with the
|
||||||
|
@var{root} and @var{disallow-internal-subset} arguments.}
|
||||||
|
@arg[root]{The expected root element name, or @code{nil} (the default).
|
||||||
|
If specified, this argument overrides the name stated in the input's
|
||||||
|
DOCTYPE (if any).}
|
||||||
|
@arg[entity-resolver]{@code{nil} or a function of two arguments which
|
||||||
|
is invoked for every entity referenced by the document with the
|
||||||
|
entity's Public ID (a rod) and System ID (an URI object) as arguments.
|
||||||
|
The function may either return nil, CXML will then try to resolve the
|
||||||
|
entity as usual. Alternatively it may return a Common Lisp stream
|
||||||
|
specialized on @code{(unsigned-byte 8)} which will be used instead.
|
||||||
|
(It may also signal an error, of course, which can be useful to prohibit
|
||||||
|
parsed XML documents from including arbitrary files readable by
|
||||||
|
the parser.)}
|
||||||
|
@arg[disallow-internal-subset]{Boolean. If true, signal
|
||||||
|
an error if the document contains an internal subset.}
|
||||||
|
@arg[recode]{Boolean. (Ignored on Lisps with Unicode
|
||||||
|
support.) Recode rods to UTF-8 strings. Defaults to true.
|
||||||
|
Make sure to use @fun{utf8-dom:make-dom-builder} if this
|
||||||
|
option is enabled and @fun{rune-dom:make-dom-builder}
|
||||||
|
otherwise.}
|
||||||
|
@return{The value returned by @fun{sax:end-document} on @var{handler}.}
|
||||||
|
|
||||||
|
Parse an XML document from @var{input}, which can be a string, pathname,
|
||||||
|
octet vector, or stream.
|
||||||
|
|
||||||
|
Return values from this function depend on the SAX handler used.
|
||||||
|
This is an old-style convenience wrapper around the new-style interface
|
||||||
|
@fun{parse}.
|
||||||
|
|
||||||
|
Parse an XML document from @var{filename}, and signal SAX events to
|
||||||
|
@var{handler} while doing so.
|
||||||
|
|
||||||
|
All SAX parsing functions share the same keyword arguments. Refer to
|
||||||
|
@fun{parse} for details on keyword arguments."
|
||||||
(declare (ignore validate dtd root entity-resolver disallow-internal-subset
|
(declare (ignore validate dtd root entity-resolver disallow-internal-subset
|
||||||
recode))
|
recode))
|
||||||
(let ((args
|
(let ((args
|
||||||
@ -3133,6 +3216,18 @@
|
|||||||
(wf-error xstream "~A" c)))))
|
(wf-error xstream "~A" c)))))
|
||||||
|
|
||||||
(defun parse-file (filename handler &rest args)
|
(defun parse-file (filename handler &rest args)
|
||||||
|
"@arg[filename]{An pathname designator.}
|
||||||
|
@arg[handler]{A @class{SAX handler}}
|
||||||
|
@return{The value returned by @fun{sax:end-document} on @var{handler}.}
|
||||||
|
|
||||||
|
This is an old-style convenience wrapper around the new-style interface
|
||||||
|
@fun{parse}.
|
||||||
|
|
||||||
|
Parse an XML document from @var{filename}, and signal SAX events to
|
||||||
|
@var{handler} while doing so.
|
||||||
|
|
||||||
|
All SAX parsing functions share the same keyword arguments. Refer to
|
||||||
|
@fun{parse} for details on keyword arguments."
|
||||||
(with-open-xfile (input filename)
|
(with-open-xfile (input filename)
|
||||||
(setf (xstream-name input)
|
(setf (xstream-name input)
|
||||||
(make-stream-name
|
(make-stream-name
|
||||||
@ -3154,7 +3249,46 @@
|
|||||||
(pathname-to-uri (merge-pathnames (pathname stream)))
|
(pathname-to-uri (merge-pathnames (pathname stream)))
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
|
(deftype |SAX HANDLER| ()
|
||||||
|
'sax:abstract-handler
|
||||||
|
"Historically, any object has been usable as a SAX handler with CXML,
|
||||||
|
as long as it implemented all SAX events, i.e. had methods
|
||||||
|
for the generic functions defined in the SAX package.
|
||||||
|
|
||||||
|
While this approach still works, it is now recommended that SAX handlers
|
||||||
|
should be implemented by subclassing @class{abstract-handler} or one
|
||||||
|
of its subclasses. Useful subclasses are @class{content-handler}
|
||||||
|
and @class{default-handler}.
|
||||||
|
|
||||||
|
(In addition, the value @code{nil} is valid SAX handler, which discards
|
||||||
|
all events it receives.)
|
||||||
|
|
||||||
|
As a rule of thumb, write a subclass of @class{default-handler} if
|
||||||
|
you want to handle only a few special SAX events and ignore the rest,
|
||||||
|
because this class has no-op default methods for all events.
|
||||||
|
|
||||||
|
If, however, you want to make certain that your class implements all
|
||||||
|
important SAX events explicitly, a good choice is @class{content-handler},
|
||||||
|
which has no-op default methods only for less important, DTD-related
|
||||||
|
events, and requires subclasses to implement all events related to the
|
||||||
|
content model.
|
||||||
|
|
||||||
|
In some cases, it might be helpful to implement @class{abstract-handler}
|
||||||
|
directly, which has no default event methods at all.")
|
||||||
|
|
||||||
(defun parse-stream (stream handler &rest args)
|
(defun parse-stream (stream handler &rest args)
|
||||||
|
"@arg[stream]{An (unsigned-byte 8) stream}
|
||||||
|
@arg[handler]{A @class{SAX handler}}
|
||||||
|
@return{The value returned by @fun{sax:end-document} on @var{handler}.}
|
||||||
|
|
||||||
|
This is an old-style convenience wrapper around the new-style interface
|
||||||
|
@fun{parse}.
|
||||||
|
|
||||||
|
Parse an XML document from @var{stream}, and signal SAX events to
|
||||||
|
@var{handler} while doing so.
|
||||||
|
|
||||||
|
All SAX parsing functions share the same keyword arguments. Refer to
|
||||||
|
@fun{parse} for details on keyword arguments."
|
||||||
(let ((xstream
|
(let ((xstream
|
||||||
(make-xstream
|
(make-xstream
|
||||||
stream
|
stream
|
||||||
@ -3167,6 +3301,33 @@
|
|||||||
|
|
||||||
(defun parse-empty-document
|
(defun parse-empty-document
|
||||||
(uri qname handler &key public-id system-id entity-resolver (recode t))
|
(uri qname handler &key public-id system-id entity-resolver (recode t))
|
||||||
|
"@arg[uri]{a string or nil}
|
||||||
|
@arg[qname]{a string or nil}
|
||||||
|
@arg[handler]{a @class{SAX handler}}
|
||||||
|
@arg[public-id]{a string or nil}
|
||||||
|
@arg[system-id]{a @type{puri:uri} or nil}
|
||||||
|
@arg[entity-resolver]{@code{nil} or a function of two arguments which
|
||||||
|
is invoked for every entity referenced by the document with the
|
||||||
|
entity's Public ID (a rod) and System ID (an URI object) as arguments.
|
||||||
|
The function may either return nil, CXML will then try to resolve the
|
||||||
|
entity as usual. Alternatively it may return a Common Lisp stream
|
||||||
|
specialized on @code{(unsigned-byte 8)} which will be used instead.
|
||||||
|
(It may also signal an error, of course, which can be useful to prohibit
|
||||||
|
parsed XML documents from including arbitrary files readable by
|
||||||
|
the parser.)}
|
||||||
|
@arg[recode]{Boolean. (Ignored on Lisps with Unicode
|
||||||
|
support.) Recode rods to UTF-8 strings. Defaults to true.
|
||||||
|
Make sure to use @fun{utf8-dom:make-dom-builder} if this
|
||||||
|
option is enabled and @fun{rune-dom:make-dom-builder}
|
||||||
|
otherwise.}
|
||||||
|
@return{The value returned by @fun{sax:end-document} on @var{handler}.}
|
||||||
|
|
||||||
|
Simulate parsing of a document with a document element @var{qname}
|
||||||
|
having no attributes except for an optional namespace
|
||||||
|
declaration to @var{uri}. If an external ID is specified
|
||||||
|
(@var{system-id}, @var{public-id}), find, parse, and report
|
||||||
|
this DTD as if with @fun{parse-file}, using the specified
|
||||||
|
entity resolver."
|
||||||
(check-type uri (or null rod))
|
(check-type uri (or null rod))
|
||||||
(check-type qname (or null rod))
|
(check-type qname (or null rod))
|
||||||
(check-type public-id (or null rod))
|
(check-type public-id (or null rod))
|
||||||
@ -3224,10 +3385,24 @@
|
|||||||
(sax:end-document handler)))
|
(sax:end-document handler)))
|
||||||
|
|
||||||
(defun parse-dtd-file (filename &optional handler)
|
(defun parse-dtd-file (filename &optional handler)
|
||||||
|
"@arg[filename]{An pathname designator.}
|
||||||
|
@arg[handler]{A @class{SAX handler}}
|
||||||
|
@return{A @class{dtd} instance.}
|
||||||
|
|
||||||
|
Parse @a[http://www.w3.org/TR/2000/REC-xml-20001006#NT-extSubset]{declarations}
|
||||||
|
from @var{filename} and return an object representing the DTD,
|
||||||
|
suitable as an argument to @code{validate} with @fun{parse}."
|
||||||
(with-open-file (s filename :element-type '(unsigned-byte 8))
|
(with-open-file (s filename :element-type '(unsigned-byte 8))
|
||||||
(parse-dtd-stream s handler)))
|
(parse-dtd-stream s handler)))
|
||||||
|
|
||||||
(defun parse-dtd-stream (stream &optional handler)
|
(defun parse-dtd-stream (stream &optional handler)
|
||||||
|
"@arg[stream]{An (unsigned-byte 8) stream.}
|
||||||
|
@arg[handler]{A @class{SAX handler}}
|
||||||
|
@return{A @class{dtd} instance.}
|
||||||
|
|
||||||
|
Parse @a[http://www.w3.org/TR/2000/REC-xml-20001006#NT-extSubset]{declarations}
|
||||||
|
from @var{stream} and return an object representing the DTD,
|
||||||
|
suitable as an argument to @code{validate} with @fun{parse}."
|
||||||
(let ((input (make-xstream stream)))
|
(let ((input (make-xstream stream)))
|
||||||
(setf (xstream-name input)
|
(setf (xstream-name input)
|
||||||
(make-stream-name
|
(make-stream-name
|
||||||
@ -3245,6 +3420,22 @@
|
|||||||
(dtd *ctx*))))))
|
(dtd *ctx*))))))
|
||||||
|
|
||||||
(defun parse-rod (string handler &rest args)
|
(defun parse-rod (string handler &rest args)
|
||||||
|
"@arg[string]{An string of unicode characters.}
|
||||||
|
@arg[handler]{A @class{SAX handler}}
|
||||||
|
@return{The value returned by @fun{sax:end-document} on @var{handler}.}
|
||||||
|
|
||||||
|
This is an old-style convenience wrapper around the new-style interface
|
||||||
|
@fun{parse}.
|
||||||
|
|
||||||
|
Parse an XML document from @var{string}, and signal SAX events to
|
||||||
|
@var{handler} while doing so.
|
||||||
|
|
||||||
|
Note: This function assumes that @var{string} has already been decoded into
|
||||||
|
Unicode runes and ignores the encoding specified in the XML declaration,
|
||||||
|
if any.
|
||||||
|
|
||||||
|
All SAX parsing functions share the same keyword arguments. Refer to
|
||||||
|
@fun{parse} for details on keyword arguments."
|
||||||
(let ((xstream (string->xstream string)))
|
(let ((xstream (string->xstream string)))
|
||||||
(setf (xstream-name xstream)
|
(setf (xstream-name xstream)
|
||||||
(make-stream-name
|
(make-stream-name
|
||||||
@ -3257,6 +3448,18 @@
|
|||||||
(make-rod-xstream (string-rod string)))
|
(make-rod-xstream (string-rod string)))
|
||||||
|
|
||||||
(defun parse-octets (octets handler &rest args)
|
(defun parse-octets (octets handler &rest args)
|
||||||
|
"@arg[octets]{An (unsigned-byte 8) vector.}
|
||||||
|
@arg[handler]{A @class{SAX handler}}
|
||||||
|
@return{The value returned by @fun{sax:end-document} on @var{handler}.}
|
||||||
|
|
||||||
|
This is an old-style convenience wrapper around the new-style interface
|
||||||
|
@fun{parse}.
|
||||||
|
|
||||||
|
Parse an XML document from @var{octets}, and signal SAX events to
|
||||||
|
@var{handler} while doing so.
|
||||||
|
|
||||||
|
All SAX parsing functions share the same keyword arguments. Refer to
|
||||||
|
@fun{parse} for details on keyword arguments."
|
||||||
(apply #'parse-stream (make-octet-input-stream octets) handler args))
|
(apply #'parse-stream (make-octet-input-stream octets) handler args))
|
||||||
|
|
||||||
;;;;
|
;;;;
|
||||||
@ -3705,6 +3908,22 @@
|
|||||||
(cdatap :initform nil :accessor cdatap)))
|
(cdatap :initform nil :accessor cdatap)))
|
||||||
|
|
||||||
(defun make-validator (dtd root)
|
(defun make-validator (dtd root)
|
||||||
|
"@arg[dtd]{An @class{dtd} instance.}
|
||||||
|
@arg[root]{Element name, a string.}
|
||||||
|
@return{A @class{SAX handler}.}
|
||||||
|
|
||||||
|
Create a SAX handler which validates against a DTD instance.
|
||||||
|
The document's root element must be named @code{root}.
|
||||||
|
Used with @fun{dom:map-document}, this validates a document
|
||||||
|
object as if by re-reading it with a validating parser, except
|
||||||
|
that declarations recorded in the document instance are completely
|
||||||
|
ignored.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
@pre{(let ((d (parse-file \"~/test.xml\" (cxml-dom:make-dom-builder)))
|
||||||
|
(x (parse-dtd-file \"~/test.dtd\")))
|
||||||
|
(dom:map-document (cxml:make-validator x #\"foo\") d))}"
|
||||||
(make-instance 'validator
|
(make-instance 'validator
|
||||||
:context (make-context
|
:context (make-context
|
||||||
:handler nil
|
:handler nil
|
||||||
|
|||||||
@ -31,6 +31,12 @@
|
|||||||
(defvar *xmlns-namespace* #"http://www.w3.org/2000/xmlns/")
|
(defvar *xmlns-namespace* #"http://www.w3.org/2000/xmlns/")
|
||||||
|
|
||||||
(defun make-namespace-normalizer (chained-handler)
|
(defun make-namespace-normalizer (chained-handler)
|
||||||
|
"@arg[chained-handler]{A @class{SAX handler}.}
|
||||||
|
@return{A @class{SAX handler}.}
|
||||||
|
|
||||||
|
Return a SAX handler that performs @a[http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#normalizeDocumentAlgo]{DOM
|
||||||
|
3-style namespace normalization} on attribute lists in
|
||||||
|
@fun{sax:start-element} events before passing them on the next handler."
|
||||||
(make-instance 'namespace-normalizer
|
(make-instance 'namespace-normalizer
|
||||||
:xmlns-stack (list (mapcar (lambda (cons)
|
:xmlns-stack (list (mapcar (lambda (cons)
|
||||||
(make-xmlns-attribute (car cons) (cdr cons)))
|
(make-xmlns-attribute (car cons) (cdr cons)))
|
||||||
|
|||||||
Reference in New Issue
Block a user