230 lines
9.0 KiB
Objective-C
230 lines
9.0 KiB
Objective-C
#import "DDXML.h"
|
|
|
|
|
|
// We can't rely solely on NSAssert, because many developers disable them for release builds.
|
|
// Our API contract requires us to keep these assertions intact.
|
|
#define DDXMLAssert(condition, desc, ...) \
|
|
do{ \
|
|
if(!(condition)) { \
|
|
[[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \
|
|
object:self \
|
|
file:[NSString stringWithUTF8String:__FILE__] \
|
|
lineNumber:__LINE__ \
|
|
description:(desc), ##__VA_ARGS__]; \
|
|
} \
|
|
}while(NO)
|
|
|
|
|
|
// Create assertion to ensure xml node is not a zombie.
|
|
#if DDXML_DEBUG_MEMORY_ISSUES
|
|
#define DDXMLNotZombieAssert() \
|
|
do{ \
|
|
if(DDXMLIsZombie(genericPtr, self)) { \
|
|
NSString *desc = @"XML node is a zombie - It's parent structure has been freed!"; \
|
|
[[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \
|
|
object:self \
|
|
file:[NSString stringWithUTF8String:__FILE__] \
|
|
lineNumber:__LINE__ \
|
|
description:desc]; \
|
|
} \
|
|
}while(NO)
|
|
#endif
|
|
|
|
#define DDLastErrorKey @"DDXML:LastError"
|
|
|
|
|
|
|
|
/**
|
|
* DDXMLNode can represent several underlying types, such as xmlNodePtr, xmlDocPtr, xmlAttrPtr, xmlNsPtr, etc.
|
|
* All of these are pointers to structures, and all of those structures start with a pointer, and a type.
|
|
* The xmlKind struct is used as a generic structure, and a stepping stone.
|
|
* We use it to check the type of a structure, and then perform the appropriate cast.
|
|
*
|
|
* For example:
|
|
* if(genericPtr->type == XML_ATTRIBUTE_NODE)
|
|
* {
|
|
* xmlAttrPtr attr = (xmlAttrPtr)genericPtr;
|
|
* // Do something with attr
|
|
* }
|
|
**/
|
|
struct _xmlKind {
|
|
void * ignore;
|
|
xmlElementType type;
|
|
};
|
|
typedef struct _xmlKind *xmlKindPtr;
|
|
|
|
/**
|
|
* Most xml types all start with this standard structure. In fact, all do except the xmlNsPtr.
|
|
* We will occasionally take advantage of this to simplify code when the code wouldn't vary from type to type.
|
|
* Obviously, you cannnot cast a xmlNsPtr to a xmlStdPtr.
|
|
**/
|
|
struct _xmlStd {
|
|
void * _private;
|
|
xmlElementType type;
|
|
const xmlChar *name;
|
|
struct _xmlNode *children;
|
|
struct _xmlNode *last;
|
|
struct _xmlNode *parent;
|
|
struct _xmlStd *next;
|
|
struct _xmlStd *prev;
|
|
struct _xmlDoc *doc;
|
|
};
|
|
typedef struct _xmlStd *xmlStdPtr;
|
|
|
|
|
|
NS_INLINE BOOL IsXmlAttrPtr(void *kindPtr)
|
|
{
|
|
return ((xmlKindPtr)kindPtr)->type == XML_ATTRIBUTE_NODE;
|
|
}
|
|
|
|
NS_INLINE BOOL IsXmlNodePtr(void *kindPtr)
|
|
{
|
|
switch (((xmlKindPtr)kindPtr)->type)
|
|
{
|
|
case XML_ELEMENT_NODE :
|
|
case XML_PI_NODE :
|
|
case XML_COMMENT_NODE :
|
|
case XML_TEXT_NODE :
|
|
case XML_CDATA_SECTION_NODE : return YES;
|
|
default : return NO;
|
|
}
|
|
}
|
|
|
|
NS_INLINE BOOL IsXmlDocPtr(void *kindPtr)
|
|
{
|
|
return ((xmlKindPtr)kindPtr)->type == XML_DOCUMENT_NODE;
|
|
}
|
|
|
|
NS_INLINE BOOL IsXmlDtdPtr(void *kindPtr)
|
|
{
|
|
return ((xmlKindPtr)kindPtr)->type == XML_DTD_NODE;
|
|
}
|
|
|
|
NS_INLINE BOOL IsXmlNsPtr(void *kindPtr)
|
|
{
|
|
return ((xmlKindPtr)kindPtr)->type == XML_NAMESPACE_DECL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
@interface DDXMLNamespaceNode : DDXMLNode
|
|
{
|
|
// The xmlNsPtr type doesn't store a reference to it's parent.
|
|
// This is here to fix the problem, and make this class more compatible with the NSXML classes.
|
|
xmlNodePtr nsParentPtr;
|
|
}
|
|
|
|
+ (id)nodeWithNsPrimitive:(xmlNsPtr)ns nsParent:(xmlNodePtr)parent owner:(DDXMLNode *)owner;
|
|
- (id)initWithNsPrimitive:(xmlNsPtr)ns nsParent:(xmlNodePtr)parent owner:(DDXMLNode *)owner;
|
|
|
|
- (xmlNodePtr)_nsParentPtr;
|
|
- (void)_setNsParentPtr:(xmlNodePtr)parentPtr;
|
|
|
|
// Overrides several methods in DDXMLNode
|
|
|
|
@end
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
@interface DDXMLAttributeNode : DDXMLNode
|
|
{
|
|
// The xmlAttrPtr type doesn't allow for ownership of a namespace.
|
|
//
|
|
// In other types, such as xmlNodePtr:
|
|
// - nsDef stores namespaces that are owned by the node (have been alloced by the node).
|
|
// - ns is simply a pointer to the default namespace of the node, which may or may not reside in its own nsDef list.
|
|
//
|
|
// The xmlAttrPtr only has a ns, it doesn't have a nsDef list.
|
|
// Which completely makes sense really, since namespaces have to be defined elsewhere.
|
|
//
|
|
// This is here to maintain compatibility with the NSXML classes,
|
|
// where one can assign a namespace to an attribute independently.
|
|
xmlNsPtr attrNsPtr;
|
|
}
|
|
|
|
+ (id)nodeWithAttrPrimitive:(xmlAttrPtr)attr owner:(DDXMLNode *)owner;
|
|
- (id)initWithAttrPrimitive:(xmlAttrPtr)attr owner:(DDXMLNode *)owner;
|
|
|
|
// Overrides several methods in DDXMLNode
|
|
|
|
@end
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
@interface DDXMLInvalidNode : DDXMLNode
|
|
{
|
|
}
|
|
|
|
// Overrides several methods in DDXMLNode
|
|
|
|
@end
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
@interface DDXMLNode (PrivateAPI)
|
|
|
|
+ (id)nodeWithUnknownPrimitive:(xmlKindPtr)kindPtr owner:(DDXMLNode *)owner;
|
|
|
|
+ (id)nodeWithPrimitive:(xmlKindPtr)kindPtr owner:(DDXMLNode *)owner;
|
|
- (id)initWithPrimitive:(xmlKindPtr)kindPtr owner:(DDXMLNode *)owner;
|
|
|
|
- (BOOL)_hasParent;
|
|
|
|
+ (void)getHasPrefix:(BOOL *)hasPrefixPtr localName:(NSString **)localNamePtr forName:(NSString *)name;
|
|
+ (void)getPrefix:(NSString **)prefixPtr localName:(NSString **)localNamePtr forName:(NSString *)name;
|
|
|
|
+ (void)recursiveStripDocPointersFromNode:(xmlNodePtr)node;
|
|
|
|
+ (void)detachNamespace:(xmlNsPtr)ns fromNode:(xmlNodePtr)node;
|
|
+ (void)removeNamespace:(xmlNsPtr)ns fromNode:(xmlNodePtr)node;
|
|
+ (void)removeAllNamespacesFromNode:(xmlNodePtr)node;
|
|
|
|
+ (void)detachAttribute:(xmlAttrPtr)attr andClean:(BOOL)clean;
|
|
+ (void)detachAttribute:(xmlAttrPtr)attr;
|
|
+ (void)removeAttribute:(xmlAttrPtr)attr;
|
|
+ (void)removeAllAttributesFromNode:(xmlNodePtr)node;
|
|
|
|
+ (void)detachChild:(xmlNodePtr)child andClean:(BOOL)clean andFixNamespaces:(BOOL)fixNamespaces;
|
|
+ (void)detachChild:(xmlNodePtr)child;
|
|
+ (void)removeChild:(xmlNodePtr)child;
|
|
+ (void)removeAllChildrenFromNode:(xmlNodePtr)node;
|
|
|
|
BOOL DDXMLIsZombie(void *xmlPtr, DDXMLNode *wrapper);
|
|
|
|
+ (NSError *)lastError;
|
|
|
|
@end
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
@interface DDXMLElement (PrivateAPI)
|
|
|
|
+ (id)nodeWithElementPrimitive:(xmlNodePtr)node owner:(DDXMLNode *)owner;
|
|
- (id)initWithElementPrimitive:(xmlNodePtr)node owner:(DDXMLNode *)owner;
|
|
|
|
- (DDXMLNode *)_recursiveResolveNamespaceForPrefix:(NSString *)prefix atNode:(xmlNodePtr)nodePtr;
|
|
- (NSString *)_recursiveResolvePrefixForURI:(NSString *)uri atNode:(xmlNodePtr)nodePtr;
|
|
|
|
@end
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
@interface DDXMLDocument (PrivateAPI)
|
|
|
|
+ (id)nodeWithDocPrimitive:(xmlDocPtr)doc owner:(DDXMLNode *)owner;
|
|
- (id)initWithDocPrimitive:(xmlDocPtr)doc owner:(DDXMLNode *)owner;
|
|
|
|
@end
|