]> err.no Git - sope/blob - sope-xml/DOM/DOMDocument.m
code reorgs
[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 NGDOMDocument
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:(NGDOMImplementation *)_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<NSObject,DOMDocumentType>)doctype {
113   return self->doctype;
114 }
115 - (NGDOMImplementation *)implementation {
116   return self->dom;
117 }
118
119 - (id<NSObject,DOMElement>)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<NSObject,DOMNamedNodeMap>)attributes {
156   return nil;
157 }
158
159 - (IDOMDocument)ownerDocument {
160   return nil;
161 }
162
163 - (id<NSObject,DOMNode>)parentNode {
164   /* document cannot be nested */
165   return nil;
166 }
167 - (id<NSObject,DOMNode>)nextSibling {
168   /* document cannot be nested */
169   return nil;
170 }
171 - (id<NSObject,DOMNode>)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<NSObject,DOMNodeList>)getElementsByTagName:(NSString *)_tagName {
200   /* introduced in DOM2, should return a *live* list ! */
201   NSMutableArray          *array;
202   NGDOMNodePreorderWalker *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 arrayWithCapacity:4];
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 = [[NGDOMNodePreorderWalker alloc]
225              initWithTarget:self selector:sel context:ctx];
226   
227   [walker walkNode:self];
228
229   [walker release]; walker = nil;
230   
231   return [[array copy] autorelease];
232 }
233 - (id<NSObject,DOMNodeList>)getElementsByTagName:(NSString *)_tagName
234   namespaceURI:(NSString *)_uri
235 {
236   [self doesNotRecognizeSelector:_cmd];
237   return nil;
238 }
239
240 - (id<NSObject,DOMElement>)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<NSObject,DOMElement>)createElement:(NSString *)_tagName {
287   id elem;
288   elem = [[[self domElementClass] 
289                  alloc] 
290                  initWithTagName:_tagName];
291   return [elem autorelease];
292 }
293 - (id<NSObject,DOMElement>)createElement:(NSString *)_tagName
294   namespaceURI:(NSString *)_uri
295 {
296   id elem;
297   elem = [[[self domElementNSClass] 
298                  alloc] 
299                  initWithTagName:_tagName namespaceURI:_uri];
300   return [elem autorelease];
301 }
302
303 - (id<NSObject,DOMDocumentFragment>)createDocumentFragment {
304   id elem;
305   elem = [[[self domDocumentFragmentClass] alloc] init];
306   return [elem autorelease];
307 }
308
309 - (id<NSObject,DOMText>)createTextNode:(NSString *)_data {
310   id elem;
311   elem = [[[self domTextNodeClass] alloc] initWithString:_data];
312   return [elem autorelease];
313 }
314 - (id<NSObject,DOMComment>)createComment:(NSString *)_data {
315   id elem;
316   elem = [[[self domCommentClass] alloc] initWithString:_data];
317   return [elem autorelease];
318 }
319 - (id<NSObject,DOMCDATASection>)createCDATASection:(NSString *)_data {
320   id elem;
321   elem = [[[self domCDATAClass] alloc] initWithString:_data];
322   return [elem autorelease];
323 }
324
325 - (id<NSObject,DOMProcessingInstruction>)createProcessingInstruction:
326     (NSString *)_target data:(NSString *)_data 
327 {
328   id elem;
329   elem = [[[self domProcessingInstructionClass] 
330                  alloc] 
331                  initWithTarget:_target data:_data];
332   return [elem autorelease];
333 }
334
335 - (id<NSObject,DOMAttr>)createAttribute:(NSString *)_name {
336   id elem;
337   elem = [[[self domAttributeClass] 
338                  alloc]
339                  initWithName:_name];
340   return [elem autorelease];
341 }
342 - (id<NSObject,DOMAttr>)createAttribute:(NSString *)_name
343   namespaceURI:(NSString *)_uri
344 {
345   id elem;
346   elem = [[[self domAttributeNSClass] 
347                  alloc]
348                  initWithName:_name namespaceURI:_uri];
349   return [elem autorelease];
350 }
351
352 - (id<NSObject,DOMEntityReference>)createEntityReference:(NSString *)_name {
353   id elem;
354   elem = [[[self domEntityReferenceClass] alloc] initWithName:_name];
355   return [elem autorelease];
356 }
357
358 /* QPValues */
359
360 - (NSException *)setQueryPathValue:(id)_value {
361   return [NSException exceptionWithName:@"QueryPathEvalException"
362                       reason:@"cannot set query-path value on DOMDocument !"
363                       userInfo:nil];
364 }
365 - (id)queryPathValue {
366   return [self documentElement];
367 }
368
369 @end /* NGDOMDocument */