Fixed (setf document-element) in the presence of non-element children
[cxml-stp.git] / classes.lisp
blob026cfc30dc327427b99cc8b88eb481bc74ef311b
1 ;;; -*- show-trailing-whitespace: t; indent-tabs: nil -*-
3 ;;; Copyright (c) 2007 David Lichteblau. All rights reserved.
5 ;;; Redistribution and use in source and binary forms, with or without
6 ;;; modification, are permitted provided that the following conditions
7 ;;; are met:
8 ;;;
9 ;;; * Redistributions of source code must retain the above copyright
10 ;;; notice, this list of conditions and the following disclaimer.
11 ;;;
12 ;;; * Redistributions in binary form must reproduce the above
13 ;;; copyright notice, this list of conditions and the following
14 ;;; disclaimer in the documentation and/or other materials
15 ;;; provided with the distribution.
16 ;;;
17 ;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
18 ;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 ;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21 ;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 ;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 ;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 ;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 ;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 (in-package :cxml-stp-impl)
31 #+sbcl
32 (declaim (optimize (debug 2)))
34 (defclass named-node-mixin ()
35 ((local-name :reader local-name :accessor %local-name)
36 (prefix :initform nil
37 :reader namespace-prefix
38 :accessor %namespace-prefix)
39 (namespace-uri :initform nil
40 :reader namespace-uri
41 :accessor %namespace-uri)))
43 (defclass attribute (leaf-node named-node-mixin)
44 ((value :accessor value))
45 (:documentation
46 "@short{Instances of this class represent attributes of an @class{element},
47 excluding namespace declarations.}
49 The @fun{parent} of an attribute is always an @class{element} or nil,
50 but the attribute is not a child of that element.
52 @see-slot{local-name}
53 @see-slot{namespace-prefix}
54 @see-slot{namespace-uri}
55 @see-slot{qualified-name}
56 @see-slot{value}
57 @see{list-attributes}
58 @see-constructor{make-attribute}"))
60 (defclass comment (leaf-node)
61 ((data :initarg :data :accessor data))
62 (:documentation
63 "Instances of this class represent XML comments.
64 @see-slot{data}
65 @see-constructor{make-comment}"))
67 (defclass cxml-stp:document-type (leaf-node)
68 ((root-element-name :accessor root-element-name)
69 (system-id :initform nil :accessor system-id)
70 (public-id :initform nil :accessor public-id)
71 (internal-subset :initform nil :accessor internal-subset)
72 (dtd :initform nil :accessor dtd))
73 (:documentation
74 "@short{Instances of this class represent the DOCTYPE declaration at the
75 beginning of a document.}
77 The document type is an optional child of a @class{document}. At most
78 one document type is allowed, and it must precede the document element.
80 Since STP checks well-formedness only, not validity, the document type
81 only declares what DTD the document claims to be conforming to, but
82 does not guarantee that it actually does.
84 @see-constructor{make-document-type}
85 @see-slot{root-element-name}
86 @see-slot{system-id}
87 @see-slot{public-id}
88 @see-slot{internal-subset}"))
89 (setf (find-class 'document-type) (find-class 'cxml-stp:document-type))
91 (defclass cxml-stp:document (parent-node) ()
92 (:documentation
93 "@short{Instances of this class represent an entire XML document.}
95 A document may have at most one document-type, and must have exactly one
96 element as a child (in this order).
98 It may also have comments and processing-instructions anywhere.
100 @see-constructor{make-document}
101 @see-slot{document-element}
102 @see-slot{document-type}"))
103 (setf (find-class 'document) (find-class 'cxml-stp:document))
105 (defclass element (parent-node named-node-mixin)
106 ((attributes :initform nil :accessor %attributes)
107 (namespaces :initform nil :accessor %namespaces))
108 (:documentation
109 "@short{Instances of this class represent XML elements with their attributes
110 and namespaces.}
112 See @class{node} for functions to query the list of children.
114 See @class{parent-node} for functions to add or remove children.
116 @see-slot{local-name}
117 @see-slot{namespace-prefix}
118 @see-slot{namespace-uri}
119 @see-slot{qualified-name}
120 @see{add-attribute}
121 @see{remove-attribute}
122 @see{find-attribute-named}
123 @see{find-attribute-if}
124 @see{with-attributes}
125 @see{list-attributes}
126 @see{map-attributes}
127 @see{attribute-value}
128 @see{find-namespace}
129 @see{find-attribute-namespace}
130 @see{find-local-namespace}
131 @see{find-extra-namespace}
132 @see{add-extra-namespace}
133 @see{remove-extra-namespace}
134 @see{map-extra-namespaces}
135 @see-constructor{make-element}"))
137 (defclass leaf-node (node) ())
139 (defclass node ()
140 ((parent :initform nil :reader parent :writer (setf %parent)))
141 (:documentation
142 "@short{The superclass of all nodes.}
144 Although only @class{document} and @class{element} allow children,
145 read-only functions accessing the list of children are available for
146 all nodes and always return zero children for other classes.
148 @see-slot{parent}
149 @see-slot{base-uri}
150 @see{document}
151 @see{root}
152 @see{detach}
153 @see{copy}
154 @see{serialize}
155 @see{map-children}
156 @see{do-children}
157 @see{list-children}
158 @see{first-child}
159 @see{last-child}
160 @see{nth-child}
161 @see{previous-sibling}
162 @see{next-sibling}
163 @see{count-children}
164 @see{find-child}
165 @see{child-position}
166 @see{count-children-if}
167 @see{find-child-if}
168 @see{child-position-if}
169 @see{filter-children}
170 @see{map-recursively}
171 @see{do-recursively}
172 @see{find-recursively}
173 @see{filter-recursively}"))
175 (defclass parent-node (node)
176 ((%base-uri :initform nil)
177 (%children :initform nil :accessor %children))
178 (:documentation
179 "@short{Instances of this class can have children.}
181 See @class{node} for functions to query the list of children without
182 changing it.
184 @see{prepend-child}
185 @see{append-child}
186 @see{delete-nth-child}
187 @see{delete-child}
188 @see{insert-child-before}
189 @see{insert-child-after}
190 @see{replace-child}
191 @see{insert-child}
192 @see{delete-child-if}
193 @see{replace-children}"))
195 (defclass processing-instruction (leaf-node)
196 ((target :initarg :target :accessor target)
197 (data :initarg :data :accessor data))
198 (:documentation
199 "Instances of this class represent processing instructions.
200 @see-slot{target}
201 @see-slot{data}
202 @see-constructor{make-processing-instruction}"))
204 (defclass text (leaf-node)
205 ((data :initarg :data :accessor data))
206 (:documentation
207 "Instances of this class represent text nodes.
208 @see-slot{data}
209 @see-constructor{make-text}"))