2
Copyright (C) 2000-2005 SKYRIX Software AG
4
This file is part of SOPE.
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
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.
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
22
#include <DOM/DOMElement.h>
23
#include <DOM/DOMNamedNodeMap.h>
24
#include <DOM/DOMAttribute.h>
25
#include <DOM/DOMDocument.h>
26
#include <DOM/DOMNodeWalker.h>
29
@interface _DOMElementAttrNamedNodeMap : NSObject < DOMNamedNodeMap >
31
DOMElement *element; /* non-retained */
34
- (id)initWithElement:(id)_element;
36
- (id)objectEnumerator;
40
@end /* _DOMElementAttrNamedNodeMap */
42
@interface DOMElement(Privates)
43
- (unsigned)_numberOfAttributes;
44
- (id)_attributeNodeAtIndex:(unsigned)_idx;
45
- (id)attributeNode:(NSString *)_localName;
46
- (id)attributeNode:(NSString *)_localName namespaceURI:(NSString *)_ns;
49
static NSNull *null = nil;
51
@implementation DOMElement
53
- (id)initWithTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri {
55
null = [[NSNull null] retain];
57
if ((self = [super init])) {
58
self->tagName = [_tagName copy];
59
self->namespaceURI = [_uri copy];
63
- (id)initWithTagName:(NSString *)_tagName {
64
return [self initWithTagName:_tagName namespaceURI:nil];
68
[self->attributes makeObjectsPerformSelector:
69
@selector(_domNodeForgetParentNode:)
72
[self->attrNodeMap invalidate];
73
[self->attrNodeMap release];
74
[self->keyToAttribute release];
75
[self->attributes release];
76
[self->tagName release];
77
[self->namespaceURI release];
78
[self->prefix release];
84
- (NSString *)tagName {
88
- (void)setPrefix:(NSString *)_prefix {
89
id old = self->prefix;
90
self->prefix = [_prefix copy];
93
- (NSString *)prefix {
97
- (NSString *)namespaceURI {
98
return self->namespaceURI;
101
- (void)setLine:(unsigned)_line {
110
- (void)_walk_getElementsByTagName:(id)_walker {
113
node = [_walker currentNode];
114
if ([node nodeType] != DOM_ELEMENT_NODE)
117
if (![[node tagName] isEqualToString:
118
[(NSArray *)[_walker context] objectAtIndex:0]])
119
/* tagname doesn't match */
122
[[(NSArray *)[_walker context] objectAtIndex:1] addObject:node];
124
- (void)_walk_getElementsByTagNameAddAll:(id)_walker {
127
node = [_walker currentNode];
128
if ([node nodeType] != DOM_ELEMENT_NODE)
131
[(NSMutableArray *)[_walker context] addObject:node];
133
- (id)getElementsByTagName:(NSString *)_tagName {
134
/* introduced in DOM2, should return a *live* list ! */
135
NSMutableArray *array;
136
DOMNodePreorderWalker *walker;
140
if (![self hasChildNodes])
146
array = [NSMutableArray array];
148
if ([_tagName isEqualToString:@"*"]) {
151
sel = @selector(_walk_getElementsByTagNameAddAll:);
154
ctx = [NSArray arrayWithObjects:_tagName, array, nil];
155
sel = @selector(_walk_getElementsByTagName:);
158
walker = [[DOMNodePreorderWalker alloc]
163
[walker walkNode:self];
165
[walker release]; walker = nil;
166
return [[array copy] autorelease];
168
- (id)getElementsByTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri {
170
[self doesNotRecognizeSelector:_cmd];
174
/* element attributes */
176
- (void)_ensureAttrs {
177
if (self->attributes == nil)
178
self->attributes = [[NSMutableArray alloc] init];
179
if (self->keyToAttribute == nil)
180
self->keyToAttribute = [[NSMutableDictionary alloc] init];
183
- (void)_attributeSetChanged {
186
- (unsigned)_numberOfAttributes {
187
return [self->attributes count];
189
- (id)_attributeNodeAtIndex:(unsigned)_idx {
190
if (_idx >= [self->attributes count])
192
return [self->attributes objectAtIndex:_idx];
195
- (id)_keyForAttribute:(id<DOMAttr>)_attrNode {
196
return [_attrNode name];
198
- (id)_nskeyForLocalName:(NSString *)attrName namespaceURI:(NSString *)nsURI {
209
key = [NSArray arrayWithObjects:objs count:2];
216
- (id)_nskeyForAttribute:(id<DOMAttr>)_attrNode {
219
if ((attrName = [_attrNode name]) == nil) {
220
NSLog(@"WARNING: attribute %@ has no valid attribute name !", _attrNode);
224
return [self _nskeyForLocalName:attrName
225
namespaceURI:[_attrNode namespaceURI]];
228
- (BOOL)hasAttribute:(NSString *)_attrName {
229
return [self hasAttribute:_attrName namespaceURI:[self namespaceURI]];
232
- (void)setAttribute:(NSString *)_attrName value:(NSString *)_value {
233
[self setAttribute:_attrName namespaceURI:[self namespaceURI] value:_value];
238
NSAssert1(_attrName, @"invalid attribute name '%@'", _attrName);
240
if ((node = [self->keyToAttribute objectForKey:_attrName]) == nil) {
241
/* create new node */
242
node = [[self ownerDocument] createAttribute:_attrName];
244
NSAssert(node, @"couldn't find/create node for attribute");
246
node = [self setAttributeNode:node];
248
[node setValue:_value];
251
- (id)attributeNode:(NSString *)_attrName {
252
return [self attributeNode:_attrName namespaceURI:[self namespaceURI]];
254
- (NSString *)attribute:(NSString *)_attrName {
255
return [[self attributeNode:_attrName] value];
258
- (BOOL)hasAttribute:(NSString *)_localName namespaceURI:(NSString *)_ns {
262
if ([_ns isEqualToString:@"*"]) {
263
/* match any namespace */
267
if ((attr = [self->keyToAttribute objectForKey:_localName]))
270
e = [self->keyToAttribute keyEnumerator];
271
while ((key = [e nextObject])) {
272
if ([key isKindOfClass:[NSArray class]]) {
273
if ([[key objectAtIndex:0] isEqualToString:_localName])
280
objs[0] = _localName;
281
objs[1] = _ns ? _ns : (id)null;
282
key = [NSArray arrayWithObjects:objs count:2];
284
return [self->keyToAttribute objectForKey:key] ? YES : NO;
287
- (void)setAttribute:(NSString *)_localName namespaceURI:(NSString *)_ns
288
value:(NSString *)_value
293
key = [self _nskeyForLocalName:_localName namespaceURI:_ns];
294
NSAssert2(key, @"invalid (ns-)attribute name localName='%@', uri='%@'",
297
if ((node = [self->keyToAttribute objectForKey:key]) == nil) {
298
/* create new node */
299
node = [[self ownerDocument] createAttribute:_localName namespaceURI:_ns];
301
NSAssert(node, @"couldn't find/create node for attribute");
303
node = [self setAttributeNodeNS:node];
305
[node setValue:_value];
307
- (id)attributeNode:(NSString *)_localName namespaceURI:(NSString *)_ns {
311
if ([_ns isEqualToString:@"*"]) {
312
/* match any namespace */
316
if ((attr = [self->keyToAttribute objectForKey:_localName]))
319
e = [self->keyToAttribute keyEnumerator];
320
while ((key = [e nextObject])) {
321
if ([key isKindOfClass:[NSArray class]]) {
322
if ([[key objectAtIndex:0] isEqualToString:_localName])
323
return [self->keyToAttribute objectForKey:key];
329
objs[0] = _localName;
330
objs[1] = _ns ? _ns : (id)null;
331
key = [NSArray arrayWithObjects:objs count:2];
333
return [self->keyToAttribute objectForKey:key];
335
- (NSString *)attribute:(NSString *)_localName namespaceURI:(NSString *)_ns {
336
return [[self attributeNode:_localName namespaceURI:_ns] value];
339
- (id)setAttributeNodeNS:(id)_attrNode {
342
if (_attrNode == nil)
343
/* invalid node parameters */
346
if ((key = [self _nskeyForAttribute:_attrNode]) == nil)
347
/* couldn't get key */
352
/* check if the key is already added */
354
if ((oldNode = [self->keyToAttribute objectForKey:key])) {
355
if (oldNode == _attrNode) {
356
/* already contained */
357
// NSLog(@"node is already set !");
361
/* replace existing node */
362
[self->attributes replaceObjectAtIndex:
363
[self->attributes indexOfObject:oldNode]
364
withObject:_attrNode];
365
[self->keyToAttribute setObject:_attrNode forKey:key];
367
[_attrNode _domNodeRegisterParentNode:self];
368
[self _attributeSetChanged];
375
NSAssert(self->keyToAttribute, @"missing keyToAttribute");
376
NSAssert(self->attributes, @"missing attrs");
378
[self->keyToAttribute setObject:_attrNode forKey:key];
379
[self->attributes addObject:_attrNode];
381
[_attrNode _domNodeRegisterParentNode:self];
382
[self _attributeSetChanged];
384
// NSLog(@"added attr %@, elem %@", _attrNode, self);
390
- (void)removeAttribute:(NSString *)_attr namespaceURI:(NSString *)_uri {
394
key = [self _nskeyForLocalName:_attr namespaceURI:_uri];
395
NSAssert2(key, @"invalid (ns-)attribute name '%@', '%@'", _attr, _uri);
397
node = [self->keyToAttribute objectForKey:key];
399
[self removeAttributeNodeNS:node];
401
- (id)removeAttributeNodeNS:(id)_attrNode {
404
if (_attrNode == nil)
405
/* invalid node parameters */
408
if (self->attributes == nil)
409
/* no attributes are set up */
412
if ((key = [self _nskeyForAttribute:_attrNode]) == nil)
413
/* couldn't get key for node */
416
if ((oldNode = [self->keyToAttribute objectForKey:key])) {
417
/* the node's key exists */
418
if (oldNode != _attrNode) {
419
/* the node has the same key, but isn't the same */
423
/* ok, found the node, let's remove ! */
424
[[_attrNode retain] autorelease];
425
[self->keyToAttribute removeObjectForKey:key];
426
[self->attributes removeObjectIdenticalTo:_attrNode];
428
[_attrNode _domNodeForgetParentNode:self];
429
[self _attributeSetChanged];
434
/* no such attribute is stored */
438
- (id)setAttributeNode:(id)_attrNode {
439
[self doesNotRecognizeSelector:_cmd];
442
- (id)removeAttributeNode:(id)_attrNode {
443
[self doesNotRecognizeSelector:_cmd];
446
- (void)removeAttribute:(NSString *)_attr {
449
NSAssert1(_attr, @"invalid attribute name '%@'", _attr);
451
node = [self->keyToAttribute objectForKey:_attr];
453
[self removeAttributeNode:node];
458
- (BOOL)_isValidChildNode:(id)_node {
459
switch ([_node nodeType]) {
460
case DOM_ELEMENT_NODE:
462
case DOM_COMMENT_NODE:
463
case DOM_PROCESSING_INSTRUCTION_NODE:
464
case DOM_CDATA_SECTION_NODE:
465
case DOM_ENTITY_REFERENCE_NODE:
473
- (DOMNodeType)nodeType {
474
return DOM_ELEMENT_NODE;
478
/* returns a named-node-map */
479
if (self->attrNodeMap == nil) {
481
[[_DOMElementAttrNamedNodeMap alloc] initWithElement:self];
483
return self->attrNodeMap;
488
- (void)_domNodeRegisterParentNode:(id)_parent {
489
self->parent = _parent;
491
- (void)_domNodeForgetParentNode:(id)_parent {
492
if (_parent == self->parent)
493
/* the node's parent was deallocated */
502
- (NSString *)description {
503
return [NSString stringWithFormat:
504
@"<0x%08X[%@]: name=%@ parent=%@ #attrs=%i #children=%i>",
505
self, NSStringFromClass([self class]),
507
[[self parentNode] nodeName],
508
[self _numberOfAttributes],
509
[self hasChildNodes] ? [[self childNodes] length] : 0];
512
@end /* DOMElement */
514
@implementation DOMElement(QPValues)
516
- (NSException *)setQueryPathValue:(id)_value {
517
return [NSException exceptionWithName:@"QueryPathEvalException"
518
reason:@"cannot set query-path value on DOMElement !"
521
- (id)queryPathValue {
522
return [self childNodes];
525
@end /* DOMElement(QPValues) */
527
@implementation _DOMElementAttrNamedNodeMap
529
- (id)initWithElement:(id)_element {
530
self->element = _element;
538
static inline void _checkValid(_DOMElementAttrNamedNodeMap *self) {
539
if (self->element == nil) {
540
NSCAssert(self->element,
541
@"named node map is invalid (element was deallocated) !");
547
static NSString *_XNSUri(NSString *_name) {
550
if (![_name hasPrefix:@"{"])
553
r1 = [_name rangeOfString:@"}"];
557
r1.length = (r1.location - 2);
559
return [_name substringWithRange:r1];
561
static NSString *_XNSLocalName(NSString *_name) {
564
r = [_name rangeOfString:@"}"];
567
: [_name substringFromIndex:(r.location + r.length)];
572
return [self->element _numberOfAttributes];
574
- (id)objectAtIndex:(unsigned)_idx {
576
return [self->element _attributeNodeAtIndex:_idx];
579
- (id)namedItem:(NSString *)_name {
583
if ((nsuri = _XNSUri(_name)))
584
return [self namedItem:_XNSLocalName(_name) namespaceURI:nsuri];
586
return [self->element attributeNode:_name];
588
- (id)setNamedItem:(id)_node {
590
return [self->element setAttributeNode:_node];
592
- (id)removeNamedItem:(NSString *)_name {
597
if ((nsuri = _XNSUri(_name)))
598
return [self removeNamedItem:_XNSLocalName(_name) namespaceURI:nsuri];
600
if ((node = [self->element attributeNode:_name])) {
601
node = [node retain];
602
[self->element removeAttribute:_name];
603
return [node autorelease];
611
- (id)namedItem:(NSString *)_name namespaceURI:(NSString *)_uri {
612
return [self->element attributeNode:_name namespaceURI:_uri];
614
- (id)setNamedItemNS:(id)_node {
616
return [self->element setAttributeNodeNS:_node];
618
- (id)removeNamedItem:(NSString *)_name namespaceURI:(NSString *)_uri {
622
if ((node = [self->element attributeNode:_name namespaceURI:_uri])) {
623
node = [node retain];
624
[self->element removeAttribute:_name namespaceURI:_uri];
625
return [node autorelease];
635
return [self->element _numberOfAttributes];
638
- (id)objectEnumerator {
643
if ((count = [self->element _numberOfAttributes]) == 0)
646
ma = [NSMutableArray arrayWithCapacity:count];
648
for (i = 0; i < count; i++)
649
[ma addObject:[self->element _attributeNodeAtIndex:i]];
651
return [ma objectEnumerator];
654
/* mimic NSDictionary */
656
- (void)setObject:(id)_value forKey:(id)_key {
658
[self takeValue:_value forKey:[_key stringValue]];
660
- (id)objectForKey:(id)_key {
662
return [self valueForKey:[_key stringValue]];
667
- (void)takeValue:(id)_value forKey:(NSString *)_key {
671
if ((node = [self->element attributeNode:_key namespaceURI:@"*"])) {
672
[node setValue:[_value stringValue]];
675
[self->element setAttribute:_key namespaceURI:@"xhtml"
676
value:[_value stringValue]];
679
- (id)valueForKey:(NSString *)_key {
683
if ((v = [self namedItem:_key]))
685
if ((v = [self namedItem:_key namespaceURI:@"*"]))
693
- (id)_jsprop_length {
694
return [NSNumber numberWithInt:[self length]];
697
- (id)_jsfunc_item:(NSArray *)_args {
700
if ((count = [_args count]) == 0) return nil;
701
return [self objectAtIndex:[[_args objectAtIndex:0] intValue]];
704
- (id)_jsfunc_getNamedItem:(NSArray *)_args {
707
if ((count = [_args count]) == 0) return nil;
708
return [self namedItem:[[_args objectAtIndex:0] stringValue]];
710
- (id)_jsfunc_getNamedItemNS:(NSArray *)_args {
713
if ((count = [_args count]) == 0) return nil;
715
return [self namedItem:[[_args objectAtIndex:0] stringValue]];
717
return [self namedItem:[[_args objectAtIndex:1] stringValue]
718
namespaceURI:[[_args objectAtIndex:0] stringValue]];
722
- (id)_jsfunc_setNamedItem:(NSArray *)_args {
726
for (i = 0, count = [_args count]; i < count; i++)
727
last = [self setNamedItem:[_args objectAtIndex:i]];
730
- (id)_jsfunc_setNamedItemNS:(NSArray *)_args {
734
for (i = 0, count = [_args count]; i < count; i++)
735
last = [self setNamedItemNS:[_args objectAtIndex:i]];
739
- (id)_jsfunc_removeNamedItem:(NSArray *)_args {
742
if ((count = [_args count]) == 0) return nil;
743
return [self namedItem:[[_args objectAtIndex:0] stringValue]];
745
- (id)_jsfunc_removeNamedItemNS:(NSArray *)_args {
748
if ((count = [_args count]) == 0) return nil;
750
return [self removeNamedItem:[[_args objectAtIndex:0] stringValue]];
752
return [self removeNamedItem:[[_args objectAtIndex:1] stringValue]
753
namespaceURI:[[_args objectAtIndex:0] stringValue]];
759
- (NSString *)description {
764
ms = [NSMutableString stringWithCapacity:1024];
765
[ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
766
[ms appendFormat:@" element=%@", self->element];
768
[ms appendString:@" attributes:\n"];
769
e = [self objectEnumerator];
770
while ((attr = [e nextObject])) {
771
[ms appendString:[attr description]];
772
[ms appendString:@"\n"];
775
[ms appendString:@">"];
779
@end /* _DOMElementAttrNamedNodeMap */