~ubuntu-branches/ubuntu/edgy/sope/edgy

« back to all changes in this revision

Viewing changes to sope-xml/DOM/DOMElement.m

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Ley
  • Date: 2005-08-19 16:53:31 UTC
  • Revision ID: james.westby@ubuntu.com-20050819165331-hs683wz1osm708pw
Tags: upstream-4.4rc.2
ImportĀ upstreamĀ versionĀ 4.4rc.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/DOMElement.h>
 
23
#include <DOM/DOMNamedNodeMap.h>
 
24
#include <DOM/DOMAttribute.h>
 
25
#include <DOM/DOMDocument.h>
 
26
#include <DOM/DOMNodeWalker.h>
 
27
#include "common.h"
 
28
 
 
29
@interface _DOMElementAttrNamedNodeMap : NSObject < DOMNamedNodeMap >
 
30
{
 
31
  DOMElement *element; /* non-retained */
 
32
}
 
33
 
 
34
- (id)initWithElement:(id)_element;
 
35
 
 
36
- (id)objectEnumerator;
 
37
 
 
38
- (void)invalidate;
 
39
 
 
40
@end /* _DOMElementAttrNamedNodeMap */
 
41
 
 
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;
 
47
@end
 
48
 
 
49
static NSNull *null = nil;
 
50
 
 
51
@implementation DOMElement
 
52
 
 
53
- (id)initWithTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri {
 
54
  if (null == nil)
 
55
    null = [[NSNull null] retain];
 
56
  
 
57
  if ((self = [super init])) {
 
58
    self->tagName      = [_tagName copy];
 
59
    self->namespaceURI = [_uri     copy];
 
60
  }
 
61
  return self;
 
62
}
 
63
- (id)initWithTagName:(NSString *)_tagName {
 
64
  return [self initWithTagName:_tagName namespaceURI:nil];
 
65
}
 
66
 
 
67
- (void)dealloc {
 
68
  [self->attributes makeObjectsPerformSelector:
 
69
                      @selector(_domNodeForgetParentNode:)
 
70
                    withObject:self];
 
71
 
 
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];
 
79
  [super dealloc];
 
80
}
 
81
 
 
82
/* attributes */
 
83
 
 
84
- (NSString *)tagName {
 
85
  return self->tagName;
 
86
}
 
87
 
 
88
- (void)setPrefix:(NSString *)_prefix {
 
89
  id old = self->prefix;
 
90
  self->prefix = [_prefix copy];
 
91
  [old release];
 
92
}
 
93
- (NSString *)prefix {
 
94
  return self->prefix;
 
95
}
 
96
 
 
97
- (NSString *)namespaceURI {
 
98
  return self->namespaceURI;
 
99
}
 
100
 
 
101
- (void)setLine:(unsigned)_line {
 
102
  self->line = _line;
 
103
}
 
104
- (unsigned)line {
 
105
  return self->line;
 
106
}
 
107
 
 
108
/* lookup */
 
109
 
 
110
- (void)_walk_getElementsByTagName:(id)_walker {
 
111
  id node;
 
112
  
 
113
  node = [_walker currentNode];
 
114
  if ([node nodeType] != DOM_ELEMENT_NODE)
 
115
    return;
 
116
 
 
117
  if (![[node tagName] isEqualToString:
 
118
          [(NSArray *)[_walker context] objectAtIndex:0]])
 
119
    /* tagname doesn't match */
 
120
    return;
 
121
  
 
122
  [[(NSArray *)[_walker context] objectAtIndex:1] addObject:node];
 
123
}
 
124
- (void)_walk_getElementsByTagNameAddAll:(id)_walker {
 
125
  id node;
 
126
  
 
127
  node = [_walker currentNode];
 
128
  if ([node nodeType] != DOM_ELEMENT_NODE)
 
129
    return;
 
130
  
 
131
  [(NSMutableArray *)[_walker context] addObject:node];
 
132
}
 
133
- (id)getElementsByTagName:(NSString *)_tagName {
 
134
  /* introduced in DOM2, should return a *live* list ! */
 
135
  NSMutableArray        *array;
 
136
  DOMNodePreorderWalker *walker;
 
137
  SEL sel;
 
138
  id  ctx;
 
139
  
 
140
  if (![self hasChildNodes])
 
141
    return nil;
 
142
 
 
143
  if (_tagName == nil)
 
144
    return nil;
 
145
 
 
146
  array = [NSMutableArray array];
 
147
  
 
148
  if ([_tagName isEqualToString:@"*"]) {
 
149
    _tagName = nil;
 
150
    ctx = array;
 
151
    sel = @selector(_walk_getElementsByTagNameAddAll:);
 
152
  }
 
153
  else {
 
154
    ctx = [NSArray arrayWithObjects:_tagName, array, nil];
 
155
    sel = @selector(_walk_getElementsByTagName:);
 
156
  }
 
157
  
 
158
  walker = [[DOMNodePreorderWalker alloc]
 
159
                                   initWithTarget:self
 
160
                                   selector:sel
 
161
                                   context:ctx];
 
162
  
 
163
  [walker walkNode:self];
 
164
 
 
165
  [walker release]; walker = nil;
 
166
  return [[array copy] autorelease];
 
167
}
 
168
- (id)getElementsByTagName:(NSString *)_tagName namespaceURI:(NSString *)_uri {
 
169
  // TODO: implement
 
170
  [self doesNotRecognizeSelector:_cmd];
 
171
  return nil;
 
172
}
 
173
 
 
174
/* element attributes */
 
175
 
 
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];
 
181
}
 
182
 
 
183
- (void)_attributeSetChanged {
 
184
}
 
185
 
 
186
- (unsigned)_numberOfAttributes {
 
187
  return [self->attributes count];
 
188
}
 
189
- (id)_attributeNodeAtIndex:(unsigned)_idx {
 
190
  if (_idx >= [self->attributes count])
 
191
    return nil;
 
192
  return [self->attributes objectAtIndex:_idx];
 
193
}
 
194
 
 
195
- (id)_keyForAttribute:(id<DOMAttr>)_attrNode {
 
196
  return [_attrNode name];
 
197
}
 
198
- (id)_nskeyForLocalName:(NSString *)attrName namespaceURI:(NSString *)nsURI {
 
199
  id key;
 
200
  
 
201
  if (attrName == nil)
 
202
    return nil;
 
203
  
 
204
  if (nsURI) {
 
205
    id objs[2];
 
206
 
 
207
    objs[0] = attrName;
 
208
    objs[1] = nsURI;
 
209
    key = [NSArray arrayWithObjects:objs count:2];
 
210
  }
 
211
  else
 
212
    key = attrName;
 
213
  
 
214
  return key;
 
215
}
 
216
- (id)_nskeyForAttribute:(id<DOMAttr>)_attrNode {
 
217
  NSString *attrName;
 
218
  
 
219
  if ((attrName = [_attrNode name]) == nil) {
 
220
    NSLog(@"WARNING: attribute %@ has no valid attribute name !", _attrNode);
 
221
    return nil;
 
222
  }
 
223
  
 
224
  return [self _nskeyForLocalName:attrName
 
225
               namespaceURI:[_attrNode namespaceURI]];
 
226
}
 
227
 
 
228
- (BOOL)hasAttribute:(NSString *)_attrName {
 
229
  return [self hasAttribute:_attrName namespaceURI:[self namespaceURI]];
 
230
}
 
231
 
 
232
- (void)setAttribute:(NSString *)_attrName value:(NSString *)_value {
 
233
  [self setAttribute:_attrName namespaceURI:[self namespaceURI] value:_value];
 
234
 
 
235
#if 0 // ms: ??
 
236
  id node;
 
237
  
 
238
  NSAssert1(_attrName, @"invalid attribute name '%@'", _attrName);
 
239
 
 
240
  if ((node = [self->keyToAttribute objectForKey:_attrName]) == nil) {
 
241
    /* create new node */
 
242
    node = [[self ownerDocument] createAttribute:_attrName];
 
243
  }
 
244
  NSAssert(node, @"couldn't find/create node for attribute");
 
245
 
 
246
  node = [self setAttributeNode:node];
 
247
  
 
248
  [node setValue:_value];
 
249
#endif
 
250
}
 
251
- (id)attributeNode:(NSString *)_attrName {
 
252
  return [self attributeNode:_attrName namespaceURI:[self namespaceURI]];
 
253
}
 
254
- (NSString *)attribute:(NSString *)_attrName {
 
255
  return [[self attributeNode:_attrName] value];
 
256
}
 
257
 
 
258
- (BOOL)hasAttribute:(NSString *)_localName namespaceURI:(NSString *)_ns {
 
259
  id objs[2];
 
260
  id key;
 
261
 
 
262
  if ([_ns isEqualToString:@"*"]) {
 
263
    /* match any namespace */
 
264
    NSEnumerator *e;
 
265
    id attr;
 
266
    
 
267
    if ((attr = [self->keyToAttribute objectForKey:_localName]))
 
268
      return YES;
 
269
    
 
270
    e = [self->keyToAttribute keyEnumerator];
 
271
    while ((key = [e nextObject])) {
 
272
      if ([key isKindOfClass:[NSArray class]]) {
 
273
        if ([[key objectAtIndex:0] isEqualToString:_localName])
 
274
          return YES;
 
275
      }
 
276
    }
 
277
    return NO;
 
278
  }
 
279
  
 
280
  objs[0] = _localName;
 
281
  objs[1] = _ns ? _ns : (id)null;
 
282
  key = [NSArray arrayWithObjects:objs count:2];
 
283
  
 
284
  return [self->keyToAttribute objectForKey:key] ? YES : NO;
 
285
}
 
286
 
 
287
- (void)setAttribute:(NSString *)_localName namespaceURI:(NSString *)_ns
 
288
  value:(NSString *)_value
 
289
{
 
290
  id key;
 
291
  id node;
 
292
  
 
293
  key = [self _nskeyForLocalName:_localName namespaceURI:_ns];
 
294
  NSAssert2(key, @"invalid (ns-)attribute name localName='%@', uri='%@'",
 
295
            _localName, _ns);
 
296
  
 
297
  if ((node = [self->keyToAttribute objectForKey:key]) == nil) {
 
298
    /* create new node */
 
299
    node = [[self ownerDocument] createAttribute:_localName namespaceURI:_ns];
 
300
  }
 
301
  NSAssert(node, @"couldn't find/create node for attribute");
 
302
 
 
303
  node = [self setAttributeNodeNS:node];
 
304
  
 
305
  [node setValue:_value];
 
306
}
 
307
- (id)attributeNode:(NSString *)_localName namespaceURI:(NSString *)_ns {
 
308
  id objs[2];
 
309
  id key;
 
310
  
 
311
  if ([_ns isEqualToString:@"*"]) {
 
312
    /* match any namespace */
 
313
    NSEnumerator *e;
 
314
    id attr;
 
315
    
 
316
    if ((attr = [self->keyToAttribute objectForKey:_localName]))
 
317
      return attr;
 
318
    
 
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];
 
324
      }
 
325
    }
 
326
    return nil;
 
327
  }
 
328
  
 
329
  objs[0] = _localName;
 
330
  objs[1] = _ns ? _ns : (id)null;
 
331
  key = [NSArray arrayWithObjects:objs count:2];
 
332
 
 
333
  return [self->keyToAttribute objectForKey:key];
 
334
}
 
335
- (NSString *)attribute:(NSString *)_localName namespaceURI:(NSString *)_ns {
 
336
  return [[self attributeNode:_localName namespaceURI:_ns] value];
 
337
}
 
338
 
 
339
- (id)setAttributeNodeNS:(id)_attrNode {
 
340
  id key, oldNode;
 
341
  
 
342
  if (_attrNode == nil)
 
343
    /* invalid node parameters */
 
344
    return nil;
 
345
  
 
346
  if ((key = [self _nskeyForAttribute:_attrNode]) == nil)
 
347
    /* couldn't get key */
 
348
    return nil;
 
349
  
 
350
  [self _ensureAttrs];
 
351
  
 
352
  /* check if the key is already added */
 
353
  
 
354
  if ((oldNode = [self->keyToAttribute objectForKey:key])) {
 
355
    if (oldNode == _attrNode) {
 
356
      /* already contained */
 
357
      // NSLog(@"node is already set !");
 
358
      return _attrNode;
 
359
    }
 
360
    
 
361
    /* replace existing node */
 
362
    [self->attributes replaceObjectAtIndex:
 
363
                        [self->attributes indexOfObject:oldNode]
 
364
                      withObject:_attrNode];
 
365
    [self->keyToAttribute setObject:_attrNode forKey:key];
 
366
    
 
367
    [_attrNode _domNodeRegisterParentNode:self];
 
368
    [self _attributeSetChanged];
 
369
 
 
370
    return _attrNode;
 
371
  }
 
372
  else {
 
373
    /* add node */
 
374
 
 
375
    NSAssert(self->keyToAttribute, @"missing keyToAttribute");
 
376
    NSAssert(self->attributes,     @"missing attrs");
 
377
    
 
378
    [self->keyToAttribute setObject:_attrNode forKey:key];
 
379
    [self->attributes     addObject:_attrNode];
 
380
    
 
381
    [_attrNode _domNodeRegisterParentNode:self];
 
382
    [self _attributeSetChanged];
 
383
 
 
384
    // NSLog(@"added attr %@, elem %@", _attrNode, self);
 
385
    
 
386
    return _attrNode;
 
387
  }
 
388
}
 
389
 
 
390
- (void)removeAttribute:(NSString *)_attr namespaceURI:(NSString *)_uri {
 
391
  id node;
 
392
  id key;
 
393
  
 
394
  key = [self _nskeyForLocalName:_attr namespaceURI:_uri];
 
395
  NSAssert2(key, @"invalid (ns-)attribute name '%@', '%@'", _attr, _uri);
 
396
 
 
397
  node = [self->keyToAttribute objectForKey:key];
 
398
  
 
399
  [self removeAttributeNodeNS:node];
 
400
}
 
401
- (id)removeAttributeNodeNS:(id)_attrNode {
 
402
  id key, oldNode;
 
403
  
 
404
  if (_attrNode == nil)
 
405
    /* invalid node parameters */
 
406
    return nil;
 
407
  
 
408
  if (self->attributes == nil)
 
409
    /* no attributes are set up */
 
410
    return nil;
 
411
  
 
412
  if ((key = [self _nskeyForAttribute:_attrNode]) == nil)
 
413
    /* couldn't get key for node */
 
414
    return nil;
 
415
 
 
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 */
 
420
      return nil;
 
421
    }
 
422
 
 
423
    /* ok, found the node, let's remove ! */
 
424
    [[_attrNode retain] autorelease];
 
425
    [self->keyToAttribute removeObjectForKey:key];
 
426
    [self->attributes removeObjectIdenticalTo:_attrNode];
 
427
    
 
428
    [_attrNode _domNodeForgetParentNode:self];
 
429
    [self _attributeSetChanged];
 
430
    
 
431
    return _attrNode;
 
432
  }
 
433
  else
 
434
    /* no such attribute is stored */
 
435
    return nil;
 
436
}
 
437
 
 
438
- (id)setAttributeNode:(id)_attrNode {
 
439
  [self doesNotRecognizeSelector:_cmd];
 
440
  return nil;
 
441
}
 
442
- (id)removeAttributeNode:(id)_attrNode {
 
443
  [self doesNotRecognizeSelector:_cmd];
 
444
  return nil;
 
445
}
 
446
- (void)removeAttribute:(NSString *)_attr {
 
447
  id node;
 
448
  
 
449
  NSAssert1(_attr, @"invalid attribute name '%@'", _attr);
 
450
 
 
451
  node = [self->keyToAttribute objectForKey:_attr];
 
452
  
 
453
  [self removeAttributeNode:node];
 
454
}
 
455
 
 
456
/* node */
 
457
 
 
458
- (BOOL)_isValidChildNode:(id)_node {
 
459
  switch ([_node nodeType]) {
 
460
    case DOM_ELEMENT_NODE:
 
461
    case DOM_TEXT_NODE:
 
462
    case DOM_COMMENT_NODE:
 
463
    case DOM_PROCESSING_INSTRUCTION_NODE:
 
464
    case DOM_CDATA_SECTION_NODE:
 
465
    case DOM_ENTITY_REFERENCE_NODE:
 
466
      return YES;
 
467
      
 
468
    default:
 
469
      return NO;
 
470
  }
 
471
}
 
472
 
 
473
- (DOMNodeType)nodeType {
 
474
  return DOM_ELEMENT_NODE;
 
475
}
 
476
 
 
477
- (id)attributes {
 
478
  /* returns a named-node-map */
 
479
  if (self->attrNodeMap == nil) {
 
480
    self->attrNodeMap =
 
481
      [[_DOMElementAttrNamedNodeMap alloc] initWithElement:self];
 
482
  }
 
483
  return self->attrNodeMap;
 
484
}
 
485
 
 
486
/* parent node */
 
487
 
 
488
- (void)_domNodeRegisterParentNode:(id)_parent {
 
489
  self->parent = _parent;
 
490
}
 
491
- (void)_domNodeForgetParentNode:(id)_parent {
 
492
  if (_parent == self->parent)
 
493
    /* the node's parent was deallocated */
 
494
    self->parent = nil;
 
495
}
 
496
- (id)parentNode {
 
497
  return self->parent;
 
498
}
 
499
 
 
500
/* description */
 
501
 
 
502
- (NSString *)description {
 
503
  return [NSString stringWithFormat:
 
504
                     @"<0x%08X[%@]: name=%@ parent=%@ #attrs=%i #children=%i>",
 
505
                     self, NSStringFromClass([self class]),
 
506
                     [self nodeName],
 
507
                     [[self parentNode] nodeName],
 
508
                     [self _numberOfAttributes],
 
509
                     [self hasChildNodes] ? [[self childNodes] length] : 0];
 
510
}
 
511
 
 
512
@end /* DOMElement */
 
513
 
 
514
@implementation DOMElement(QPValues)
 
515
 
 
516
- (NSException *)setQueryPathValue:(id)_value {
 
517
  return [NSException exceptionWithName:@"QueryPathEvalException"
 
518
                      reason:@"cannot set query-path value on DOMElement !"
 
519
                      userInfo:nil];
 
520
}
 
521
- (id)queryPathValue {
 
522
  return [self childNodes];
 
523
}
 
524
 
 
525
@end /* DOMElement(QPValues) */
 
526
 
 
527
@implementation _DOMElementAttrNamedNodeMap
 
528
 
 
529
- (id)initWithElement:(id)_element {
 
530
  self->element = _element;
 
531
  return self;
 
532
}
 
533
 
 
534
- (void)invalidate {
 
535
  self->element = nil;
 
536
}
 
537
 
 
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) !");
 
542
  }
 
543
}
 
544
 
 
545
/* access */
 
546
 
 
547
static NSString *_XNSUri(NSString *_name) {
 
548
  NSRange r1;
 
549
 
 
550
  if (![_name hasPrefix:@"{"])
 
551
    return nil;
 
552
  
 
553
  r1 = [_name rangeOfString:@"}"];
 
554
  if (r1.length == 0)
 
555
    return nil;
 
556
  
 
557
  r1.length   = (r1.location - 2);
 
558
  r1.location = 1;
 
559
  return [_name substringWithRange:r1];
 
560
}
 
561
static NSString *_XNSLocalName(NSString *_name) {
 
562
  NSRange r;
 
563
  
 
564
  r = [_name rangeOfString:@"}"];
 
565
  return r.length == 0
 
566
    ? _name
 
567
    : [_name substringFromIndex:(r.location + r.length)];
 
568
}
 
569
 
 
570
- (unsigned)length {
 
571
  _checkValid(self);
 
572
  return [self->element _numberOfAttributes];
 
573
}
 
574
- (id)objectAtIndex:(unsigned)_idx {
 
575
  _checkValid(self);
 
576
  return [self->element _attributeNodeAtIndex:_idx];
 
577
}
 
578
 
 
579
- (id)namedItem:(NSString *)_name {
 
580
  NSString *nsuri;
 
581
  _checkValid(self);
 
582
  
 
583
  if ((nsuri = _XNSUri(_name)))
 
584
    return [self namedItem:_XNSLocalName(_name) namespaceURI:nsuri];
 
585
  
 
586
  return [self->element attributeNode:_name];
 
587
}
 
588
- (id)setNamedItem:(id)_node {
 
589
  _checkValid(self);
 
590
  return [self->element setAttributeNode:_node];
 
591
}
 
592
- (id)removeNamedItem:(NSString *)_name {
 
593
  NSString *nsuri;
 
594
  id node;
 
595
  
 
596
  _checkValid(self);
 
597
  if ((nsuri = _XNSUri(_name)))
 
598
    return [self removeNamedItem:_XNSLocalName(_name) namespaceURI:nsuri];
 
599
  
 
600
  if ((node = [self->element attributeNode:_name])) {
 
601
    node = [node retain];
 
602
    [self->element removeAttribute:_name];
 
603
    return [node autorelease];
 
604
  }
 
605
  else
 
606
    return nil;
 
607
}
 
608
 
 
609
/* DOM2 access */
 
610
 
 
611
- (id)namedItem:(NSString *)_name namespaceURI:(NSString *)_uri {
 
612
  return [self->element attributeNode:_name namespaceURI:_uri];
 
613
}
 
614
- (id)setNamedItemNS:(id)_node {
 
615
  _checkValid(self);
 
616
  return [self->element setAttributeNodeNS:_node];
 
617
}
 
618
- (id)removeNamedItem:(NSString *)_name namespaceURI:(NSString *)_uri {
 
619
  id node;
 
620
 
 
621
  _checkValid(self);
 
622
  if ((node = [self->element attributeNode:_name namespaceURI:_uri])) {
 
623
    node = [node retain];
 
624
    [self->element removeAttribute:_name namespaceURI:_uri];
 
625
    return [node autorelease];
 
626
  }
 
627
  else
 
628
    return nil;
 
629
}
 
630
 
 
631
/* mimic NSArray */
 
632
 
 
633
- (unsigned)count {
 
634
  _checkValid(self);
 
635
  return [self->element _numberOfAttributes];
 
636
}
 
637
 
 
638
- (id)objectEnumerator {
 
639
  NSMutableArray *ma;
 
640
  unsigned i, count;
 
641
 
 
642
  _checkValid(self);
 
643
  if ((count = [self->element _numberOfAttributes]) == 0)
 
644
    return nil;
 
645
 
 
646
  ma = [NSMutableArray arrayWithCapacity:count];
 
647
  
 
648
  for (i = 0; i < count; i++)
 
649
    [ma addObject:[self->element _attributeNodeAtIndex:i]];
 
650
  
 
651
  return [ma objectEnumerator];
 
652
}
 
653
 
 
654
/* mimic NSDictionary */
 
655
 
 
656
- (void)setObject:(id)_value forKey:(id)_key {
 
657
  _checkValid(self);
 
658
  [self takeValue:_value forKey:[_key stringValue]];
 
659
}
 
660
- (id)objectForKey:(id)_key {
 
661
  _checkValid(self);
 
662
  return [self valueForKey:[_key stringValue]];
 
663
}
 
664
 
 
665
/* KVC */
 
666
 
 
667
- (void)takeValue:(id)_value forKey:(NSString *)_key {
 
668
  id node;
 
669
  _checkValid(self);
 
670
  
 
671
  if ((node = [self->element attributeNode:_key namespaceURI:@"*"])) {
 
672
    [node setValue:[_value stringValue]];
 
673
  }
 
674
  else {
 
675
    [self->element setAttribute:_key namespaceURI:@"xhtml"
 
676
                   value:[_value stringValue]];
 
677
  }
 
678
}
 
679
- (id)valueForKey:(NSString *)_key {
 
680
  id v;
 
681
  _checkValid(self);
 
682
  
 
683
  if ((v = [self namedItem:_key]))
 
684
    return [v value];
 
685
  if ((v = [self namedItem:_key namespaceURI:@"*"]))
 
686
    return [v value];
 
687
  
 
688
  return nil;
 
689
}
 
690
 
 
691
/* JSSupport */
 
692
 
 
693
- (id)_jsprop_length {
 
694
  return [NSNumber numberWithInt:[self length]];
 
695
}
 
696
 
 
697
- (id)_jsfunc_item:(NSArray *)_args {
 
698
  unsigned count;
 
699
  
 
700
  if ((count = [_args count]) == 0) return nil;
 
701
  return [self objectAtIndex:[[_args objectAtIndex:0] intValue]];
 
702
}
 
703
 
 
704
- (id)_jsfunc_getNamedItem:(NSArray *)_args {
 
705
  unsigned count;
 
706
  
 
707
  if ((count = [_args count]) == 0) return nil;
 
708
  return [self namedItem:[[_args objectAtIndex:0] stringValue]];
 
709
}
 
710
- (id)_jsfunc_getNamedItemNS:(NSArray *)_args {
 
711
  unsigned count;
 
712
  
 
713
  if ((count = [_args count]) == 0) return nil;
 
714
  if (count == 1)
 
715
    return [self namedItem:[[_args objectAtIndex:0] stringValue]];
 
716
  else {
 
717
    return [self namedItem:[[_args objectAtIndex:1] stringValue]
 
718
                 namespaceURI:[[_args objectAtIndex:0] stringValue]];
 
719
  }
 
720
}
 
721
 
 
722
- (id)_jsfunc_setNamedItem:(NSArray *)_args {
 
723
  unsigned i, count;
 
724
  id last = nil;
 
725
 
 
726
  for (i = 0, count = [_args count]; i < count; i++)
 
727
    last = [self setNamedItem:[_args objectAtIndex:i]];
 
728
  return last;
 
729
}
 
730
- (id)_jsfunc_setNamedItemNS:(NSArray *)_args {
 
731
  unsigned i, count;
 
732
  id last = nil;
 
733
 
 
734
  for (i = 0, count = [_args count]; i < count; i++)
 
735
    last = [self setNamedItemNS:[_args objectAtIndex:i]];
 
736
  return last;
 
737
}
 
738
 
 
739
- (id)_jsfunc_removeNamedItem:(NSArray *)_args {
 
740
  unsigned count;
 
741
  
 
742
  if ((count = [_args count]) == 0) return nil;
 
743
  return [self namedItem:[[_args objectAtIndex:0] stringValue]];
 
744
}
 
745
- (id)_jsfunc_removeNamedItemNS:(NSArray *)_args {
 
746
  unsigned count;
 
747
  
 
748
  if ((count = [_args count]) == 0) return nil;
 
749
  if (count == 1)
 
750
    return [self removeNamedItem:[[_args objectAtIndex:0] stringValue]];
 
751
  else {
 
752
    return [self removeNamedItem:[[_args objectAtIndex:1] stringValue]
 
753
                 namespaceURI:[[_args objectAtIndex:0] stringValue]];
 
754
  }
 
755
}
 
756
 
 
757
/* description */
 
758
 
 
759
- (NSString *)description {
 
760
  NSMutableString *ms;
 
761
  NSEnumerator *e;
 
762
  id attr;
 
763
  
 
764
  ms = [NSMutableString stringWithCapacity:1024];
 
765
  [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
 
766
  [ms appendFormat:@" element=%@", self->element];
 
767
  
 
768
  [ms appendString:@" attributes:\n"];
 
769
  e = [self objectEnumerator];
 
770
  while ((attr = [e nextObject])) {
 
771
    [ms appendString:[attr description]];
 
772
    [ms appendString:@"\n"];
 
773
  }
 
774
  
 
775
  [ms appendString:@">"];
 
776
  return ms;
 
777
}
 
778
 
 
779
@end /* _DOMElementAttrNamedNodeMap */