• R/O
  • SSH
  • HTTPS

poi-poi-capsule: Commit


Commit MetaInfo

Révision272 (tree)
l'heure2011-05-06 19:01:02
Auteurpoi-poi-capsule

Message de Log

kissxmlアップデート

Change Summary

Modification

--- trunk/0.2.X/NSStringAdditions.h (revision 271)
+++ trunk/0.2.X/NSStringAdditions.h (nonexistent)
@@ -1,14 +0,0 @@
1-#import <Foundation/Foundation.h>
2-#import <libxml/tree.h>
3-
4-
5-@interface NSString (NSStringAdditions)
6-
7-/**
8- * xmlChar - A basic replacement for char, a byte in a UTF-8 encoded string.
9-**/
10-- (const xmlChar *)xmlChar;
11-
12-- (NSString *)stringByTrimming;
13-
14-@end
--- trunk/0.2.X/NSStringAdditions.m (revision 271)
+++ trunk/0.2.X/NSStringAdditions.m (nonexistent)
@@ -1,29 +0,0 @@
1-#import "NSStringAdditions.h"
2-
3-
4-@implementation NSString (NSStringAdditions)
5-
6-- (const xmlChar *)xmlChar
7-{
8- return (const xmlChar *)[self UTF8String];
9-}
10-
11-#ifdef GNUSTEP
12-- (NSString *)stringByTrimming
13-{
14- return [self stringByTrimmingSpaces];
15-}
16-#else
17-- (NSString *)stringByTrimming
18-{
19- NSMutableString *mStr = [self mutableCopy];
20- CFStringTrimWhitespace((CFMutableStringRef)mStr);
21-
22- NSString *result = [mStr copy];
23-
24- [mStr release];
25- return [result autorelease];
26-}
27-#endif
28-
29-@end
--- trunk/0.2.X/DDXMLPrivate.h (revision 271)
+++ trunk/0.2.X/DDXMLPrivate.h (nonexistent)
@@ -1,79 +0,0 @@
1-#import "DDXMLNode.h"
2-#import "DDXMLElement.h"
3-#import "DDXMLDocument.h"
4-
5-// We can't rely solely on NSAssert, because many developers disable them for release builds.
6-// Our API contract requires us to keep these assertions intact.
7-#define DDCheck(condition, desc, ...) { if(!(condition)) { [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd object:self file:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; } }
8-
9-#define DDLastErrorKey @"DDXML:LastError"
10-
11-
12-@interface DDXMLNode (PrivateAPI)
13-
14-+ (id)nodeWithUnknownPrimitive:(xmlKindPtr)kindPtr;
15-
16-+ (id)nodeWithPrimitive:(xmlKindPtr)kindPtr;
17-- (id)initWithCheckedPrimitive:(xmlKindPtr)kindPtr;
18-
19-+ (id)nodeWithPrimitive:(xmlNsPtr)ns nsParent:(xmlNodePtr)parent;
20-- (id)initWithCheckedPrimitive:(xmlNsPtr)ns nsParent:(xmlNodePtr)parent;
21-
22-+ (BOOL)isXmlAttrPtr:(xmlKindPtr)kindPtr;
23-- (BOOL)isXmlAttrPtr;
24-
25-+ (BOOL)isXmlNodePtr:(xmlKindPtr)kindPtr;
26-- (BOOL)isXmlNodePtr;
27-
28-+ (BOOL)isXmlDocPtr:(xmlKindPtr)kindPtr;
29-- (BOOL)isXmlDocPtr;
30-
31-+ (BOOL)isXmlDtdPtr:(xmlKindPtr)kindPtr;
32-- (BOOL)isXmlDtdPtr;
33-
34-+ (BOOL)isXmlNsPtr:(xmlKindPtr)kindPtr;
35-- (BOOL)isXmlNsPtr;
36-
37-- (BOOL)hasParent;
38-
39-+ (void)recursiveStripDocPointersFromNode:(xmlNodePtr)node;
40-
41-+ (void)detachAttribute:(xmlAttrPtr)attr fromNode:(xmlNodePtr)node;
42-+ (void)removeAttribute:(xmlAttrPtr)attr fromNode:(xmlNodePtr)node;
43-+ (void)removeAllAttributesFromNode:(xmlNodePtr)node;
44-
45-+ (void)detachNamespace:(xmlNsPtr)ns fromNode:(xmlNodePtr)node;
46-+ (void)removeNamespace:(xmlNsPtr)ns fromNode:(xmlNodePtr)node;
47-+ (void)removeAllNamespacesFromNode:(xmlNodePtr)node;
48-
49-+ (void)detachChild:(xmlNodePtr)child fromNode:(xmlNodePtr)node;
50-+ (void)removeChild:(xmlNodePtr)child fromNode:(xmlNodePtr)node;
51-+ (void)removeAllChildrenFromNode:(xmlNodePtr)node;
52-
53-+ (void)removeAllChildrenFromDoc:(xmlDocPtr)doc;
54-
55-- (void)nodeRetain;
56-- (void)nodeRelease;
57-
58-+ (NSError *)lastError;
59-
60-@end
61-
62-@interface DDXMLElement (PrivateAPI)
63-
64-+ (id)nodeWithPrimitive:(xmlKindPtr)kindPtr;
65-- (id)initWithCheckedPrimitive:(xmlKindPtr)kindPtr;
66-
67-- (NSArray *)elementsWithName:(NSString *)name uri:(NSString *)URI;
68-
69-+ (DDXMLNode *)resolveNamespaceForPrefix:(NSString *)prefix atNode:(xmlNodePtr)nodePtr;
70-+ (NSString *)resolvePrefixForURI:(NSString *)uri atNode:(xmlNodePtr)nodePtr;
71-
72-@end
73-
74-@interface DDXMLDocument (PrivateAPI)
75-
76-+ (id)nodeWithPrimitive:(xmlKindPtr)kindPtr;
77-- (id)initWithCheckedPrimitive:(xmlKindPtr)kindPtr;
78-
79-@end
\ No newline at end of file
--- trunk/0.2.X/DDXMLNode.h (revision 271)
+++ trunk/0.2.X/DDXMLNode.h (nonexistent)
@@ -1,170 +0,0 @@
1-#import <Foundation/Foundation.h>
2-#import <libxml/tree.h>
3-
4-@class DDXMLDocument;
5-
6-
7-enum {
8- DDXMLInvalidKind = 0,
9- DDXMLDocumentKind = XML_DOCUMENT_NODE,
10- DDXMLElementKind = XML_ELEMENT_NODE,
11- DDXMLAttributeKind = XML_ATTRIBUTE_NODE,
12- DDXMLNamespaceKind = XML_NAMESPACE_DECL,
13- DDXMLProcessingInstructionKind = XML_PI_NODE,
14- DDXMLCommentKind = XML_COMMENT_NODE,
15- DDXMLTextKind = XML_TEXT_NODE,
16- DDXMLDTDKind = XML_DTD_NODE,
17- DDXMLEntityDeclarationKind = XML_ENTITY_DECL,
18- DDXMLAttributeDeclarationKind = XML_ATTRIBUTE_DECL,
19- DDXMLElementDeclarationKind = XML_ELEMENT_DECL,
20- DDXMLNotationDeclarationKind = XML_NOTATION_NODE
21-};
22-typedef NSUInteger DDXMLNodeKind;
23-
24-enum {
25- DDXMLNodeOptionsNone = 0,
26- DDXMLNodeExpandEmptyElement = 1 << 1,
27- DDXMLNodeCompactEmptyElement = 1 << 2,
28- DDXMLNodePrettyPrint = 1 << 17,
29-};
30-
31-/**
32- * DDXMLNode can represent several underlying types, such as xmlNodePtr, xmlDocPtr, xmlAttrPtr, xmlNsPtr, etc.
33- * All of these are pointers to structures, and all of those structures start with a pointer, and a type.
34- * The xmlKind struct is used as a generic structure, and a stepping stone.
35- * We use it to check the type of a structure, and then perform the appropriate cast.
36- *
37- * For example:
38- * if(genericPtr->type == XML_ATTRIBUTE_NODE)
39- * {
40- * xmlAttrPtr attr = (xmlAttrPtr)genericPtr;
41- * // Do something with attr
42- * }
43-**/
44-struct _xmlKind {
45- void * ignore;
46- xmlElementType type;
47-};
48-typedef struct _xmlKind *xmlKindPtr;
49-
50-/**
51- * Most xml types all start with this standard structure. In fact, all do except the xmlNsPtr.
52- * We will occasionally take advantage of this to simplify code when the code wouldn't vary from type to type.
53- * Obviously, you cannnot cast a xmlNsPtr to a xmlStdPtr.
54-**/
55-struct _xmlStd {
56- void * _private;
57- xmlElementType type;
58- const xmlChar *name;
59- struct _xmlNode *children;
60- struct _xmlNode *last;
61- struct _xmlNode *parent;
62- struct _xmlStd *next;
63- struct _xmlStd *prev;
64- struct _xmlDoc *doc;
65-};
66-typedef struct _xmlStd *xmlStdPtr;
67-
68-@interface DDXMLNode : NSObject <NSCopying>
69-{
70- // Every DDXML object is simply a wrapper around an underlying libxml node
71- xmlKindPtr genericPtr;
72-
73- // The xmlNsPtr type doesn't store a reference to it's parent
74- // This is here to fix that problem, and make this class more compatible with the NSXML classes
75- xmlNodePtr nsParentPtr;
76-}
77-
78-//- (id)initWithKind:(DDXMLNodeKind)kind;
79-
80-//- (id)initWithKind:(DDXMLNodeKind)kind options:(NSUInteger)options;
81-
82-//+ (id)document;
83-
84-//+ (id)documentWithRootElement:(DDXMLElement *)element;
85-
86-+ (id)elementWithName:(NSString *)name;
87-
88-+ (id)elementWithName:(NSString *)name URI:(NSString *)URI;
89-
90-+ (id)elementWithName:(NSString *)name stringValue:(NSString *)string;
91-
92-+ (id)elementWithName:(NSString *)name children:(NSArray *)children attributes:(NSArray *)attributes;
93-
94-+ (id)attributeWithName:(NSString *)name stringValue:(NSString *)stringValue;
95-
96-+ (id)attributeWithName:(NSString *)name URI:(NSString *)URI stringValue:(NSString *)stringValue;
97-
98-+ (id)namespaceWithName:(NSString *)name stringValue:(NSString *)stringValue;
99-
100-+ (id)processingInstructionWithName:(NSString *)name stringValue:(NSString *)stringValue;
101-
102-+ (id)commentWithStringValue:(NSString *)stringValue;
103-
104-+ (id)textWithStringValue:(NSString *)stringValue;
105-
106-//+ (id)DTDNodeWithXMLString:(NSString *)string;
107-
108-#pragma mark --- Properties ---
109-
110-- (DDXMLNodeKind)kind;
111-
112-- (void)setName:(NSString *)name;
113-- (NSString *)name;
114-
115-//- (void)setObjectValue:(id)value;
116-//- (id)objectValue;
117-
118-- (void)setStringValue:(NSString *)string;
119-//- (void)setStringValue:(NSString *)string resolvingEntities:(BOOL)resolve;
120-- (NSString *)stringValue;
121-
122-#pragma mark --- Tree Navigation ---
123-
124-- (NSUInteger)index;
125-
126-- (NSUInteger)level;
127-
128-- (DDXMLDocument *)rootDocument;
129-
130-- (DDXMLNode *)parent;
131-- (NSUInteger)childCount;
132-- (NSArray *)children;
133-- (DDXMLNode *)childAtIndex:(NSUInteger)index;
134-
135-- (DDXMLNode *)previousSibling;
136-- (DDXMLNode *)nextSibling;
137-
138-- (DDXMLNode *)previousNode;
139-- (DDXMLNode *)nextNode;
140-
141-- (void)detach;
142-
143-- (NSString *)XPath;
144-
145-#pragma mark --- QNames ---
146-
147-- (NSString *)localName;
148-- (NSString *)prefix;
149-
150-- (void)setURI:(NSString *)URI;
151-- (NSString *)URI;
152-
153-+ (NSString *)localNameForName:(NSString *)name;
154-+ (NSString *)prefixForName:(NSString *)name;
155-//+ (DDXMLNode *)predefinedNamespaceForPrefix:(NSString *)name;
156-
157-#pragma mark --- Output ---
158-
159-- (NSString *)description;
160-- (NSString *)XMLString;
161-- (NSString *)XMLStringWithOptions:(NSUInteger)options;
162-//- (NSString *)canonicalXMLStringPreservingComments:(BOOL)comments;
163-
164-#pragma mark --- XPath/XQuery ---
165-
166-- (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error;
167-//- (NSArray *)objectsForXQuery:(NSString *)xquery constants:(NSDictionary *)constants error:(NSError **)error;
168-//- (NSArray *)objectsForXQuery:(NSString *)xquery error:(NSError **)error;
169-
170-@end
--- trunk/0.2.X/DDXML.h (revision 271)
+++ trunk/0.2.X/DDXML.h (nonexistent)
@@ -1,3 +0,0 @@
1-#import "DDXMLNode.h"
2-#import "DDXMLElement.h"
3-#import "DDXMLDocument.h"
--- trunk/0.2.X/DDXMLNode.m (revision 271)
+++ trunk/0.2.X/DDXMLNode.m (nonexistent)
@@ -1,1808 +0,0 @@
1-#import "DDXMLNode.h"
2-#import "DDXMLElement.h"
3-#import "DDXMLDocument.h"
4-#import "NSStringAdditions.h"
5-#import "DDXMLPrivate.h"
6-
7-#import <libxml/xpath.h>
8-#import <libxml/xpathInternals.h>
9-
10-
11-@implementation DDXMLNode
12-
13-static void MyErrorHandler(void * userData, xmlErrorPtr error);
14-
15-+ (void)initialize
16-{
17- static BOOL initialized = NO;
18- if(!initialized)
19- {
20- // Redirect error output to our own function (don't clog up the console)
21- initGenericErrorDefaultFunc(NULL);
22- xmlSetStructuredErrorFunc(NULL, MyErrorHandler);
23-
24- // Tell libxml not to keep ignorable whitespace (such as node indentation, formatting, etc).
25- // NSXML ignores such whitespace.
26- // This also has the added benefit of taking up less RAM when parsing formatted XML documents.
27- xmlKeepBlanksDefault(0);
28-
29- initialized = YES;
30- }
31-}
32-
33-+ (id)elementWithName:(NSString *)name
34-{
35- return [[[DDXMLElement alloc] initWithName:name] autorelease];
36-}
37-
38-+ (id)elementWithName:(NSString *)name stringValue:(NSString *)string
39-{
40- return [[[DDXMLElement alloc] initWithName:name stringValue:string] autorelease];
41-}
42-
43-+ (id)elementWithName:(NSString *)name children:(NSArray *)children attributes:(NSArray *)attributes
44-{
45- DDXMLElement *result = [[[DDXMLElement alloc] initWithName:name] autorelease];
46- [result setChildren:children];
47- [result setAttributes:attributes];
48-
49- return result;
50-}
51-
52-+ (id)elementWithName:(NSString *)name URI:(NSString *)URI
53-{
54- return [[[DDXMLElement alloc] initWithName:name URI:URI] autorelease];
55-}
56-
57-+ (id)attributeWithName:(NSString *)name stringValue:(NSString *)stringValue
58-{
59- xmlAttrPtr attr = xmlNewProp(NULL, [name xmlChar], [stringValue xmlChar]);
60-
61- if(attr == NULL) return nil;
62-
63- return [[[DDXMLNode alloc] initWithCheckedPrimitive:(xmlKindPtr)attr] autorelease];
64-}
65-
66-+ (id)attributeWithName:(NSString *)name URI:(NSString *)URI stringValue:(NSString *)stringValue
67-{
68- xmlAttrPtr attr = xmlNewProp(NULL, [name xmlChar], [stringValue xmlChar]);
69-
70- if(attr == NULL) return nil;
71-
72- DDXMLNode *result = [[[DDXMLNode alloc] initWithCheckedPrimitive:(xmlKindPtr)attr] autorelease];
73- [result setURI:URI];
74-
75- return result;
76-}
77-
78-+ (id)namespaceWithName:(NSString *)name stringValue:(NSString *)stringValue
79-{
80- // If the user passes a nil or empty string name, they are trying to create a default namespace
81- const xmlChar *xmlName = [name length] > 0 ? [name xmlChar] : NULL;
82-
83- xmlNsPtr ns = xmlNewNs(NULL, [stringValue xmlChar], xmlName);
84-
85- if(ns == NULL) return nil;
86-
87- return [[[DDXMLNode alloc] initWithCheckedPrimitive:(xmlKindPtr)ns] autorelease];
88-}
89-
90-+ (id)processingInstructionWithName:(NSString *)name stringValue:(NSString *)stringValue
91-{
92- xmlNodePtr procInst = xmlNewPI([name xmlChar], [stringValue xmlChar]);
93-
94- if(procInst == NULL) return nil;
95-
96- return [[[DDXMLNode alloc] initWithCheckedPrimitive:(xmlKindPtr)procInst] autorelease];
97-}
98-
99-+ (id)commentWithStringValue:(NSString *)stringValue
100-{
101- xmlNodePtr comment = xmlNewComment([stringValue xmlChar]);
102-
103- if(comment == NULL) return nil;
104-
105- return [[[DDXMLNode alloc] initWithCheckedPrimitive:(xmlKindPtr)comment] autorelease];
106-}
107-
108-+ (id)textWithStringValue:(NSString *)stringValue
109-{
110- xmlNodePtr text = xmlNewText([stringValue xmlChar]);
111-
112- if(text == NULL) return nil;
113-
114- return [[[DDXMLNode alloc] initWithCheckedPrimitive:(xmlKindPtr)text] autorelease];
115-}
116-
117-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118-#pragma mark Init, Dealloc
119-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
120-
121-+ (id)nodeWithUnknownPrimitive:(xmlKindPtr)kindPtr
122-{
123- if(kindPtr->type == XML_DOCUMENT_NODE)
124- {
125- return [DDXMLDocument nodeWithPrimitive:kindPtr];
126- }
127- else if(kindPtr->type == XML_ELEMENT_NODE)
128- {
129- return [DDXMLElement nodeWithPrimitive:kindPtr];
130- }
131- else
132- {
133- return [DDXMLNode nodeWithPrimitive:kindPtr];
134- }
135-}
136-
137-/**
138- * Returns a DDXML wrapper object for the given primitive node.
139- * The given node MUST be non-NULL and of the proper type.
140- *
141- * If the wrapper object already exists, it is retained/autoreleased and returned.
142- * Otherwise a new wrapper object is alloc/init/autoreleased and returned.
143-**/
144-+ (id)nodeWithPrimitive:(xmlKindPtr)kindPtr
145-{
146- // If a wrapper object already exists, the _private variable is pointing to it.
147- // Warning: The _private variable is in a different location in the xmlNsPtr
148-
149- if([self isXmlNsPtr:kindPtr])
150- {
151- xmlNsPtr ns = (xmlNsPtr)kindPtr;
152- if(ns->_private != NULL)
153- {
154- return [[((DDXMLNode *)(ns->_private)) retain] autorelease];
155- }
156- }
157- else
158- {
159- xmlStdPtr node = (xmlStdPtr)kindPtr;
160- if(node->_private != NULL)
161- {
162- return [[((DDXMLNode *)(node->_private)) retain] autorelease];
163- }
164- }
165-
166- return [[[DDXMLNode alloc] initWithCheckedPrimitive:kindPtr] autorelease];
167-}
168-
169-/**
170- * Returns a DDXML wrapper object for the given primitive node.
171- * The given node MUST be non-NULL and of the proper type.
172- *
173- * The given node is checked, meaning a wrapper object for it does not already exist.
174-**/
175-- (id)initWithCheckedPrimitive:(xmlKindPtr)kindPtr
176-{
177- if((self = [super init]))
178- {
179- genericPtr = kindPtr;
180- nsParentPtr = NULL;
181- [self nodeRetain];
182- }
183- return self;
184-}
185-
186-/**
187- * Returns a DDXML wrapper object for the given primitive node.
188- * The given node MUST be non-NULL and of the proper type.
189- *
190- * If the wrapper object already exists, it is retained/autoreleased and returned.
191- * Otherwise a new wrapper object is alloc/init/autoreleased and returned.
192-**/
193-+ (id)nodeWithPrimitive:(xmlNsPtr)ns nsParent:(xmlNodePtr)parent
194-{
195- // If a wrapper object already exists, the _private variable is pointing to it.
196-
197- if(ns->_private == NULL)
198- return [[[DDXMLNode alloc] initWithCheckedPrimitive:ns nsParent:parent] autorelease];
199- else
200- return [[((DDXMLNode *)(ns->_private)) retain] autorelease];
201-}
202-
203-/**
204- * Returns a DDXML wrapper object for the given primitive node.
205- * The given node MUST be non-NULL and of the proper type.
206- *
207- * The given node is checked, meaning a wrapper object for it does not already exist.
208-**/
209-- (id)initWithCheckedPrimitive:(xmlNsPtr)ns nsParent:(xmlNodePtr)parent
210-{
211- if((self = [super init]))
212- {
213- genericPtr = (xmlKindPtr)ns;
214- nsParentPtr = parent;
215- [self nodeRetain];
216- }
217- return self;
218-}
219-
220-- (void)dealloc
221-{
222- // Check if genericPtr is NULL
223- // This may be the case if, eg, DDXMLElement calls [self release] from it's init method
224- if(genericPtr != NULL)
225- {
226- [self nodeRelease];
227- }
228- [super dealloc];
229-}
230-
231-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
232-#pragma mark Copying
233-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
234-
235-- (id)copyWithZone:(NSZone *)zone
236-{
237- if([self isXmlDocPtr])
238- {
239- xmlDocPtr copyDocPtr = xmlCopyDoc((xmlDocPtr)genericPtr, 1);
240-
241- if(copyDocPtr == NULL) return nil;
242-
243- return [[DDXMLDocument alloc] initWithCheckedPrimitive:(xmlKindPtr)copyDocPtr];
244- }
245-
246- if([self isXmlNodePtr])
247- {
248- xmlNodePtr copyNodePtr = xmlCopyNode((xmlNodePtr)genericPtr, 1);
249-
250- if(copyNodePtr == NULL) return nil;
251-
252- if([self isKindOfClass:[DDXMLElement class]])
253- return [[DDXMLElement alloc] initWithCheckedPrimitive:(xmlKindPtr)copyNodePtr];
254- else
255- return [[DDXMLNode alloc] initWithCheckedPrimitive:(xmlKindPtr)copyNodePtr];
256- }
257-
258- if([self isXmlAttrPtr])
259- {
260- xmlAttrPtr copyAttrPtr = xmlCopyProp(NULL, (xmlAttrPtr)genericPtr);
261-
262- if(copyAttrPtr == NULL) return nil;
263-
264- return [[DDXMLNode alloc] initWithCheckedPrimitive:(xmlKindPtr)copyAttrPtr];
265- }
266-
267- if([self isXmlNsPtr])
268- {
269- xmlNsPtr copyNsPtr = xmlCopyNamespace((xmlNsPtr)genericPtr);
270-
271- if(copyNsPtr == NULL) return nil;
272-
273- return [[DDXMLNode alloc] initWithCheckedPrimitive:copyNsPtr nsParent:NULL];
274- }
275-
276- if([self isXmlDtdPtr])
277- {
278- xmlDtdPtr copyDtdPtr = xmlCopyDtd((xmlDtdPtr)genericPtr);
279-
280- if(copyDtdPtr == NULL) return nil;
281-
282- return [[DDXMLNode alloc] initWithCheckedPrimitive:(xmlKindPtr)copyDtdPtr];
283- }
284-
285- return nil;
286-}
287-
288-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
289-#pragma mark Properties
290-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
291-
292-- (DDXMLNodeKind)kind
293-{
294- if(genericPtr != NULL)
295- return genericPtr->type;
296- else
297- return DDXMLInvalidKind;
298-}
299-
300-- (void)setName:(NSString *)name
301-{
302- if([self isXmlNsPtr])
303- {
304- xmlNsPtr ns = (xmlNsPtr)genericPtr;
305-
306- xmlFree((xmlChar *)ns->prefix);
307- ns->prefix = xmlStrdup([name xmlChar]);
308- }
309- else
310- {
311- // The xmlNodeSetName function works for both nodes and attributes
312- xmlNodeSetName((xmlNodePtr)genericPtr, [name xmlChar]);
313- }
314-}
315-
316-- (NSString *)name
317-{
318- if([self isXmlNsPtr])
319- {
320- xmlNsPtr ns = (xmlNsPtr)genericPtr;
321- if(ns->prefix != NULL)
322- return [NSString stringWithUTF8String:((const char*)ns->prefix)];
323- else
324- return @"";
325- }
326- else
327- {
328- const char *name = (const char *)((xmlStdPtr)genericPtr)->name;
329-
330- if(name == NULL)
331- return nil;
332- else
333- return [NSString stringWithUTF8String:name];
334- }
335-}
336-
337-- (void)setStringValue:(NSString *)string
338-{
339- if([self isXmlNsPtr])
340- {
341- xmlNsPtr ns = (xmlNsPtr)genericPtr;
342-
343- xmlFree((xmlChar *)ns->href);
344- ns->href = xmlEncodeSpecialChars(NULL, [string xmlChar]);
345- }
346- else if([self isXmlAttrPtr])
347- {
348- xmlAttrPtr attr = (xmlAttrPtr)genericPtr;
349-
350- if(attr->children != NULL)
351- {
352- xmlChar *escapedString = xmlEncodeSpecialChars(attr->doc, [string xmlChar]);
353- xmlNodeSetContent((xmlNodePtr)attr, escapedString);
354- xmlFree(escapedString);
355- }
356- else
357- {
358- xmlNodePtr text = xmlNewText([string xmlChar]);
359- attr->children = text;
360- }
361- }
362- else if([self isXmlNodePtr])
363- {
364- xmlStdPtr node = (xmlStdPtr)genericPtr;
365-
366- // Setting the content of a node erases any existing child nodes.
367- // Therefore, we need to remove them properly first.
368- [[self class] removeAllChildrenFromNode:(xmlNodePtr)node];
369-
370- xmlChar *escapedString = xmlEncodeSpecialChars(node->doc, [string xmlChar]);
371- xmlNodeSetContent((xmlNodePtr)node, escapedString);
372- xmlFree(escapedString);
373- }
374-}
375-
376-/**
377- * Returns the content of the receiver as a string value.
378- *
379- * If the receiver is a node object of element kind, the content is that of any text-node children.
380- * This method recursively visits elements nodes and concatenates their text nodes in document order with
381- * no intervening spaces.
382-**/
383-- (NSString *)stringValue
384-{
385- if([self isXmlNsPtr])
386- {
387- return [NSString stringWithUTF8String:((const char *)((xmlNsPtr)genericPtr)->href)];
388- }
389- else if([self isXmlAttrPtr])
390- {
391- xmlAttrPtr attr = (xmlAttrPtr)genericPtr;
392-
393- if(attr->children != NULL)
394- {
395- return [NSString stringWithUTF8String:(const char *)attr->children->content];
396- }
397-
398- return nil;
399- }
400- else if([self isXmlNodePtr])
401- {
402- xmlChar *content = xmlNodeGetContent((xmlNodePtr)genericPtr);
403-
404- NSString *result = [NSString stringWithUTF8String:(const char *)content];
405-
406- xmlFree(content);
407- return result;
408- }
409-
410- return nil;
411-}
412-
413-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
414-#pragma mark Tree Navigation
415-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
416-
417-/**
418- * Returns the index of the receiver identifying its position relative to its sibling nodes.
419- * The first child node of a parent has an index of zero.
420-**/
421-- (NSUInteger)index
422-{
423- if([self isXmlNsPtr])
424- {
425- // The xmlNsPtr has no prev pointer, so we have to search from the parent
426- if(nsParentPtr == NULL) return 0;
427-
428- xmlNsPtr currentNs = nsParentPtr->nsDef;
429-
430- NSUInteger result = 0;
431- while(currentNs != NULL)
432- {
433- if(currentNs == (xmlNsPtr)genericPtr)
434- {
435- return result;
436- }
437- result++;
438- currentNs = currentNs->next;
439- }
440- return 0;
441- }
442- else
443- {
444- xmlStdPtr node = ((xmlStdPtr)genericPtr)->prev;
445-
446- NSUInteger result = 0;
447- while(node != NULL)
448- {
449- result++;
450- node = node->prev;
451- }
452-
453- return result;
454- }
455-}
456-
457-/**
458- * Returns the nesting level of the receiver within the tree hierarchy.
459- * The root element of a document has a nesting level of one.
460-**/
461-- (NSUInteger)level
462-{
463- xmlNodePtr currentNode;
464- if([self isXmlNsPtr])
465- currentNode = nsParentPtr;
466- else
467- currentNode = ((xmlStdPtr)genericPtr)->parent;
468-
469- NSUInteger result = 0;
470- while(currentNode != NULL)
471- {
472- result++;
473- currentNode = currentNode->parent;
474- }
475-
476- return result;
477-}
478-
479-/**
480- * Returns the DDXMLDocument object containing the root element and representing the XML document as a whole.
481- * If the receiver is a standalone node (that is, a node at the head of a detached branch of the tree), this
482- * method returns nil.
483-**/
484-- (DDXMLDocument *)rootDocument
485-{
486- xmlStdPtr node;
487- if([self isXmlNsPtr])
488- node = (xmlStdPtr)nsParentPtr;
489- else
490- node = (xmlStdPtr)genericPtr;
491-
492- if(node == NULL || node->doc == NULL)
493- return nil;
494- else
495- return [DDXMLDocument nodeWithPrimitive:(xmlKindPtr)node->doc];
496-}
497-
498-/**
499- * Returns the parent node of the receiver.
500- *
501- * Document nodes and standalone nodes (that is, the root of a detached branch of a tree) have no parent, and
502- * sending this message to them returns nil. A one-to-one relationship does not always exists between a parent and
503- * its children; although a namespace or attribute node cannot be a child, it still has a parent element.
504-**/
505-- (DDXMLNode *)parent
506-{
507- if([self isXmlNsPtr])
508- {
509- if(nsParentPtr == NULL) return nil;
510-
511- return [DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)nsParentPtr];
512- }
513-
514- xmlStdPtr node = (xmlStdPtr)genericPtr;
515-
516- if(node->parent == NULL) return nil;
517-
518- return [DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)node->parent];
519-}
520-
521-/**
522- * Returns the number of child nodes the receiver has.
523- * For performance reasons, use this method instead of getting the count from the array returned by children.
524-**/
525-- (NSUInteger)childCount
526-{
527- if(![self isXmlDocPtr] && ![self isXmlNodePtr] && ![self isXmlDtdPtr]) return 0;
528-
529- NSUInteger result = 0;
530-
531- xmlNodePtr child = ((xmlStdPtr)genericPtr)->children;
532- while(child != NULL)
533- {
534- result++;
535- child = child->next;
536- }
537-
538- return result;
539-}
540-
541-/**
542- * Returns an immutable array containing the child nodes of the receiver (as DDXMLNode objects).
543-**/
544-- (NSArray *)children
545-{
546- if(![self isXmlDocPtr] && ![self isXmlNodePtr] && ![self isXmlDtdPtr]) return nil;
547-
548- NSMutableArray *result = [NSMutableArray array];
549-
550- xmlNodePtr child = ((xmlStdPtr)genericPtr)->children;
551- while(child != NULL)
552- {
553- [result addObject:[DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)child]];
554-
555- child = child->next;
556- }
557-
558- return [[result copy] autorelease];
559-}
560-
561-/**
562- * Returns the child node of the receiver at the specified location.
563- * Returns a DDXMLNode object or nil if the receiver has no children.
564- *
565- * If the receive has children and index is out of bounds, an exception is raised.
566- *
567- * The receiver should be a DDXMLNode object representing a document, element, or document type declaration.
568- * The returned node object can represent an element, comment, text, or processing instruction.
569-**/
570-- (DDXMLNode *)childAtIndex:(NSUInteger)index
571-{
572- if(![self isXmlDocPtr] && ![self isXmlNodePtr] && ![self isXmlDtdPtr]) return nil;
573-
574- NSUInteger i = 0;
575-
576- xmlNodePtr child = ((xmlStdPtr)genericPtr)->children;
577-
578- if(child == NULL)
579- {
580- // NSXML doesn't raise an exception if there are no children
581- return nil;
582- }
583-
584- while(child != NULL)
585- {
586- if(i == index)
587- {
588- return [DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)child];
589- }
590-
591- i++;
592- child = child->next;
593- }
594-
595- // NSXML version uses this same assertion
596- DDCheck(NO, @"index (%u) beyond bounds (%u)", (unsigned)index, (unsigned)i);
597-
598- return nil;
599-}
600-
601-/**
602- * Returns the previous DDXMLNode object that is a sibling node to the receiver.
603- *
604- * This object will have an index value that is one less than the receiver’s.
605- * If there are no more previous siblings (that is, other child nodes of the receiver’s parent) the method returns nil.
606-**/
607-- (DDXMLNode *)previousSibling
608-{
609- if([self isXmlNsPtr]) return nil;
610-
611- xmlStdPtr node = (xmlStdPtr)genericPtr;
612-
613- if(node->prev == NULL) return nil;
614-
615- return [DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)node->prev];
616-}
617-
618-/**
619- * Returns the next DDXMLNode object that is a sibling node to the receiver.
620- *
621- * This object will have an index value that is one more than the receiver’s.
622- * If there are no more subsequent siblings (that is, other child nodes of the receiver’s parent) the
623- * method returns nil.
624-**/
625-- (DDXMLNode *)nextSibling
626-{
627- if([self isXmlNsPtr]) return nil;
628-
629- xmlStdPtr node = (xmlStdPtr)genericPtr;
630-
631- if(node->next == NULL) return nil;
632-
633- return [DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)node->next];
634-}
635-
636-/**
637- * Returns the previous DDXMLNode object in document order.
638- *
639- * You use this method to “walk” backward through the tree structure representing an XML document or document section.
640- * (Use nextNode to traverse the tree in the opposite direction.) Document order is the natural order that XML
641- * constructs appear in markup text. If you send this message to the first node in the tree (that is, the root element),
642- * nil is returned. DDXMLNode bypasses namespace and attribute nodes when it traverses a tree in document order.
643-**/
644-- (DDXMLNode *)previousNode
645-{
646- if([self isXmlNsPtr] || [self isXmlAttrPtr]) return nil;
647-
648- // If the node has a previous sibling,
649- // then we need the last child of the last child of the last child etc
650-
651- // Note: Try to accomplish this task without creating dozens of intermediate wrapper objects
652-
653- xmlStdPtr node = (xmlStdPtr)genericPtr;
654- xmlStdPtr previousSibling = node->prev;
655-
656- if(previousSibling != NULL)
657- {
658- if(previousSibling->last != NULL)
659- {
660- xmlNodePtr lastChild = previousSibling->last;
661- while(lastChild->last != NULL)
662- {
663- lastChild = lastChild->last;
664- }
665-
666- return [DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)lastChild];
667- }
668- else
669- {
670- // The previous sibling has no children, so the previous node is simply the previous sibling
671- return [DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)previousSibling];
672- }
673- }
674-
675- // If there are no previous siblings, then the previous node is simply the parent
676-
677- // Note: rootNode.parent == docNode
678-
679- if(node->parent == NULL || node->parent->type == XML_DOCUMENT_NODE)
680- return nil;
681- else
682- return [DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)node->parent];
683-}
684-
685-/**
686- * Returns the next DDXMLNode object in document order.
687- *
688- * You use this method to “walk” forward through the tree structure representing an XML document or document section.
689- * (Use previousNode to traverse the tree in the opposite direction.) Document order is the natural order that XML
690- * constructs appear in markup text. If you send this message to the last node in the tree, nil is returned.
691- * DDXMLNode bypasses namespace and attribute nodes when it traverses a tree in document order.
692-**/
693-- (DDXMLNode *)nextNode
694-{
695- if([self isXmlNsPtr] || [self isXmlAttrPtr]) return nil;
696-
697- // If the node has children, then next node is the first child
698- DDXMLNode *firstChild = [self childAtIndex:0];
699- if(firstChild)
700- return firstChild;
701-
702- // If the node has a next sibling, then next node is the same as next sibling
703-
704- DDXMLNode *nextSibling = [self nextSibling];
705- if(nextSibling)
706- return nextSibling;
707-
708- // There are no children, and no more siblings, so we need to get the next sibling of the parent.
709- // If that is nil, we need to get the next sibling of the grandparent, etc.
710-
711- // Note: Try to accomplish this task without creating dozens of intermediate wrapper objects
712-
713- xmlNodePtr parent = ((xmlStdPtr)genericPtr)->parent;
714- while(parent != NULL)
715- {
716- xmlNodePtr parentNextSibling = parent->next;
717- if(parentNextSibling != NULL)
718- return [DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)parentNextSibling];
719- else
720- parent = parent->parent;
721- }
722-
723- return nil;
724-}
725-
726-/**
727- * Detaches the receiver from its parent node.
728- *
729- * This method is applicable to DDXMLNode objects representing elements, text, comments, processing instructions,
730- * attributes, and namespaces. Once the node object is detached, you can add it as a child node of another parent.
731-**/
732-- (void)detach
733-{
734- if([self isXmlNsPtr])
735- {
736- if(nsParentPtr != NULL)
737- {
738- [[self class] removeNamespace:(xmlNsPtr)genericPtr fromNode:nsParentPtr];
739- }
740- return;
741- }
742-
743- xmlStdPtr node = (xmlStdPtr)genericPtr;
744-
745- if(node->parent == NULL) return;
746-
747- if([self isXmlAttrPtr])
748- {
749- [[self class] detachAttribute:(xmlAttrPtr)node fromNode:node->parent];
750- }
751- else if([self isXmlNodePtr])
752- {
753- [[self class] detachChild:(xmlNodePtr)node fromNode:node->parent];
754- }
755-}
756-
757-- (NSString *)XPath
758-{
759- NSMutableString *result = [NSMutableString stringWithCapacity:25];
760-
761- // Examples:
762- // /rootElement[1]/subElement[4]/thisNode[2]
763- // topElement/thisNode[2]
764-
765- xmlStdPtr node = NULL;
766-
767- if([self isXmlNsPtr])
768- {
769- node = (xmlStdPtr)nsParentPtr;
770-
771- if(node == NULL)
772- [result appendFormat:@"namespace::%@", [self name]];
773- else
774- [result appendFormat:@"/namespace::%@", [self name]];
775- }
776- else if([self isXmlAttrPtr])
777- {
778- node = (xmlStdPtr)(((xmlAttrPtr)genericPtr)->parent);
779-
780- if(node == NULL)
781- [result appendFormat:@"@%@", [self name]];
782- else
783- [result appendFormat:@"/@%@", [self name]];
784- }
785- else
786- {
787- node = (xmlStdPtr)genericPtr;
788- }
789-
790- // Note: rootNode.parent == docNode
791-
792- while((node != NULL) && (node->type != XML_DOCUMENT_NODE))
793- {
794- if((node->parent == NULL) && (node->doc == NULL))
795- {
796- // We're at the top of the heirarchy, and there is no xml document.
797- // Thus we don't use a leading '/', and we don't need an index.
798-
799- [result insertString:[NSString stringWithFormat:@"%s", node->name] atIndex:0];
800- }
801- else
802- {
803- // Find out what index this node is.
804- // If it's the first node with this name, the index is 1.
805- // If there are previous siblings with the same name, the index is greater than 1.
806-
807- int index = 1;
808- xmlStdPtr prevNode = node->prev;
809- while(prevNode != NULL)
810- {
811- if(xmlStrEqual(node->name, prevNode->name))
812- {
813- index++;
814- }
815- prevNode = prevNode->prev;
816- }
817-
818- [result insertString:[NSString stringWithFormat:@"/%s[%i]", node->name, index] atIndex:0];
819- }
820-
821- node = (xmlStdPtr)node->parent;
822- }
823-
824- return [[result copy] autorelease];
825-}
826-
827-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
828-#pragma mark QNames
829-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
830-
831-/**
832- * Returns the local name of the receiver.
833- *
834- * The local name is the part of a node name that follows a namespace-qualifying colon or the full name if
835- * there is no colon. For example, “chapter” is the local name in the qualified name “acme:chapter”.
836-**/
837-- (NSString *)localName
838-{
839- if([self isXmlNsPtr])
840- {
841- // Strangely enough, the localName of a namespace is the prefix, and the prefix is an empty string
842- xmlNsPtr ns = (xmlNsPtr)genericPtr;
843- if(ns->prefix != NULL)
844- return [NSString stringWithUTF8String:((const char *)ns->prefix)];
845- else
846- return @"";
847- }
848-
849- return [[self class] localNameForName:[self name]];
850-}
851-
852-/**
853- * Returns the prefix of the receiver’s name.
854- *
855- * The prefix is the part of a namespace-qualified name that precedes the colon.
856- * For example, “acme” is the local name in the qualified name “acme:chapter”.
857- * This method returns an empty string if the receiver’s name is not qualified by a namespace.
858-**/
859-- (NSString *)prefix
860-{
861- if([self isXmlNsPtr])
862- {
863- // Strangely enough, the localName of a namespace is the prefix, and the prefix is an empty string
864- return @"";
865- }
866-
867- return [[self class] prefixForName:[self name]];
868-}
869-
870-/**
871- * Sets the URI identifying the source of this document.
872- * Pass nil to remove the current URI.
873-**/
874-- (void)setURI:(NSString *)URI
875-{
876- if([self isXmlNodePtr])
877- {
878- xmlNodePtr node = (xmlNodePtr)genericPtr;
879- if(node->ns != NULL)
880- {
881- [[self class] removeNamespace:node->ns fromNode:node];
882- }
883-
884- if(URI)
885- {
886- // Create a new xmlNsPtr, add it to the nsDef list, and make ns point to it
887- xmlNsPtr ns = xmlNewNs(NULL, [URI xmlChar], NULL);
888- ns->next = node->nsDef;
889- node->nsDef = ns;
890- node->ns = ns;
891- }
892- }
893- else if([self isXmlAttrPtr])
894- {
895- xmlAttrPtr attr = (xmlAttrPtr)genericPtr;
896- if(attr->ns != NULL)
897- {
898- // An attribute can only have a single namespace attached to it.
899- // In addition, this namespace can only be accessed via the URI method.
900- // There is no way, within the API, to get a DDXMLNode wrapper for the attribute's namespace.
901- xmlFreeNs(attr->ns);
902- attr->ns = NULL;
903- }
904-
905- if(URI)
906- {
907- // Create a new xmlNsPtr, and make ns point to it
908- xmlNsPtr ns = xmlNewNs(NULL, [URI xmlChar], NULL);
909- attr->ns = ns;
910- }
911- }
912-}
913-
914-/**
915- * Returns the URI associated with the receiver.
916- *
917- * A node’s URI is derived from its namespace or a document’s URI; for documents, the URI comes either from the
918- * parsed XML or is explicitly set. You cannot change the URI for a particular node other for than a namespace
919- * or document node.
920-**/
921-- (NSString *)URI
922-{
923- if([self isXmlAttrPtr])
924- {
925- xmlAttrPtr attr = (xmlAttrPtr)genericPtr;
926- if(attr->ns != NULL)
927- {
928- return [NSString stringWithUTF8String:((const char *)attr->ns->href)];
929- }
930- }
931- else if([self isXmlNodePtr])
932- {
933- xmlNodePtr node = (xmlNodePtr)genericPtr;
934- if(node->ns != NULL)
935- {
936- return [NSString stringWithUTF8String:((const char *)node->ns->href)];
937- }
938- }
939-
940- return nil;
941-}
942-
943-/**
944- * Returns the local name from the specified qualified name.
945- *
946- * Examples:
947- * "a:node" -> "node"
948- * "a:a:node" -> "a:node"
949- * "node" -> "node"
950- * nil - > nil
951-**/
952-+ (NSString *)localNameForName:(NSString *)name
953-{
954- if(name)
955- {
956- NSRange range = [name rangeOfString:@":"];
957-
958- if(range.length != 0)
959- return [name substringFromIndex:(range.location + range.length)];
960- else
961- return name;
962- }
963- return nil;
964-}
965-
966-/**
967- * Extracts the prefix from the given name.
968- * If name is nil, or has no prefix, an empty string is returned.
969- *
970- * Examples:
971- * "a:deusty.com" -> "a"
972- * "a:a:deusty.com" -> "a"
973- * "node" -> ""
974- * nil -> ""
975-**/
976-+ (NSString *)prefixForName:(NSString *)name
977-{
978- if(name)
979- {
980- NSRange range = [name rangeOfString:@":"];
981-
982- if(range.length != 0)
983- {
984- return [name substringToIndex:range.location];
985- }
986- }
987- return @"";
988-}
989-
990-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
991-#pragma mark Output
992-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
993-
994-- (NSString *)description
995-{
996- return [self XMLStringWithOptions:0];
997-}
998-
999-- (NSString *)XMLString
1000-{
1001- // Todo: Test XMLString for namespace node
1002- return [self XMLStringWithOptions:0];
1003-}
1004-
1005-- (NSString *)XMLStringWithOptions:(NSUInteger)options
1006-{
1007- // xmlSaveNoEmptyTags:
1008- // Global setting, asking the serializer to not output empty tags
1009- // as <empty/> but <empty></empty>. those two forms are undistinguishable
1010- // once parsed.
1011- // Disabled by default
1012-
1013- if(options & DDXMLNodeCompactEmptyElement)
1014- xmlSaveNoEmptyTags = 0;
1015- else
1016- xmlSaveNoEmptyTags = 1;
1017-
1018- int format = 0;
1019- if(options & DDXMLNodePrettyPrint)
1020- {
1021- format = 1;
1022- xmlIndentTreeOutput = 1;
1023- }
1024-
1025- xmlBufferPtr bufferPtr = xmlBufferCreate();
1026- if([self isXmlNsPtr])
1027- xmlNodeDump(bufferPtr, NULL, (xmlNodePtr)genericPtr, 0, format);
1028- else
1029- xmlNodeDump(bufferPtr, ((xmlStdPtr)genericPtr)->doc, (xmlNodePtr)genericPtr, 0, format);
1030-
1031- if([self kind] == DDXMLTextKind)
1032- {
1033- NSString *result = [NSString stringWithUTF8String:(const char *)bufferPtr->content];
1034-
1035- xmlBufferFree(bufferPtr);
1036-
1037- return result;
1038- }
1039- else
1040- {
1041- NSMutableString *resTmp = [NSMutableString stringWithUTF8String:(const char *)bufferPtr->content];
1042- NSString *result = [resTmp stringByTrimming];
1043-
1044- xmlBufferFree(bufferPtr);
1045-
1046- return result;
1047- }
1048-}
1049-
1050-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1051-#pragma mark XPath/XQuery
1052-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1053-
1054--(NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error
1055-{
1056- xmlXPathContextPtr xpathCtx;
1057- xmlXPathObjectPtr xpathObj;
1058-
1059- BOOL isTempDoc = NO;
1060- xmlDocPtr doc;
1061-
1062- if([DDXMLNode isXmlDocPtr:genericPtr])
1063- {
1064- doc = (xmlDocPtr)genericPtr;
1065- }
1066- else if([DDXMLNode isXmlNodePtr:genericPtr])
1067- {
1068- doc = ((xmlNodePtr)genericPtr)->doc;
1069-
1070- if(doc == NULL)
1071- {
1072- isTempDoc = YES;
1073-
1074- doc = xmlNewDoc(NULL);
1075- xmlDocSetRootElement(doc, (xmlNodePtr)genericPtr);
1076- }
1077- }
1078- else
1079- {
1080- return nil;
1081- }
1082-
1083- xpathCtx = xmlXPathNewContext(doc);
1084- xpathCtx->node = (xmlNodePtr)genericPtr;
1085-
1086- xmlNodePtr rootNode = (doc)->children;
1087- if(rootNode != NULL)
1088- {
1089- xmlNsPtr ns = rootNode->nsDef;
1090- while(ns != NULL)
1091- {
1092- xmlXPathRegisterNs(xpathCtx, ns->prefix, ns->href);
1093-
1094- ns = ns->next;
1095- }
1096- }
1097-
1098- xpathObj = xmlXPathEvalExpression([xpath xmlChar], xpathCtx);
1099-
1100- NSArray *result;
1101-
1102- if(xpathObj == NULL)
1103- {
1104- if(error) *error = [[self class] lastError];
1105- result = nil;
1106- }
1107- else
1108- {
1109- if(error) *error = nil;
1110-
1111- int count = xmlXPathNodeSetGetLength(xpathObj->nodesetval);
1112-
1113- if(count == 0)
1114- {
1115- result = [NSArray array];
1116- }
1117- else
1118- {
1119- NSMutableArray *mResult = [NSMutableArray arrayWithCapacity:count];
1120-
1121- int i;
1122- for (i = 0; i < count; i++)
1123- {
1124- xmlNodePtr node = xpathObj->nodesetval->nodeTab[i];
1125-
1126- [mResult addObject:[DDXMLNode nodeWithUnknownPrimitive:(xmlKindPtr)node]];
1127- }
1128-
1129- result = mResult;
1130- }
1131- }
1132-
1133- if(xpathObj) xmlXPathFreeObject(xpathObj);
1134- if(xpathCtx) xmlXPathFreeContext(xpathCtx);
1135-
1136- if(isTempDoc)
1137- {
1138- xmlUnlinkNode((xmlNodePtr)genericPtr);
1139- xmlFreeDoc(doc);
1140-
1141- // xmlUnlinkNode doesn't remove the doc ptr
1142- [[self class] recursiveStripDocPointersFromNode:(xmlNodePtr)genericPtr];
1143- }
1144-
1145- return result;
1146-}
1147-
1148-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1149-#pragma mark Private API
1150-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1151-
1152-/**
1153- * Returns whether or not the given node is of type xmlAttrPtr.
1154-**/
1155-+ (BOOL)isXmlAttrPtr:(xmlKindPtr)kindPtr
1156-{
1157- return kindPtr->type == XML_ATTRIBUTE_NODE;
1158-}
1159-
1160-/**
1161- * Returns whether or not the genericPtr is of type xmlAttrPtr.
1162-**/
1163-- (BOOL)isXmlAttrPtr
1164-{
1165- return [[self class] isXmlAttrPtr:genericPtr];
1166-}
1167-
1168-/**
1169- * Returns whether or not the given node is of type xmlNodePtr.
1170-**/
1171-+ (BOOL)isXmlNodePtr:(xmlKindPtr)kindPtr
1172-{
1173- xmlElementType type = kindPtr->type;
1174- switch(type)
1175- {
1176- case XML_ELEMENT_NODE :
1177- case XML_PI_NODE :
1178- case XML_COMMENT_NODE :
1179- case XML_TEXT_NODE :
1180- case XML_CDATA_SECTION_NODE : return YES;
1181- default : return NO;
1182- }
1183-}
1184-
1185-/**
1186- * Returns whether or not the genericPtr is of type xmlNodePtr.
1187-**/
1188-- (BOOL)isXmlNodePtr
1189-{
1190- return [[self class] isXmlNodePtr:genericPtr];
1191-}
1192-
1193-/**
1194- * Returns whether or not the given node is of type xmlDocPtr.
1195-**/
1196-+ (BOOL)isXmlDocPtr:(xmlKindPtr)kindPtr
1197-{
1198- return kindPtr->type == XML_DOCUMENT_NODE;
1199-}
1200-
1201-/**
1202- * Returns whether or not the genericPtr is of type xmlDocPtr.
1203-**/
1204-- (BOOL)isXmlDocPtr
1205-{
1206- return [[self class] isXmlDocPtr:genericPtr];
1207-}
1208-
1209-/**
1210- * Returns whether or not the given node is of type xmlDtdPtr.
1211-**/
1212-+ (BOOL)isXmlDtdPtr:(xmlKindPtr)kindPtr
1213-{
1214- return kindPtr->type == XML_DTD_NODE;
1215-}
1216-
1217-/**
1218- * Returns whether or not the genericPtr is of type xmlDtdPtr.
1219-**/
1220-- (BOOL)isXmlDtdPtr
1221-{
1222- return [[self class] isXmlDtdPtr:genericPtr];
1223-}
1224-
1225-/**
1226- * Returns whether or not the given node is of type xmlNsPtr.
1227-**/
1228-+ (BOOL)isXmlNsPtr:(xmlKindPtr)kindPtr
1229-{
1230- return kindPtr->type == XML_NAMESPACE_DECL;
1231-}
1232-
1233-/**
1234- * Returns whether or not the genericPtr is of type xmlNsPtr.
1235-**/
1236-- (BOOL)isXmlNsPtr
1237-{
1238- return [[self class] isXmlNsPtr:genericPtr];
1239-}
1240-
1241-/**
1242- * Returns whether or not the node has a parent.
1243- * Use this method instead of parent when you only need to ensure parent is nil.
1244- * This prevents the unnecessary creation of a parent node wrapper.
1245-**/
1246-- (BOOL)hasParent
1247-{
1248- if([self isXmlNsPtr])
1249- {
1250- return (nsParentPtr != NULL);
1251- }
1252-
1253- xmlStdPtr node = (xmlStdPtr)genericPtr;
1254-
1255- return (node->parent != NULL);
1256-}
1257-
1258-/**
1259- * - - - - - - - - - - R E A D M E - - - - - - - - - -
1260- *
1261- * The memory management of these wrapper classes is straight-forward, but requires explanation.
1262- * To understand the problem, consider the following situation:
1263- *
1264- * <root>
1265- * <level1>
1266- * <level2/>
1267- * </level1>
1268- * </root>
1269- *
1270- * Imagine the user has retained two DDXMLElements - one for root, and one for level2.
1271- * Then they release the root element, but they want to hold onto the level2 element.
1272- * We need to release root, and level1, but keep level2 intact until the user is done with it.
1273- * Note that this is also how the NSXML classes work.
1274- * The user will no longer be able to traverse up the tree from level2, but will be able to access all the normal
1275- * information in level2, as well as any children, if there was any.
1276- *
1277- * So the first question is, how do we know if a libxml node is being referenced by a cocoa wrapper?
1278- * In order to accomplish this, we take advantage of the node's _private variable.
1279- * If the private variable is NULL, then the node isn't being directly referenced by any cocoa wrapper objects.
1280- * If the private variable is NON-NULL, then the private variable points to the cocoa wrapper object.
1281- * When a cocoa wrapper object is created, it points the private variable to itself (via nodeRetain),
1282- * and when it's dealloced it sets the private variable back to NULL (via nodeRelease).
1283- *
1284- * With this simple technique, then given any libxml node, we can easily determine if it's still needed,
1285- * or if we can free it:
1286- * Is there a cocoa wrapper objects still directly referring to the node?
1287- * If so, we can't free the node.
1288- * Otherwise, does the node still have a parent?
1289- * If so, then the node is still part of a heirarchy, and we can't free the node.
1290- *
1291- * To fully understand the parent restriction, consider the following scenario:
1292- * Imagine the user extracts the level1 DDXMLElement from the root.
1293- * The user reads the data, and the level1 DDXMLElement is autoreleased. The root is still retained.
1294- * When the level1 DDXMLElement is dealloced, nodeRelease will be called, and the private variable will be set to NULL.
1295- * Can we free the level1 node at this point?
1296- * Of course not, because it's still within the root heirarchy, and the user is still using the root element.
1297- *
1298- * The following should be spelled out:
1299- * If you call libxml's xmlFreeNode(), this method will free all linked attributes and children.
1300- * So you can't blindly call this method, because you can't free nodes that are still being referenced.
1301-**/
1302-
1303-
1304-+ (void)stripDocPointersFromAttr:(xmlAttrPtr)attr
1305-{
1306- xmlNodePtr child = attr->children;
1307- while(child != NULL)
1308- {
1309- child->doc = NULL;
1310- child = child->next;
1311- }
1312-
1313- attr->doc = NULL;
1314-}
1315-
1316-+ (void)recursiveStripDocPointersFromNode:(xmlNodePtr)node
1317-{
1318- xmlAttrPtr attr = node->properties;
1319- while(attr != NULL)
1320- {
1321- [self stripDocPointersFromAttr:attr];
1322- attr = attr->next;
1323- }
1324-
1325- xmlNodePtr child = node->children;
1326- while(child != NULL)
1327- {
1328- [self recursiveStripDocPointersFromNode:child];
1329- child = child->next;
1330- }
1331-
1332- node->doc = NULL;
1333-}
1334-
1335-/**
1336- * This method will recursively free the given node, as long as the node is no longer being referenced.
1337- * If the node is still being referenced, then it's parent, prev, next and doc pointers are destroyed.
1338-**/
1339-+ (void)nodeFree:(xmlNodePtr)node
1340-{
1341- NSAssert1([self isXmlNodePtr:(xmlKindPtr)node], @"Wrong kind of node passed to nodeFree: %i", node->type);
1342-
1343- if(node->_private == NULL)
1344- {
1345- [self removeAllAttributesFromNode:node];
1346- [self removeAllNamespacesFromNode:node];
1347- [self removeAllChildrenFromNode:node];
1348-
1349- xmlFreeNode(node);
1350- }
1351- else
1352- {
1353- node->parent = NULL;
1354- node->prev = NULL;
1355- node->next = NULL;
1356- if(node->doc != NULL) [self recursiveStripDocPointersFromNode:node];
1357- }
1358-}
1359-
1360-/**
1361- * Detaches the given attribute from the given node.
1362- * The attribute's surrounding prev/next pointers are properly updated to remove the attribute from the attr list.
1363- * Then the attribute's parent, prev, next and doc pointers are destroyed.
1364-**/
1365-+ (void)detachAttribute:(xmlAttrPtr)attr fromNode:(xmlNodePtr)node
1366-{
1367- // Update the surrounding prev/next pointers
1368- if(attr->prev == NULL)
1369- {
1370- if(attr->next == NULL)
1371- {
1372- node->properties = NULL;
1373- }
1374- else
1375- {
1376- node->properties = attr->next;
1377- attr->next->prev = NULL;
1378- }
1379- }
1380- else
1381- {
1382- if(attr->next == NULL)
1383- {
1384- attr->prev->next = NULL;
1385- }
1386- else
1387- {
1388- attr->prev->next = attr->next;
1389- attr->next->prev = attr->prev;
1390- }
1391- }
1392-
1393- // Nullify pointers
1394- attr->parent = NULL;
1395- attr->prev = NULL;
1396- attr->next = NULL;
1397- if(attr->doc != NULL) [self stripDocPointersFromAttr:attr];
1398-}
1399-
1400-/**
1401- * Removes the given attribute from the given node.
1402- * The attribute's surrounding prev/next pointers are properly updated to remove the attribute from the attr list.
1403- * Then the attribute is freed if it's no longer being referenced.
1404- * Otherwise, it's parent, prev, next and doc pointers are destroyed.
1405-**/
1406-+ (void)removeAttribute:(xmlAttrPtr)attr fromNode:(xmlNodePtr)node
1407-{
1408- [self detachAttribute:attr fromNode:node];
1409-
1410- // Free the attr if it's no longer in use
1411- if(attr->_private == NULL)
1412- {
1413- xmlFreeProp(attr);
1414- }
1415-}
1416-
1417-/**
1418- * Removes all attributes from the given node.
1419- * All attributes are either freed, or their parent, prev, next and doc pointers are properly destroyed.
1420- * Upon return, the given node's properties pointer is NULL.
1421-**/
1422-+ (void)removeAllAttributesFromNode:(xmlNodePtr)node
1423-{
1424- xmlAttrPtr attr = node->properties;
1425-
1426- while(attr != NULL)
1427- {
1428- xmlAttrPtr nextAttr = attr->next;
1429-
1430- // Free the attr if it's no longer in use
1431- if(attr->_private == NULL)
1432- {
1433- xmlFreeProp(attr);
1434- }
1435- else
1436- {
1437- attr->parent = NULL;
1438- attr->prev = NULL;
1439- attr->next = NULL;
1440- if(attr->doc != NULL) [self stripDocPointersFromAttr:attr];
1441- }
1442-
1443- attr = nextAttr;
1444- }
1445-
1446- node->properties = NULL;
1447-}
1448-
1449-/**
1450- * Detaches the given namespace from the given node.
1451- * The namespace's surrounding next pointers are properly updated to remove the namespace from the node's nsDef list.
1452- * Then the namespace's parent and next pointers are destroyed.
1453-**/
1454-+ (void)detachNamespace:(xmlNsPtr)ns fromNode:(xmlNodePtr)node
1455-{
1456- // Namespace nodes have no previous pointer, so we have to search for the node
1457- xmlNsPtr previousNs = NULL;
1458- xmlNsPtr currentNs = node->nsDef;
1459- while(currentNs != NULL)
1460- {
1461- if(currentNs == ns)
1462- {
1463- if(previousNs == NULL)
1464- node->nsDef = currentNs->next;
1465- else
1466- previousNs->next = currentNs->next;
1467-
1468- break;
1469- }
1470-
1471- previousNs = currentNs;
1472- currentNs = currentNs->next;
1473- }
1474-
1475- // Nullify pointers
1476- ns->next = NULL;
1477-
1478- if(node->ns == ns)
1479- {
1480- node->ns = NULL;
1481- }
1482-
1483- // We also have to nullify the nsParentPtr, which is in the cocoa wrapper object (if one exists)
1484- if(ns->_private != NULL)
1485- {
1486- DDXMLNode *node = (DDXMLNode *)ns->_private;
1487- node->nsParentPtr = NULL;
1488- }
1489-}
1490-
1491-/**
1492- * Removes the given namespace from the given node.
1493- * The namespace's surrounding next pointers are properly updated to remove the namespace from the nsDef list.
1494- * Then the namespace is freed if it's no longer being referenced.
1495- * Otherwise, it's nsParent and next pointers are destroyed.
1496-**/
1497-+ (void)removeNamespace:(xmlNsPtr)ns fromNode:(xmlNodePtr)node
1498-{
1499- [self detachNamespace:ns fromNode:node];
1500-
1501- // Free the ns if it's no longer in use
1502- if(ns->_private == NULL)
1503- {
1504- xmlFreeNs(ns);
1505- }
1506-}
1507-
1508-/**
1509- * Removes all namespaces from the given node.
1510- * All namespaces are either freed, or their nsParent and next pointers are properly destroyed.
1511- * Upon return, the given node's nsDef pointer is NULL.
1512-**/
1513-+ (void)removeAllNamespacesFromNode:(xmlNodePtr)node
1514-{
1515- xmlNsPtr ns = node->nsDef;
1516-
1517- while(ns != NULL)
1518- {
1519- xmlNsPtr nextNs = ns->next;
1520-
1521- // We manage the nsParent pointer, which is in the cocoa wrapper object, so we have to nullify it ourself
1522- if(ns->_private != NULL)
1523- {
1524- DDXMLNode *node = (DDXMLNode *)ns->_private;
1525- node->nsParentPtr = NULL;
1526- }
1527-
1528- // Free the ns if it's no longer in use
1529- if(ns->_private == NULL)
1530- {
1531- xmlFreeNs(ns);
1532- }
1533- else
1534- {
1535- ns->next = NULL;
1536- }
1537-
1538- ns = nextNs;
1539- }
1540-
1541- node->nsDef = NULL;
1542- node->ns = NULL;
1543-}
1544-
1545-/**
1546- * Detaches the given child from the given node.
1547- * The child's surrounding prev/next pointers are properly updated to remove the child from the node's children list.
1548- * Then, if flag is YES, the child's parent, prev, next and doc pointers are destroyed.
1549-**/
1550-+ (void)detachChild:(xmlNodePtr)child fromNode:(xmlNodePtr)node andNullifyPointers:(BOOL)flag
1551-{
1552- // Update the surrounding prev/next pointers
1553- if(child->prev == NULL)
1554- {
1555- if(child->next == NULL)
1556- {
1557- node->children = NULL;
1558- node->last = NULL;
1559- }
1560- else
1561- {
1562- node->children = child->next;
1563- child->next->prev = NULL;
1564- }
1565- }
1566- else
1567- {
1568- if(child->next == NULL)
1569- {
1570- node->last = child->prev;
1571- child->prev->next = NULL;
1572- }
1573- else
1574- {
1575- child->prev->next = child->next;
1576- child->next->prev = child->prev;
1577- }
1578- }
1579-
1580- if(flag)
1581- {
1582- // Nullify pointers
1583- child->parent = NULL;
1584- child->prev = NULL;
1585- child->next = NULL;
1586- if(child->doc != NULL) [self recursiveStripDocPointersFromNode:child];
1587- }
1588-}
1589-
1590-/**
1591- * Detaches the given child from the given node.
1592- * The child's surrounding prev/next pointers are properly updated to remove the child from the node's children list.
1593- * Then the child's parent, prev, next and doc pointers are destroyed.
1594-**/
1595-+ (void)detachChild:(xmlNodePtr)child fromNode:(xmlNodePtr)node
1596-{
1597- [self detachChild:child fromNode:node andNullifyPointers:YES];
1598-}
1599-
1600-/**
1601- * Removes the given child from the given node.
1602- * The child's surrounding prev/next pointers are properly updated to remove the child from the node's children list.
1603- * Then the child is recursively freed if it's no longer being referenced.
1604- * Otherwise, it's parent, prev, next and doc pointers are destroyed.
1605- *
1606- * During the recursive free, subnodes still being referenced are properly handled.
1607-**/
1608-+ (void)removeChild:(xmlNodePtr)child fromNode:(xmlNodePtr)node
1609-{
1610- // We perform a wee bit of optimization here.
1611- // Imagine that we're removing the root element of a big tree, and none of the elements are retained.
1612- // If we simply call detachChild:fromNode:, this will traverse the entire tree, nullifying doc pointers.
1613- // Then, when we call nodeFree:, it will again traverse the entire tree, freeing all the nodes.
1614- // To avoid this double traversal, we skip the nullification step in the detach method, and let nodeFree do it.
1615- [self detachChild:child fromNode:node andNullifyPointers:NO];
1616-
1617- // Free the child recursively if it's no longer in use
1618- [self nodeFree:child];
1619-}
1620-
1621-/**
1622- * Removes all children from the given node.
1623- * All children are either recursively freed, or their parent, prev, next and doc pointers are properly destroyed.
1624- * Upon return, the given node's children pointer is NULL.
1625- *
1626- * During the recursive free, subnodes still being referenced are properly handled.
1627-**/
1628-+ (void)removeAllChildrenFromNode:(xmlNodePtr)node
1629-{
1630- xmlNodePtr child = node->children;
1631-
1632- while(child != NULL)
1633- {
1634- xmlNodePtr nextChild = child->next;
1635-
1636- // Free the child recursively if it's no longer in use
1637- [self nodeFree:child];
1638-
1639- child = nextChild;
1640- }
1641-
1642- node->children = NULL;
1643- node->last = NULL;
1644-}
1645-
1646-/**
1647- * Removes the root element from the given document.
1648-**/
1649-+ (void)removeAllChildrenFromDoc:(xmlDocPtr)doc
1650-{
1651- xmlNodePtr child = doc->children;
1652-
1653- while(child != NULL)
1654- {
1655- xmlNodePtr nextChild = child->next;
1656-
1657- if(child->type == XML_ELEMENT_NODE)
1658- {
1659- // Remove child from list of children
1660- if(child->prev != NULL)
1661- {
1662- child->prev->next = child->next;
1663- }
1664- if(child->next != NULL)
1665- {
1666- child->next->prev = child->prev;
1667- }
1668- if(doc->children == child)
1669- {
1670- doc->children = child->next;
1671- }
1672- if(doc->last == child)
1673- {
1674- doc->last = child->prev;
1675- }
1676-
1677- // Free the child recursively if it's no longer in use
1678- [self nodeFree:child];
1679- }
1680- else
1681- {
1682- // Leave comments and DTD's embedded in the doc's child list.
1683- // They will get freed in xmlFreeDoc.
1684- }
1685-
1686- child = nextChild;
1687- }
1688-}
1689-
1690-/**
1691- * Adds self to the node's retain list.
1692- * This way we know the node is still being referenced, and it won't be improperly freed.
1693-**/
1694-- (void)nodeRetain
1695-{
1696- // Warning: The _private variable is in a different location in the xmlNsPtr
1697-
1698- if([self isXmlNsPtr])
1699- ((xmlNsPtr)genericPtr)->_private = self;
1700- else
1701- ((xmlStdPtr)genericPtr)->_private = self;
1702-}
1703-
1704-/**
1705- * Removes self from the node's retain list.
1706- * If the node is no longer being referenced, and it's not still embedded within a heirarchy above, then
1707- * the node is properly freed. This includes element nodes, which are recursively freed, detaching any subnodes
1708- * that are still being referenced.
1709-**/
1710-- (void)nodeRelease
1711-{
1712- // Check to see if the node can be released.
1713- // Did you read the giant readme comment section above?
1714-
1715- // Warning: The _private variable is in a different location in the xmlNsPtr
1716-
1717- if([self isXmlNsPtr])
1718- {
1719- xmlNsPtr ns = (xmlNsPtr)genericPtr;
1720- ns->_private = NULL;
1721-
1722- if(nsParentPtr == NULL)
1723- {
1724- xmlFreeNs(ns);
1725- }
1726- else
1727- {
1728- // The node still has a parent, so it's still in use
1729- }
1730- }
1731- else
1732- {
1733- xmlStdPtr node = (xmlStdPtr)genericPtr;
1734- node->_private = NULL;
1735-
1736- if(node->parent == NULL)
1737- {
1738- if([self isXmlAttrPtr])
1739- {
1740- xmlFreeProp((xmlAttrPtr)genericPtr);
1741- }
1742- else if([self isXmlDtdPtr])
1743- {
1744- xmlFreeDtd((xmlDtdPtr)genericPtr);
1745- }
1746- else if([self isXmlDocPtr])
1747- {
1748- [[self class] removeAllChildrenFromDoc:(xmlDocPtr)genericPtr];
1749- xmlFreeDoc((xmlDocPtr)genericPtr);
1750- }
1751- else
1752- {
1753- [[self class] nodeFree:(xmlNodePtr)genericPtr];
1754- }
1755- }
1756- else
1757- {
1758- // The node still has a parent, so it's still in use
1759- }
1760- }
1761-}
1762-
1763-/**
1764- * Returns the last error encountered by libxml.
1765- * Errors are caught in the MyErrorHandler method within DDXMLDocument.
1766-**/
1767-+ (NSError *)lastError
1768-{
1769- NSValue *lastErrorValue = [[[NSThread currentThread] threadDictionary] objectForKey:DDLastErrorKey];
1770- if(lastErrorValue)
1771- {
1772- xmlError lastError;
1773- [lastErrorValue getValue:&lastError];
1774-
1775- int errCode = lastError.code;
1776- NSString *errMsg = [[NSString stringWithFormat:@"%s", lastError.message] stringByTrimming];
1777-
1778- NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
1779-
1780- return [NSError errorWithDomain:@"DDXMLErrorDomain" code:errCode userInfo:info];
1781- }
1782- else
1783- {
1784- return nil;
1785- }
1786-}
1787-
1788-static void MyErrorHandler(void * userData, xmlErrorPtr error)
1789-{
1790- // This method is called by libxml when an error occurs.
1791- // We register for this error in the initialize method below.
1792-
1793- // Extract error message and store in the current thread's dictionary.
1794- // This ensure's thread safey, and easy access for all other DDXML classes.
1795-
1796- if(error == NULL)
1797- {
1798- [[[NSThread currentThread] threadDictionary] removeObjectForKey:DDLastErrorKey];
1799- }
1800- else
1801- {
1802- NSValue *errorValue = [NSValue valueWithBytes:error objCType:@encode(xmlError)];
1803-
1804- [[[NSThread currentThread] threadDictionary] setObject:errorValue forKey:DDLastErrorKey];
1805- }
1806-}
1807-
1808-@end
--- trunk/0.2.X/DDXMLDocument.h (revision 271)
+++ trunk/0.2.X/DDXMLDocument.h (nonexistent)
@@ -1,67 +0,0 @@
1-#import <Foundation/Foundation.h>
2-#import "DDXMLElement.h"
3-#import "DDXMLNode.h"
4-
5-
6-enum {
7- DDXMLDocumentXMLKind = 0,
8- DDXMLDocumentXHTMLKind,
9- DDXMLDocumentHTMLKind,
10- DDXMLDocumentTextKind
11-};
12-typedef NSUInteger DDXMLDocumentContentKind;
13-
14-@interface DDXMLDocument : DDXMLNode
15-{
16-}
17-
18-- (id)initWithXMLString:(NSString *)string options:(NSUInteger)mask error:(NSError **)error;
19-//- (id)initWithContentsOfURL:(NSURL *)url options:(NSUInteger)mask error:(NSError **)error;
20-- (id)initWithData:(NSData *)data options:(NSUInteger)mask error:(NSError **)error;
21-//- (id)initWithRootElement:(DDXMLElement *)element;
22-
23-//+ (Class)replacementClassForClass:(Class)cls;
24-
25-//- (void)setCharacterEncoding:(NSString *)encoding; //primitive
26-//- (NSString *)characterEncoding; //primitive
27-
28-//- (void)setVersion:(NSString *)version;
29-//- (NSString *)version;
30-
31-//- (void)setStandalone:(BOOL)standalone;
32-//- (BOOL)isStandalone;
33-
34-//- (void)setDocumentContentKind:(DDXMLDocumentContentKind)kind;
35-//- (DDXMLDocumentContentKind)documentContentKind;
36-
37-//- (void)setMIMEType:(NSString *)MIMEType;
38-//- (NSString *)MIMEType;
39-
40-//- (void)setDTD:(DDXMLDTD *)documentTypeDeclaration;
41-//- (DDXMLDTD *)DTD;
42-
43-//- (void)setRootElement:(DDXMLNode *)root;
44-- (DDXMLElement *)rootElement;
45-
46-//- (void)insertChild:(DDXMLNode *)child atIndex:(NSUInteger)index;
47-
48-//- (void)insertChildren:(NSArray *)children atIndex:(NSUInteger)index;
49-
50-//- (void)removeChildAtIndex:(NSUInteger)index;
51-
52-//- (void)setChildren:(NSArray *)children;
53-
54-//- (void)addChild:(DDXMLNode *)child;
55-
56-//- (void)replaceChildAtIndex:(NSUInteger)index withNode:(DDXMLNode *)node;
57-
58-- (NSData *)XMLData;
59-- (NSData *)XMLDataWithOptions:(NSUInteger)options;
60-
61-//- (id)objectByApplyingXSLT:(NSData *)xslt arguments:(NSDictionary *)arguments error:(NSError **)error;
62-//- (id)objectByApplyingXSLTString:(NSString *)xslt arguments:(NSDictionary *)arguments error:(NSError **)error;
63-//- (id)objectByApplyingXSLTAtURL:(NSURL *)xsltURL arguments:(NSDictionary *)argument error:(NSError **)error;
64-
65-//- (BOOL)validateAndReturnError:(NSError **)error;
66-
67-@end
--- trunk/0.2.X/DDXMLDocument.m (revision 271)
+++ trunk/0.2.X/DDXMLDocument.m (nonexistent)
@@ -1,111 +0,0 @@
1-#import "DDXMLDocument.h"
2-#import "NSStringAdditions.h"
3-#import "DDXMLPrivate.h"
4-
5-
6-@implementation DDXMLDocument
7-
8-/**
9- * Returns a DDXML wrapper object for the given primitive node.
10- * The given node MUST be non-NULL and of the proper type.
11- *
12- * If the wrapper object already exists, it is retained/autoreleased and returned.
13- * Otherwise a new wrapper object is alloc/init/autoreleased and returned.
14-**/
15-+ (id)nodeWithPrimitive:(xmlKindPtr)kindPtr
16-{
17- // If a wrapper object already exists, the _private variable is pointing to it.
18-
19- xmlDocPtr doc = (xmlDocPtr)kindPtr;
20- if(doc->_private == NULL)
21- return [[[DDXMLDocument alloc] initWithCheckedPrimitive:kindPtr] autorelease];
22- else
23- return [[((DDXMLDocument *)(doc->_private)) retain] autorelease];
24-}
25-
26-/**
27- * Returns a DDXML wrapper object for the given primitive node.
28- * The given node MUST be non-NULL and of the proper type.
29- *
30- * The given node is checked, meaning a wrapper object for it does not already exist.
31-**/
32-- (id)initWithCheckedPrimitive:(xmlKindPtr)kindPtr
33-{
34- self = [super initWithCheckedPrimitive:kindPtr];
35- return self;
36-}
37-
38-/**
39- * Initializes and returns a DDXMLDocument object created from an NSData object.
40- *
41- * Returns an initialized DDXMLDocument object, or nil if initialization fails
42- * because of parsing errors or other reasons.
43-**/
44-- (id)initWithXMLString:(NSString *)string options:(NSUInteger)mask error:(NSError **)error
45-{
46- return [self initWithData:[string dataUsingEncoding:NSUTF8StringEncoding] options:mask error:error];
47-}
48-
49-/**
50- * Initializes and returns a DDXMLDocument object created from an NSData object.
51- *
52- * Returns an initialized DDXMLDocument object, or nil if initialization fails
53- * because of parsing errors or other reasons.
54-**/
55-- (id)initWithData:(NSData *)data options:(NSUInteger)mask error:(NSError **)error
56-{
57- if(data == nil || [data length] == 0)
58- {
59- if(error) *error = [NSError errorWithDomain:@"DDXMLErrorDomain" code:0 userInfo:nil];
60-
61- [self release];
62- return nil;
63- }
64-
65- // Even though xmlKeepBlanksDefault(0) is called in DDXMLNode's initialize method,
66- // it has been documented that this call seems to get reset on the iPhone:
67- // http://code.google.com/p/kissxml/issues/detail?id=8
68- //
69- // Therefore, we call it again here just to be safe.
70- xmlKeepBlanksDefault(0);
71-
72- xmlDocPtr doc = xmlParseMemory([data bytes], [data length]);
73- if(doc == NULL)
74- {
75- if(error) *error = [NSError errorWithDomain:@"DDXMLErrorDomain" code:1 userInfo:nil];
76-
77- [self release];
78- return nil;
79- }
80-
81- return [self initWithCheckedPrimitive:(xmlKindPtr)doc];
82-}
83-
84-/**
85- * Returns the root element of the receiver.
86-**/
87-- (DDXMLElement *)rootElement
88-{
89- xmlDocPtr doc = (xmlDocPtr)genericPtr;
90-
91- // doc->children is a list containing possibly comments, DTDs, etc...
92-
93- xmlNodePtr rootNode = xmlDocGetRootElement(doc);
94-
95- if(rootNode != NULL)
96- return [DDXMLElement nodeWithPrimitive:(xmlKindPtr)rootNode];
97- else
98- return nil;
99-}
100-
101-- (NSData *)XMLData
102-{
103- return [[self XMLString] dataUsingEncoding:NSUTF8StringEncoding];
104-}
105-
106-- (NSData *)XMLDataWithOptions:(NSUInteger)options
107-{
108- return [[self XMLStringWithOptions:options] dataUsingEncoding:NSUTF8StringEncoding];
109-}
110-
111-@end
--- trunk/0.2.X/DDXMLElement.h (revision 271)
+++ trunk/0.2.X/DDXMLElement.h (nonexistent)
@@ -1,49 +0,0 @@
1-#import <Foundation/Foundation.h>
2-#import "DDXMLNode.h"
3-
4-
5-@interface DDXMLElement : DDXMLNode
6-{
7-}
8-
9-- (id)initWithName:(NSString *)name;
10-- (id)initWithName:(NSString *)name URI:(NSString *)URI;
11-- (id)initWithName:(NSString *)name stringValue:(NSString *)string;
12-- (id)initWithXMLString:(NSString *)string error:(NSError **)error;
13-
14-#pragma mark --- Elements by name ---
15-
16-- (NSArray *)elementsForName:(NSString *)name;
17-- (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI;
18-
19-#pragma mark --- Attributes ---
20-
21-- (void)addAttribute:(DDXMLNode *)attribute;
22-- (void)removeAttributeForName:(NSString *)name;
23-- (void)setAttributes:(NSArray *)attributes;
24-//- (void)setAttributesAsDictionary:(NSDictionary *)attributes;
25-- (NSArray *)attributes;
26-- (DDXMLNode *)attributeForName:(NSString *)name;
27-//- (DDXMLNode *)attributeForLocalName:(NSString *)localName URI:(NSString *)URI;
28-
29-#pragma mark --- Namespaces ---
30-
31-- (void)addNamespace:(DDXMLNode *)aNamespace;
32-- (void)removeNamespaceForPrefix:(NSString *)name;
33-- (void)setNamespaces:(NSArray *)namespaces;
34-- (NSArray *)namespaces;
35-- (DDXMLNode *)namespaceForPrefix:(NSString *)prefix;
36-- (DDXMLNode *)resolveNamespaceForName:(NSString *)name;
37-- (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI;
38-
39-#pragma mark --- Children ---
40-
41-- (void)insertChild:(DDXMLNode *)child atIndex:(NSUInteger)index;
42-//- (void)insertChildren:(NSArray *)children atIndex:(NSUInteger)index;
43-- (void)removeChildAtIndex:(NSUInteger)index;
44-- (void)setChildren:(NSArray *)children;
45-- (void)addChild:(DDXMLNode *)child;
46-//- (void)replaceChildAtIndex:(NSUInteger)index withNode:(DDXMLNode *)node;
47-//- (void)normalizeAdjacentTextNodesPreservingCDATA:(BOOL)preserve;
48-
49-@end
--- trunk/0.2.X/DDXMLElement.m (revision 271)
+++ trunk/0.2.X/DDXMLElement.m (nonexistent)
@@ -1,610 +0,0 @@
1-#import "DDXMLElement.h"
2-#import "NSStringAdditions.h"
3-#import "DDXMLPrivate.h"
4-
5-
6-@implementation DDXMLElement
7-
8-/**
9- * Returns a DDXML wrapper object for the given primitive node.
10- * The given node MUST be non-NULL and of the proper type.
11- *
12- * If the wrapper object already exists, it is retained/autoreleased and returned.
13- * Otherwise a new wrapper object is alloc/init/autoreleased and returned.
14-**/
15-+ (id)nodeWithPrimitive:(xmlKindPtr)kindPtr
16-{
17- // If a wrapper object already exists, the _private variable is pointing to it.
18-
19- xmlNodePtr node = (xmlNodePtr)kindPtr;
20- if(node->_private == NULL)
21- return [[[DDXMLElement alloc] initWithCheckedPrimitive:kindPtr] autorelease];
22- else
23- return [[((DDXMLElement *)(node->_private)) retain] autorelease];
24-}
25-
26-/**
27- * Returns a DDXML wrapper object for the given primitive node.
28- * The given node MUST be non-NULL and of the proper type.
29- *
30- * The given node is checked, meaning a wrapper object for it does not already exist.
31-**/
32-- (id)initWithCheckedPrimitive:(xmlKindPtr)kindPtr
33-{
34- self = [super initWithCheckedPrimitive:kindPtr];
35- return self;
36-}
37-
38-- (id)initWithName:(NSString *)name
39-{
40- // Note: Make every guarantee that genericPtr is not null
41-
42- xmlNodePtr node = xmlNewNode(NULL, [name xmlChar]);
43- if(node == NULL)
44- {
45- [self release];
46- return nil;
47- }
48-
49- return [self initWithCheckedPrimitive:(xmlKindPtr)node];
50-}
51-
52-- (id)initWithName:(NSString *)name URI:(NSString *)URI
53-{
54- // Note: Make every guarantee that genericPtr is not null
55-
56- xmlNodePtr node = xmlNewNode(NULL, [name xmlChar]);
57- if(node == NULL)
58- {
59- [self release];
60- return nil;
61- }
62-
63- DDXMLElement *result = [self initWithCheckedPrimitive:(xmlKindPtr)node];
64- [result setURI:URI];
65-
66- return result;
67-}
68-
69-- (id)initWithName:(NSString *)name stringValue:(NSString *)string
70-{
71- // Note: Make every guarantee that genericPtr is not null
72-
73- xmlNodePtr node = xmlNewNode(NULL, [name xmlChar]);
74- if(node == NULL)
75- {
76- [self release];
77- return nil;
78- }
79-
80- DDXMLElement *result = [self initWithCheckedPrimitive:(xmlKindPtr)node];
81- [result setStringValue:string];
82-
83- return result;
84-}
85-
86-- (id)initWithXMLString:(NSString *)string error:(NSError **)error
87-{
88- DDXMLDocument *doc = [[DDXMLDocument alloc] initWithXMLString:string options:0 error:error];
89- if(doc == nil)
90- {
91- [self release];
92- return nil;
93- }
94-
95- DDXMLElement *result = [doc rootElement];
96- [result detach];
97- [doc release];
98-
99- [self release];
100- return [result retain];
101-}
102-
103-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104-#pragma mark Elements by name
105-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
106-
107-/**
108- * Returns the child element nodes (as DDXMLElement objects) of the receiver that have a specified name.
109- *
110- * If name is a qualified name, then this method invokes elementsForLocalName:URI: with the URI parameter set to
111- * the URI associated with the prefix. Otherwise comparison is based on string equality of the qualified or
112- * non-qualified name.
113-**/
114-- (NSArray *)elementsForName:(NSString *)name
115-{
116- if(name == nil) return [NSArray array];
117-
118- // We need to check to see if name has a prefix.
119- // If it does have a prefix, we need to figure out what the corresponding URI is for that prefix,
120- // and then search for any elements that have the same name (including prefix) OR have the same URI.
121- // Otherwise we loop through the children as usual and do a string compare on the name
122-
123- NSString *prefix = [[self class] prefixForName:name];
124- if([prefix length] > 0)
125- {
126- xmlNodePtr node = (xmlNodePtr)genericPtr;
127- xmlNsPtr ns = xmlSearchNs(node->doc, node, [prefix xmlChar]);
128- if(ns != NULL)
129- {
130- NSString *uri = [NSString stringWithUTF8String:((const char *)ns->href)];
131- return [self elementsWithName:name uri:uri];
132- }
133-
134- // Note: We used xmlSearchNs instead of resolveNamespaceForName: - avoid creating wrapper objects when possible
135- }
136-
137- return [self elementsWithName:name uri:nil];
138-}
139-
140-- (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI
141-{
142- if(localName == nil) return [NSArray array];
143-
144- // We need to figure out what the prefix is for this URI.
145- // Then we search for elements that are named prefix:localName OR (named localName AND have the given URI).
146-
147- NSString *prefix = [self resolvePrefixForNamespaceURI:URI];
148- if(prefix != nil)
149- {
150- NSString *name = [NSString stringWithFormat:@"%@:%@", prefix, localName];
151-
152- return [self elementsWithName:name uri:URI];
153- }
154- else
155- {
156- return [self elementsWithName:localName uri:URI];
157- }
158-}
159-
160-/**
161- * Helper method elementsForName and elementsForLocalName:URI: so work isn't duplicated.
162- * The name parameter is required, URI is optional.
163-**/
164-- (NSArray *)elementsWithName:(NSString *)name uri:(NSString *)uri
165-{
166- // Supplied: name, !uri : match: name
167- // Supplied: p:name, uri : match: p:name || (name && uri)
168- // Supplied: name, uri : match: name && uri
169-
170- NSMutableArray *result = [NSMutableArray array];
171-
172- xmlNodePtr node = (xmlNodePtr)genericPtr;
173-
174- BOOL hasPrefix = [[[self class] prefixForName:name] length] > 0;
175- NSString *localName = [[self class] localNameForName:name];
176-
177- xmlNodePtr child = node->children;
178- while(child != NULL)
179- {
180- if(child->type == XML_ELEMENT_NODE)
181- {
182- BOOL match = NO;
183- if(uri == nil)
184- {
185- match = xmlStrEqual(child->name, [name xmlChar]);
186- }
187- else
188- {
189- BOOL nameMatch = xmlStrEqual(child->name, [name xmlChar]);
190- BOOL localNameMatch = xmlStrEqual(child->name, [localName xmlChar]);
191-
192- BOOL uriMatch = NO;
193- if(child->ns != NULL)
194- {
195- uriMatch = xmlStrEqual(child->ns->href, [uri xmlChar]);
196- }
197-
198- if(hasPrefix)
199- match = nameMatch || (localNameMatch && uriMatch);
200- else
201- match = nameMatch && uriMatch;
202- }
203-
204- if(match)
205- {
206- [result addObject:[DDXMLElement nodeWithPrimitive:(xmlKindPtr)child]];
207- }
208- }
209-
210- child = child->next;
211- }
212-
213- return result;
214-}
215-
216-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
217-#pragma mark Attributes
218-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
219-
220-- (void)addAttribute:(DDXMLNode *)attribute
221-{
222- // NSXML version uses this same assertion
223- DDCheck([attribute hasParent] == NO, @"Cannot add an attribute with a parent; detach or copy first");
224- DDCheck([attribute isXmlAttrPtr], @"Not an attribute");
225-
226- // xmlNodePtr xmlAddChild(xmlNodePtr parent, xmlNodePtr cur)
227- // Add a new node to @parent, at the end of the child (or property) list merging
228- // adjacent TEXT nodes (in which case @cur is freed). If the new node is ATTRIBUTE, it is added
229- // into properties instead of children. If there is an attribute with equal name, it is first destroyed.
230-
231- [self removeAttributeForName:[attribute name]];
232-
233- xmlAddChild((xmlNodePtr)genericPtr, (xmlNodePtr)attribute->genericPtr);
234-}
235-
236-- (void)removeAttribute:(xmlAttrPtr)attr
237-{
238- [[self class] removeAttribute:attr fromNode:(xmlNodePtr)genericPtr];
239-}
240-
241-- (void)removeAllAttributes
242-{
243- [[self class] removeAllAttributesFromNode:(xmlNodePtr)genericPtr];
244-}
245-
246-- (void)removeAttributeForName:(NSString *)name
247-{
248- // If we use xmlUnsetProp, then the attribute will be automatically freed.
249- // We don't want this unless no other wrapper objects have a reference to the property.
250-
251- xmlAttrPtr attr = ((xmlNodePtr)genericPtr)->properties;
252- while(attr != NULL)
253- {
254- if(xmlStrEqual(attr->name, [name xmlChar]))
255- {
256- [self removeAttribute:attr];
257- return;
258- }
259- attr = attr->next;
260- }
261-}
262-
263-- (NSArray *)attributes
264-{
265- NSMutableArray *result = [NSMutableArray array];
266-
267- xmlAttrPtr attr = ((xmlNodePtr)genericPtr)->properties;
268- while(attr != NULL)
269- {
270- [result addObject:[DDXMLNode nodeWithPrimitive:(xmlKindPtr)attr]];
271-
272- attr = attr->next;
273- }
274-
275- return result;
276-}
277-
278-- (DDXMLNode *)attributeForName:(NSString *)name
279-{
280- xmlAttrPtr attr = ((xmlNodePtr)genericPtr)->properties;
281- while(attr != NULL)
282- {
283- if(xmlStrEqual([name xmlChar], attr->name))
284- {
285- return [DDXMLNode nodeWithPrimitive:(xmlKindPtr)attr];
286- }
287- attr = attr->next;
288- }
289- return nil;
290-}
291-
292-/**
293- * Sets the list of attributes for the element.
294- * Any previously set attributes are removed.
295-**/
296-- (void)setAttributes:(NSArray *)attributes
297-{
298- [self removeAllAttributes];
299-
300- NSUInteger i;
301- for(i = 0; i < [attributes count]; i++)
302- {
303- DDXMLNode *attribute = [attributes objectAtIndex:i];
304- [self addAttribute:attribute];
305- }
306-}
307-
308-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
309-#pragma mark Namespaces
310-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
311-
312-- (void)addNamespace:(DDXMLNode *)namespace
313-{
314- // NSXML version uses this same assertion
315- DDCheck([namespace hasParent] == NO, @"Cannot add a namespace with a parent; detach or copy first");
316- DDCheck([namespace isXmlNsPtr], @"Not a namespace");
317-
318- // Beware: [namespace prefix] does NOT return what you might expect. Use [namespace name] instead.
319-
320- [self removeNamespaceForPrefix:[namespace name]];
321-
322- xmlNsPtr currentNs = ((xmlNodePtr)genericPtr)->nsDef;
323- if(currentNs == NULL)
324- {
325- ((xmlNodePtr)genericPtr)->nsDef = (xmlNsPtr)namespace->genericPtr;
326- }
327- else
328- {
329- while(currentNs != NULL)
330- {
331- if(currentNs->next == NULL)
332- {
333- currentNs->next = (xmlNsPtr)namespace->genericPtr;
334- break; // Yes this break is needed
335- }
336- currentNs = currentNs->next;
337- }
338- }
339-
340- // The xmlNs structure doesn't contain a reference to the parent, so we manage our own reference
341- namespace->nsParentPtr = (xmlNodePtr)genericPtr;
342-
343- // Did we just add a default namespace
344- if([[namespace name] isEqualToString:@""])
345- {
346- ((xmlNodePtr)genericPtr)->ns = (xmlNsPtr)namespace->genericPtr;
347-
348- // Note: The removeNamespaceForPrefix method above properly handled removing any previous default namespace
349- }
350-}
351-
352-- (void)removeNamespace:(xmlNsPtr)ns
353-{
354- [[self class] removeNamespace:ns fromNode:(xmlNodePtr)genericPtr];
355-}
356-
357-- (void)removeAllNamespaces
358-{
359- [[self class] removeAllNamespacesFromNode:(xmlNodePtr)genericPtr];
360-}
361-
362-- (void)removeNamespaceForPrefix:(NSString *)name
363-{
364- // If name is nil or the empty string, the user is wishing to remove the default namespace
365- const xmlChar *xmlName = [name length] > 0 ? [name xmlChar] : NULL;
366-
367- xmlNsPtr ns = ((xmlNodePtr)genericPtr)->nsDef;
368- while(ns != NULL)
369- {
370- if(xmlStrEqual(ns->prefix, xmlName))
371- {
372- [self removeNamespace:ns];
373- break;
374- }
375- ns = ns->next;
376- }
377-
378- // Note: The removeNamespace method properly handles the situation where the namespace is the default namespace
379-}
380-
381-- (NSArray *)namespaces
382-{
383- NSMutableArray *result = [NSMutableArray array];
384-
385- xmlNsPtr ns = ((xmlNodePtr)genericPtr)->nsDef;
386- while(ns != NULL)
387- {
388- [result addObject:[DDXMLNode nodeWithPrimitive:ns nsParent:(xmlNodePtr)genericPtr]];
389-
390- ns = ns->next;
391- }
392-
393- return result;
394-}
395-
396-- (DDXMLNode *)namespaceForPrefix:(NSString *)prefix
397-{
398- // If the prefix is nil or the empty string, the user is requesting the default namespace
399-
400- if([prefix length] == 0)
401- {
402- // Requesting the default namespace
403- xmlNsPtr ns = ((xmlNodePtr)genericPtr)->ns;
404- if(ns != NULL)
405- {
406- return [DDXMLNode nodeWithPrimitive:ns nsParent:(xmlNodePtr)genericPtr];
407- }
408- }
409- else
410- {
411- xmlNsPtr ns = ((xmlNodePtr)genericPtr)->nsDef;
412- while(ns != NULL)
413- {
414- if(xmlStrEqual(ns->prefix, [prefix xmlChar]))
415- {
416- return [DDXMLNode nodeWithPrimitive:ns nsParent:(xmlNodePtr)genericPtr];
417- }
418- ns = ns->next;
419- }
420- }
421-
422- return nil;
423-}
424-
425-- (void)setNamespaces:(NSArray *)namespaces
426-{
427- [self removeAllNamespaces];
428-
429- NSUInteger i;
430- for(i = 0; i < [namespaces count]; i++)
431- {
432- DDXMLNode *namespace = [namespaces objectAtIndex:i];
433- [self addNamespace:namespace];
434- }
435-}
436-
437-/**
438- * Recursively searches the given node for the given namespace
439-**/
440-+ (DDXMLNode *)resolveNamespaceForPrefix:(NSString *)prefix atNode:(xmlNodePtr)nodePtr
441-{
442- if(nodePtr == NULL) return nil;
443-
444- xmlNsPtr ns = nodePtr->nsDef;
445- while(ns != NULL)
446- {
447- if(xmlStrEqual(ns->prefix, [prefix xmlChar]))
448- {
449- return [DDXMLNode nodeWithPrimitive:ns nsParent:nodePtr];
450- }
451- ns = ns->next;
452- }
453-
454- return [self resolveNamespaceForPrefix:prefix atNode:nodePtr->parent];
455-}
456-
457-/**
458- * Returns the namespace node with the prefix matching the given qualified name.
459- * Eg: You pass it "a:dog", it returns the namespace (defined in this node or parent nodes) that has the "a" prefix.
460-**/
461-- (DDXMLNode *)resolveNamespaceForName:(NSString *)name
462-{
463- // If the user passes nil or an empty string for name, they're looking for the default namespace.
464- if([name length] == 0)
465- {
466- return [[self class] resolveNamespaceForPrefix:nil atNode:(xmlNodePtr)genericPtr];
467- }
468-
469- NSString *prefix = [[self class] prefixForName:name];
470-
471- if([prefix length] > 0)
472- {
473- // Unfortunately we can't use xmlSearchNs because it returns an xmlNsPtr.
474- // This gives us mostly what we want, except we also need to know the nsParent.
475- // So we do the recursive search ourselves.
476-
477- return [[self class] resolveNamespaceForPrefix:prefix atNode:(xmlNodePtr)genericPtr];
478- }
479-
480- return nil;
481-}
482-
483-/**
484- * Recursively searches the given node for a namespace with the given URI, and a set prefix.
485-**/
486-+ (NSString *)resolvePrefixForURI:(NSString *)uri atNode:(xmlNodePtr)nodePtr
487-{
488- if(nodePtr == NULL) return nil;
489-
490- xmlNsPtr ns = nodePtr->nsDef;
491- while(ns != NULL)
492- {
493- if(xmlStrEqual(ns->href, [uri xmlChar]))
494- {
495- if(ns->prefix != NULL)
496- {
497- return [NSString stringWithUTF8String:((const char *)ns->prefix)];
498- }
499- }
500- ns = ns->next;
501- }
502-
503- return [self resolvePrefixForURI:uri atNode:nodePtr->parent];
504-}
505-
506-/**
507- * Returns the prefix associated with the specified URI.
508- * Returns a string that is the matching prefix or nil if it finds no matching prefix.
509-**/
510-- (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI
511-{
512- // We can't use xmlSearchNsByHref because it will return xmlNsPtr's with NULL prefixes.
513- // We're looking for a definitive prefix for the given URI.
514-
515- return [[self class] resolvePrefixForURI:namespaceURI atNode:(xmlNodePtr)genericPtr];
516-}
517-
518-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
519-#pragma mark Children
520-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
521-
522-- (void)removeChild:(xmlNodePtr)child
523-{
524- [[self class] removeChild:child fromNode:(xmlNodePtr)genericPtr];
525-}
526-
527-- (void)removeAllChildren
528-{
529- [[self class] removeAllChildrenFromNode:(xmlNodePtr)genericPtr];
530-}
531-
532-- (void)removeChildAtIndex:(NSUInteger)index
533-{
534- NSUInteger i = 0;
535-
536- xmlNodePtr child = ((xmlNodePtr)genericPtr)->children;
537- while(child != NULL)
538- {
539- // Ignore all but element, comment, text, or processing instruction nodes
540- if([[self class] isXmlNodePtr:(xmlKindPtr)child])
541- {
542- if(i == index)
543- {
544- [self removeChild:child];
545- return;
546- }
547-
548- i++;
549- }
550- child = child->next;
551- }
552-}
553-
554-- (void)addChild:(DDXMLNode *)child
555-{
556- // NSXML version uses these same assertions
557- DDCheck([child hasParent] == NO, @"Cannot add a child that has a parent; detach or copy first");
558- DDCheck([child isXmlNodePtr], @"Elements can only have text, elements, processing instructions, and comments as children");
559-
560- xmlAddChild((xmlNodePtr)genericPtr, (xmlNodePtr)child->genericPtr);
561-}
562-
563-- (void)insertChild:(DDXMLNode *)child atIndex:(NSUInteger)index
564-{
565- // NSXML version uses these same assertions
566- DDCheck([child hasParent] == NO, @"Cannot add a child that has a parent; detach or copy first");
567- DDCheck([child isXmlNodePtr], @"Elements can only have text, elements, processing instructions, and comments as children");
568-
569- NSUInteger i = 0;
570-
571- xmlNodePtr childNodePtr = ((xmlNodePtr)genericPtr)->children;
572- while(childNodePtr != NULL)
573- {
574- // Ignore all but element, comment, text, or processing instruction nodes
575- if([[self class] isXmlNodePtr:(xmlKindPtr)childNodePtr])
576- {
577- if(i == index)
578- {
579- xmlAddPrevSibling(childNodePtr, (xmlNodePtr)child->genericPtr);
580- return;
581- }
582-
583- i++;
584- }
585- childNodePtr = childNodePtr->next;
586- }
587-
588- if(i == index)
589- {
590- xmlAddChild((xmlNodePtr)genericPtr, (xmlNodePtr)child->genericPtr);
591- return;
592- }
593-
594- // NSXML version uses this same assertion
595- DDCheck(NO, @"index (%u) beyond bounds (%u)", (unsigned)index, (unsigned)++i);
596-}
597-
598-- (void)setChildren:(NSArray *)children
599-{
600- [self removeAllChildren];
601-
602- NSUInteger i;
603- for(i = 0; i < [children count]; i++)
604- {
605- DDXMLNode *child = [children objectAtIndex:i];
606- [self addChild:child];
607- }
608-}
609-
610-@end
--- trunk/0.2.X/DDXMLElementAdditions.h (revision 271)
+++ trunk/0.2.X/DDXMLElementAdditions.h (nonexistent)
@@ -1,21 +0,0 @@
1-#import <Foundation/Foundation.h>
2-#import "DDXML.h"
3-
4-// These methods are not part of the standard NSXML API.
5-// But any developer working extensively with XML will likely appreciate them.
6-
7-@interface DDXMLElement (DDAdditions)
8-
9-+ (DDXMLElement *)elementWithName:(NSString *)name xmlns:(NSString *)ns;
10-
11-- (DDXMLElement *)elementForName:(NSString *)name;
12-- (DDXMLElement *)elementForName:(NSString *)name xmlns:(NSString *)xmlns;
13-
14-- (NSString *)xmlns;
15-- (void)setXmlns:(NSString *)ns;
16-
17-- (void)addAttributeWithName:(NSString *)name stringValue:(NSString *)string;
18-
19-- (NSDictionary *)attributesAsDictionary;
20-
21-@end
--- trunk/0.2.X/DDXMLElementAdditions.m (revision 271)
+++ trunk/0.2.X/DDXMLElementAdditions.m (nonexistent)
@@ -1,115 +0,0 @@
1-#import "DDXMLElementAdditions.h"
2-
3-@implementation DDXMLElement (DDAdditions)
4-
5-/**
6- * Quick method to create an element
7-**/
8-+ (DDXMLElement *)elementWithName:(NSString *)name xmlns:(NSString *)ns
9-{
10- DDXMLElement *element = [DDXMLElement elementWithName:name];
11- [element setXmlns:ns];
12- return element;
13-}
14-
15-/**
16- * This method returns the first child element for the given name.
17- * If no child element exists for the given name, returns nil.
18-**/
19-- (DDXMLElement *)elementForName:(NSString *)name
20-{
21- NSArray *elements = [self elementsForName:name];
22- if([elements count] > 0)
23- {
24- return [elements objectAtIndex:0];
25- }
26- else
27- {
28- // Note: If you port this code to work with Apple's NSXML, beware of the following:
29- //
30- // There is a bug in the NSXMLElement elementsForName: method.
31- // Consider the following XML fragment:
32- //
33- // <query xmlns="jabber:iq:private">
34- // <x xmlns="some:other:namespace"></x>
35- // </query>
36- //
37- // Calling [query elementsForName:@"x"] results in an empty array!
38- //
39- // However, it will work properly if you use the following:
40- // [query elementsForLocalName:@"x" URI:@"some:other:namespace"]
41- //
42- // The trouble with this is that we may not always know the xmlns in advance,
43- // so in this particular case there is no way to access the element without looping through the children.
44- //
45- // This bug was submitted to apple on June 1st, 2007 and was classified as "serious".
46- //
47- // --!!-- This bug does NOT exist in DDXML --!!--
48-
49- return nil;
50- }
51-}
52-
53-/**
54- * This method returns the first child element for the given name and given xmlns.
55- * If no child elements exist for the given name and given xmlns, returns nil.
56-**/
57-- (DDXMLElement *)elementForName:(NSString *)name xmlns:(NSString *)xmlns
58-{
59- NSArray *elements = [self elementsForLocalName:name URI:xmlns];
60- if([elements count] > 0)
61- {
62- return [elements objectAtIndex:0];
63- }
64- else
65- {
66- return nil;
67- }
68-}
69-
70-/**
71- * Returns the common xmlns "attribute", which is only accessible via the namespace methods.
72- * The xmlns value is often used in jabber elements.
73-**/
74-- (NSString *)xmlns
75-{
76- return [[self namespaceForPrefix:@""] stringValue];
77-}
78-
79-- (void)setXmlns:(NSString *)ns
80-{
81- // If you use setURI: then the xmlns won't be displayed in the XMLString.
82- // Adding the namespace this way works properly.
83- //
84- // This applies to both Apple's NSXML and DDXML.
85-
86- [self addNamespace:[DDXMLNode namespaceWithName:@"" stringValue:ns]];
87-}
88-
89-/**
90- * Shortcut to avoid having to manually create a DDXMLNode everytime.
91-**/
92-- (void)addAttributeWithName:(NSString *)name stringValue:(NSString *)string
93-{
94- [self addAttribute:[DDXMLNode attributeWithName:name stringValue:string]];
95-}
96-
97-/**
98- * Returns all the attributes as a dictionary.
99-**/
100-- (NSDictionary *)attributesAsDictionary
101-{
102- NSArray *attributes = [self attributes];
103- NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:[attributes count]];
104-
105- uint i;
106- for(i = 0; i < [attributes count]; i++)
107- {
108- DDXMLNode *node = [attributes objectAtIndex:i];
109-
110- [result setObject:[node stringValue] forKey:[node name]];
111- }
112- return result;
113-}
114-
115-@end
Afficher sur ancien navigateur de dépôt.