]> err.no Git - sope/blob - sope-xml/DOM/DOMDocument.m
fixed copyrights for 2005
[sope] / sope-xml / DOM / DOMDocument.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #include <DOM/DOMDocument.h>
23 #include <DOM/DOMImplementation.h>
24 #include <DOM/DOMElement.h>
25 #include <DOM/DOMNodeWalker.h>
26 #include <DOM/DOMProcessingInstruction.h>
27 #include <DOM/DOMElement.h>
28 #include <DOM/DOMAttribute.h>
29 #include <DOM/DOMEntityReference.h>
30 #include "DOMSaxBuilder.h"
31 #include "common.h"
32
33 //#define PROF_DEALLOC 1
34
35 @implementation DOMDocument
36
37 + (id)documentFromData:(NSData *)_data {
38   id builder;
39   
40   builder = [[[DOMSaxBuilder alloc] init] autorelease];
41   return [builder buildFromData:_data];
42 }
43 + (id)documentFromString:(NSString *)_string {
44   return [self documentFromData:
45                  [_string dataUsingEncoding:NSISOLatin1StringEncoding]];
46 }
47 + (id)documentFromURI:(NSString *)_uri {
48   id builder;
49   
50   builder = [[[DOMSaxBuilder alloc] init] autorelease];
51   return [builder buildFromContentsOfFile:_uri];
52 }
53
54 - (id)initWithName:(NSString *)_qname
55   namespaceURI:(NSString *)_uri
56   documentType:(id)_doctype
57   dom:(DOMImplementation *)_dom
58 {
59   self->dom     = [_dom   retain];
60   self->qname   = [_qname copy];
61   self->uri     = [_uri   copy];
62   self->doctype = [_doctype retain];
63   return self;
64 }
65
66 - (void)dealloc {
67 #if PROF_DEALLOC
68   NSDate *start = [NSDate date];
69 #endif
70
71   [self->errors   release];
72   [self->warnings release];
73   [self->dom      release];
74   [self->qname    release];
75   [self->uri      release];
76   [self->doctype  release];
77   [super dealloc];
78
79 #if PROF_DEALLOC
80   printf("%s: %.3fs\n", __PRETTY_FUNCTION__,
81          [NSDate timeIntervalSinceDate:start]);
82 #endif
83 }
84
85 /* errors/warnings */
86
87 - (void)addErrors:(NSArray *)_errors {
88   if (self->errors == nil)
89     self->errors = [_errors copy];
90   else {
91     NSArray *tmp;
92
93     tmp = self->errors;
94     self->errors = [[tmp arrayByAddingObjectsFromArray:_errors] copy];
95     [tmp release];
96   }
97 }
98 - (void)addWarnings:(NSArray *)_errors {
99   if (self->warnings == nil)
100     self->warnings = [_errors copy];
101   else {
102     NSArray *tmp;
103
104     tmp = self->warnings;
105     self->warnings = [[tmp arrayByAddingObjectsFromArray:_errors] copy];
106     [tmp release];
107   }
108 }
109
110 /* attributes */
111
112 - (id)doctype {
113   return self->doctype;
114 }
115 - (DOMImplementation *)implementation {
116   return self->dom;
117 }
118
119 - (id)documentElement {
120   id children;
121   unsigned i, count;
122   
123   if ((children = [self childNodes]) == nil)
124     return nil;
125   
126   for (i = 0, count = [children count]; i < count; i++) {
127     id node;
128
129     node = [children objectAtIndex:i];
130     if ([node nodeType] == DOM_ELEMENT_NODE)
131       return node;
132   }
133   return nil;
134 }
135
136 /* node */
137
138 - (BOOL)_isValidChildNode:(id)_node {
139   switch ([_node nodeType]) {
140     case DOM_ELEMENT_NODE:
141     case DOM_PROCESSING_INSTRUCTION_NODE:
142     case DOM_COMMENT_NODE:
143     case DOM_DOCUMENT_TYPE_NODE:
144       return YES;
145       
146     default:
147       return NO;
148   }
149 }
150
151 - (DOMNodeType)nodeType {
152   return DOM_DOCUMENT_NODE;
153 }
154
155 - (id)attributes {
156   return nil;
157 }
158
159 - (DOMDocument *)ownerDocument {
160   return nil;
161 }
162
163 - (id)parentNode {
164   /* document cannot be nested */
165   return nil;
166 }
167 - (id)nextSibling {
168   /* document cannot be nested */
169   return nil;
170 }
171 - (id)previousSibling {
172   /* document cannot be nested */
173   return nil;
174 }
175
176 - (void)_walk_getElementsByTagName:(id)_walker {
177   id node;
178   
179   node = [_walker currentNode];
180   if ([node nodeType] != DOM_ELEMENT_NODE)
181     return;
182
183   if (![[node tagName] isEqualToString:
184           [(NSArray *)[_walker context] objectAtIndex:0]])
185     /* tagname doesn't match */
186     return;
187   
188   [[(NSArray *)[_walker context] objectAtIndex:1] addObject:node];
189 }
190 - (void)_walk_getElementsByTagNameAddAll:(id)_walker {
191   id node;
192   
193   node = [_walker currentNode];
194   if ([node nodeType] != DOM_ELEMENT_NODE)
195     return;
196   
197   [(NSMutableArray *)[_walker context] addObject:node];
198 }
199 - (id)getElementsByTagName:(NSString *)_tagName {
200   /* introduced in DOM2, should return a *live* list ! */
201   NSMutableArray        *array;
202   DOMNodePreorderWalker *walker;
203   SEL sel;
204   id  ctx;
205   
206   if (![self hasChildNodes])
207     return nil;
208
209   if (_tagName == nil)
210     return nil;
211
212   array = [NSMutableArray array];
213   
214   if ([_tagName isEqualToString:@"*"]) {
215     _tagName = nil;
216     ctx = array;
217     sel = @selector(_walk_getElementsByTagNameAddAll:);
218   }
219   else {
220     ctx = [NSArray arrayWithObjects:_tagName, array, nil];
221     sel = @selector(_walk_getElementsByTagName:);
222   }
223   
224   walker = [[DOMNodePreorderWalker alloc]
225                                    initWithTarget:self
226                                    selector:sel
227                                    context:ctx];
228   
229   [walker walkNode:self];
230
231   [walker release]; walker = nil;
232   
233   return [[array copy] autorelease];
234 }
235 - (id)getElementsByTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri {
236   [self doesNotRecognizeSelector:_cmd];
237   return nil;
238 }
239
240 - (id)getElementById:(NSString *)_eid {
241   /*
242     Introduced in DOM2
243     
244     Note: The DOM implementation must have information that says which
245     attributes are of type ID. Attributes with the name "ID" are not of
246     type ID unless so defined.
247     Implementations that do not know whether attributes are of type ID
248     or not are expected to return null.
249   */
250   return nil;
251 }
252
253 /* factory */
254
255 - (Class)domElementClass {
256   return [self->dom domElementClass];
257 }
258 - (Class)domElementNSClass {
259   return [self->dom domElementNSClass];
260 }
261 - (Class)domDocumentFragmentClass {
262   return [self->dom domDocumentFragmentClass];
263 }
264 - (Class)domTextNodeClass {
265   return [self->dom domTextNodeClass];
266 }
267 - (Class)domCommentClass {
268   return [self->dom domCommentClass];
269 }
270 - (Class)domCDATAClass {
271   return [self->dom domCDATAClass];
272 }
273 - (Class)domProcessingInstructionClass {
274   return [self->dom domProcessingInstructionClass];
275 }
276 - (Class)domAttributeClass {
277   return [self->dom domAttributeClass];
278 }
279 - (Class)domAttributeNSClass {
280   return [self->dom domAttributeNSClass];
281 }
282 - (Class)domEntityReferenceClass {
283   return [self->dom domEntityReferenceClass];
284 }
285
286 - (id)createElement:(NSString *)_tagName {
287   id elem;
288   elem = [[[self domElementClass] 
289                  alloc] 
290                  initWithTagName:_tagName];
291   return [elem autorelease];
292 }
293 - (id)createElement:(NSString *)_tagName namespaceURI:(NSString *)_uri {
294   id elem;
295   elem = [[[self domElementNSClass] 
296                  alloc] 
297                  initWithTagName:_tagName namespaceURI:_uri];
298   return [elem autorelease];
299 }
300
301 - (id)createDocumentFragment {
302   id elem;
303   elem = [[[self domDocumentFragmentClass] alloc] init];
304   return [elem autorelease];
305 }
306
307 - (id)createTextNode:(NSString *)_data {
308   id elem;
309   elem = [[[self domTextNodeClass] alloc] initWithString:_data];
310   return [elem autorelease];
311 }
312 - (id)createComment:(NSString *)_data {
313   id elem;
314   elem = [[[self domCommentClass] alloc] initWithString:_data];
315   return [elem autorelease];
316 }
317 - (id)createCDATASection:(NSString *)_data {
318   id elem;
319   elem = [[[self domCDATAClass] alloc] initWithString:_data];
320   return [elem autorelease];
321 }
322
323 - (id)createProcessingInstruction:(NSString *)_target data:(NSString *)_data {
324   id elem;
325   elem = [[[self domProcessingInstructionClass] 
326                  alloc] 
327                  initWithTarget:_target data:_data];
328   return [elem autorelease];
329 }
330
331 - (id)createAttribute:(NSString *)_name {
332   id elem;
333   elem = [[[self domAttributeClass] 
334                  alloc]
335                  initWithName:_name];
336   return [elem autorelease];
337 }
338 - (id)createAttribute:(NSString *)_name namespaceURI:(NSString *)_uri {
339   id elem;
340   elem = [[[self domAttributeNSClass] 
341                  alloc]
342                  initWithName:_name namespaceURI:_uri];
343   return [elem autorelease];
344 }
345
346 - (id)createEntityReference:(NSString *)_name {
347   id elem;
348   elem = [[[self domEntityReferenceClass] alloc] initWithName:_name];
349   return [elem autorelease];
350 }
351
352 @end /* DOMDocument */
353
354 @implementation DOMDocument(QPValues)
355
356 - (NSException *)setQueryPathValue:(id)_value {
357   return [NSException exceptionWithName:@"QueryPathEvalException"
358                       reason:@"cannot set query-path value on DOMDocument !"
359                       userInfo:nil];
360 }
361 - (id)queryPathValue {
362   return [self documentElement];
363 }
364
365 @end /* DOMDocument(QPValues) */