This commit is contained in:
giuseppenuc committed 2016-02-24 16:56:39 +01:00
1 parent d281d765ea
commit 5b074a5176
1261 files changed
+199158 -7303

No files matched your search

+18
View File
@@ -0,0 +1,18 @@
#import <Foundation/Foundation.h>
#if !(TARGET_IPHONE_SIMULATOR)
@import libxml;
#else
@import libxmlSimu;
#endif
@interface NSString (DDXML)
/**
* xmlChar - A basic replacement for char, a byte in a UTF-8 encoded string.
**/
- (const xmlChar *)xmlChar;
- (NSString *)stringByTrimming;
@end
+31
View File
@@ -0,0 +1,31 @@
#import "NSString+DDXML.h"
#if ! __has_feature(objc_arc)
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
#endif
@implementation NSString (DDXML)
- (const xmlChar *)xmlChar
{
return (const xmlChar *)[self UTF8String];
}
#ifdef GNUSTEP
- (NSString *)stringByTrimming
{
return [self stringByTrimmingSpaces];
}
#else
- (NSString *)stringByTrimming
{
NSMutableString *mStr = [self mutableCopy];
CFStringTrimWhitespace((__bridge CFMutableStringRef)mStr);
NSString *result = [mStr copy];
return result;
}
#endif
@end
+196
View File
@@ -0,0 +1,196 @@
/**
* Welcome to KissXML.
*
* The project page has documentation if you have questions.
* https://github.com/robbiehanson/KissXML
*
* If you're new to the project you may wish to read the "Getting Started" wiki.
* https://github.com/robbiehanson/KissXML/wiki/GettingStarted
*
* KissXML provides a drop-in replacement for Apple's NSXML class cluster.
* The goal is to get the exact same behavior as the NSXML classes.
*
* For API Reference, see Apple's excellent documentation,
* either via Xcode's Mac OS X documentation, or via the web:
*
* https://github.com/robbiehanson/KissXML/wiki/Reference
**/
#import "DDXMLNode.h"
#import "DDXMLElement.h"
#import "DDXMLDocument.h"
#if TARGET_OS_IPHONE
// Since KissXML is a drop in replacement for NSXML,
// it may be desireable (when writing cross-platform code to be used on both Mac OS X and iOS)
// to use the NSXML prefixes instead of the DDXML prefix.
//
// This way, on Mac OS X it uses NSXML, and on iOS it uses KissXML.
#ifndef NSXMLNode
#define NSXMLNode DDXMLNode
#endif
#ifndef NSXMLElement
#define NSXMLElement DDXMLElement
#endif
#ifndef NSXMLDocument
#define NSXMLDocument DDXMLDocument
#endif
#ifndef NSXMLInvalidKind
#define NSXMLInvalidKind DDXMLInvalidKind
#endif
#ifndef NSXMLDocumentKind
#define NSXMLDocumentKind DDXMLDocumentKind
#endif
#ifndef NSXMLElementKind
#define NSXMLElementKind DDXMLElementKind
#endif
#ifndef NSXMLAttributeKind
#define NSXMLAttributeKind DDXMLAttributeKind
#endif
#ifndef NSXMLNamespaceKind
#define NSXMLNamespaceKind DDXMLNamespaceKind
#endif
#ifndef NSXMLProcessingInstructionKind
#define NSXMLProcessingInstructionKind DDXMLProcessingInstructionKind
#endif
#ifndef NSXMLCommentKind
#define NSXMLCommentKind DDXMLCommentKind
#endif
#ifndef NSXMLTextKind
#define NSXMLTextKind DDXMLTextKind
#endif
#ifndef NSXMLDTDKind
#define NSXMLDTDKind DDXMLDTDKind
#endif
#ifndef NSXMLEntityDeclarationKind
#define NSXMLEntityDeclarationKind DDXMLEntityDeclarationKind
#endif
#ifndef NSXMLAttributeDeclarationKind
#define NSXMLAttributeDeclarationKind DDXMLAttributeDeclarationKind
#endif
#ifndef NSXMLElementDeclarationKind
#define NSXMLElementDeclarationKind DDXMLElementDeclarationKind
#endif
#ifndef NSXMLNotationDeclarationKind
#define NSXMLNotationDeclarationKind DDXMLNotationDeclarationKind
#endif
#ifndef NSXMLNodeOptionsNone
#define NSXMLNodeOptionsNone DDXMLNodeOptionsNone
#endif
#ifndef NSXMLNodeExpandEmptyElement
#define NSXMLNodeExpandEmptyElement DDXMLNodeExpandEmptyElement
#endif
#ifndef NSXMLNodeCompactEmptyElement
#define NSXMLNodeCompactEmptyElement DDXMLNodeCompactEmptyElement
#endif
#ifndef NSXMLNodePrettyPrint
#define NSXMLNodePrettyPrint DDXMLNodePrettyPrint
#endif
#endif // #if TARGET_OS_IPHONE
// KissXML has rather straight-forward memory management:
// https://github.com/robbiehanson/KissXML/wiki/MemoryManagementThreadSafety
//
// There are 3 important concepts to keep in mind when working with KissXML:
//
//
// 1.) KissXML provides a light-weight wrapper around libxml.
//
// The parsing, creation, storage, etc of the xml tree is all done via libxml.
// This is a fast low-level C library that's been around for ages, and comes pre-installed on Mac OS X and iOS.
// KissXML provides an easy-to-use Objective-C library atop libxml.
// So a DDXMLNode, DDXMLElement, or DDXMLDocument are simply objective-c objects
// with pointers to the underlying libxml C structure.
// Then only time you need to be aware of any of this is when it comes to equality.
// In order to maximize speed and provide read-access thread-safety,
// the library may create multiple DDXML wrapper objects that point to the same underlying xml node.
// So don't assume you can test for equality with "==".
// Instead use the isEqual method (as you should generally do with objects anyway).
//
//
// 2.) XML is implicitly a tree heirarchy, and the XML API's are designed to allow traversal up & down the tree.
//
// The tree heirarchy and API contract have an implicit impact concerning memory management.
//
// <starbucks>
// <latte/>
// </starbucks>
//
// Imagine you have a DDXMLNode corresponding to the starbucks node,
// and you have a DDXMLNode corresponding to the latte node.
// Now imagine you release the starbucks node, but you retain a reference to the latte node.
// What happens?
// Well the latte node is a part of the xml tree heirarchy.
// So if the latte node is still around, the xml tree heirarchy must stick around as well.
// So even though the DDXMLNode corresponding to the starbucks node may get deallocated,
// the underlying xml tree structure won't be freed until the latte node gets dealloacated.
//
// In general, this means that KissXML remains thread-safe when reading and processing a tree.
// If you traverse a tree and fork off asynchronous tasks to process subnodes,
// the tree will remain properly in place until all your asynchronous tasks have completed.
// In other words, it just works.
//
// However, if you parse a huge document into memory, and retain a single node from the giant xml tree...
// Well you should see the problem this creates.
// Instead, in this situation, copy or detach the node if you want to keep it around.
// Or just extract the info you need from it.
//
//
// 3.) KissXML is read-access thread-safe, but write-access thread-unsafe (designed for speed).
//
// <starbucks>
// <latte/>
// </starbucks>
//
// Imagine you have a DDXMLNode corresponding to the starbucks node,
// and you have a DDXMLNode corresponding to the latte node.
// What happens if you invoke [starbucks removeChildAtIndex:0]?
// Well the undelying xml tree will remove the latte node, and release the associated memory.
// And what if you still have a reference to the DDXMLNode that corresponds to the latte node?
// Well the short answer is that you shouldn't use it. At all.
// This is pretty obvious when you think about it from the context of this simple example.
// But in the real world, you might have multiple threads running in parallel,
// and you might accidently modify a node while another thread is processing it.
//
// To completely fix this problem, and provide write-access thread-safety, would require extensive overhead.
// This overhead is completely unwanted in the majority of cases.
// Most XML usage patterns are heavily read-only.
// And in the case of xml creation or modification, it is generally done on the same thread.
// Thus the KissXML library is write-access thread-unsafe, but provides speedier performance.
//
// However, when such a bug does creep up, it produces horrible side-effects.
// Essentially the pointer to the underlying xml structure becomes a dangling pointer,
// which means that accessing the dangling pointer might give you the correct results, or completely random results.
// And attempting to make modifications to non-existant xml nodes via the dangling pointer might do nothing,
// or completely corrupt your heap and cause un-explainable crashes in random parts of your library.
// Heap corruption is one of the worst problems to track down.
// So to help out, the library provides a debugging macro to track down these problems.
// That is, if you invalidate the write-access thread-unsafe rule,
// this macro will tell you when you're trying to access a now-dangling pointer.
//
// How does it work?
// Well everytime a DDXML wrapper object is created atop a libxml structure,
// it marks the linkage in a table.
// And everytime a libxml structure is freed, it destorys all corresponding linkages in the table.
// So everytime a DDXML wrapper objects is about to dereference it's pointer,
// it first ensures the linkage still exists in the table.
//
// Set to 1 to enable
// Set to 0 to disable (this is the default)
//
// The debugging macro adds a significant amount of overhead, and should NOT be enabled on production builds.
#if DEBUG
#define DDXML_DEBUG_MEMORY_ISSUES 0
#else
#define DDXML_DEBUG_MEMORY_ISSUES 0 // Don't change me!
#endif
+84
View File
@@ -0,0 +1,84 @@
#import <Foundation/Foundation.h>
#import "DDXMLElement.h"
#import "DDXMLNode.h"
/**
* Welcome to KissXML.
*
* The project page has documentation if you have questions.
* https://github.com/robbiehanson/KissXML
*
* If you're new to the project you may wish to read the "Getting Started" wiki.
* https://github.com/robbiehanson/KissXML/wiki/GettingStarted
*
* KissXML provides a drop-in replacement for Apple's NSXML class cluster.
* The goal is to get the exact same behavior as the NSXML classes.
*
* For API Reference, see Apple's excellent documentation,
* either via Xcode's Mac OS X documentation, or via the web:
*
* https://github.com/robbiehanson/KissXML/wiki/Reference
**/
enum {
DDXMLDocumentXMLKind = 0,
DDXMLDocumentXHTMLKind,
DDXMLDocumentHTMLKind,
DDXMLDocumentTextKind
};
typedef NSUInteger DDXMLDocumentContentKind;
@interface DDXMLDocument : DDXMLNode
{
}
- (id)initWithXMLString:(NSString *)string options:(NSUInteger)mask error:(NSError **)error;
//- (id)initWithContentsOfURL:(NSURL *)url options:(NSUInteger)mask error:(NSError **)error;
- (id)initWithData:(NSData *)data options:(NSUInteger)mask error:(NSError **)error;
//- (id)initWithRootElement:(DDXMLElement *)element;
//+ (Class)replacementClassForClass:(Class)cls;
//- (void)setCharacterEncoding:(NSString *)encoding; //primitive
//- (NSString *)characterEncoding; //primitive
//- (void)setVersion:(NSString *)version;
//- (NSString *)version;
//- (void)setStandalone:(BOOL)standalone;
//- (BOOL)isStandalone;
//- (void)setDocumentContentKind:(DDXMLDocumentContentKind)kind;
//- (DDXMLDocumentContentKind)documentContentKind;
//- (void)setMIMEType:(NSString *)MIMEType;
//- (NSString *)MIMEType;
//- (void)setDTD:(DDXMLDTD *)documentTypeDeclaration;
//- (DDXMLDTD *)DTD;
//- (void)setRootElement:(DDXMLNode *)root;
- (DDXMLElement *)rootElement;
//- (void)insertChild:(DDXMLNode *)child atIndex:(NSUInteger)index;
//- (void)insertChildren:(NSArray *)children atIndex:(NSUInteger)index;
//- (void)removeChildAtIndex:(NSUInteger)index;
//- (void)setChildren:(NSArray *)children;
//- (void)addChild:(DDXMLNode *)child;
//- (void)replaceChildAtIndex:(NSUInteger)index withNode:(DDXMLNode *)node;
- (NSData *)XMLData;
- (NSData *)XMLDataWithOptions:(NSUInteger)options;
//- (id)objectByApplyingXSLT:(NSData *)xslt arguments:(NSDictionary *)arguments error:(NSError **)error;
//- (id)objectByApplyingXSLTString:(NSString *)xslt arguments:(NSDictionary *)arguments error:(NSError **)error;
//- (id)objectByApplyingXSLTAtURL:(NSURL *)xsltURL arguments:(NSDictionary *)argument error:(NSError **)error;
//- (BOOL)validateAndReturnError:(NSError **)error;
@end
+140
View File
@@ -0,0 +1,140 @@
#import "DDXMLPrivate.h"
#import "NSString+DDXML.h"
#if ! __has_feature(objc_arc)
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
#endif
/**
* Welcome to KissXML.
*
* The project page has documentation if you have questions.
* https://github.com/robbiehanson/KissXML
*
* If you're new to the project you may wish to read the "Getting Started" wiki.
* https://github.com/robbiehanson/KissXML/wiki/GettingStarted
*
* KissXML provides a drop-in replacement for Apple's NSXML class cluster.
* The goal is to get the exact same behavior as the NSXML classes.
*
* For API Reference, see Apple's excellent documentation,
* either via Xcode's Mac OS X documentation, or via the web:
*
* https://github.com/robbiehanson/KissXML/wiki/Reference
**/
@implementation DDXMLDocument
/**
* Returns a DDXML wrapper object for the given primitive node.
* The given node MUST be non-NULL and of the proper type.
**/
+ (id)nodeWithDocPrimitive:(xmlDocPtr)doc owner:(DDXMLNode *)owner
{
return [[DDXMLDocument alloc] initWithDocPrimitive:doc owner:owner];
}
- (id)initWithDocPrimitive:(xmlDocPtr)doc owner:(DDXMLNode *)inOwner
{
self = [super initWithPrimitive:(xmlKindPtr)doc owner:inOwner];
return self;
}
+ (id)nodeWithPrimitive:(xmlKindPtr)kindPtr owner:(DDXMLNode *)owner
{
// Promote initializers which use proper parameter types to enable compiler to catch more mistakes
NSAssert(NO, @"Use nodeWithDocPrimitive:owner:");
return nil;
}
- (id)initWithPrimitive:(xmlKindPtr)kindPtr owner:(DDXMLNode *)inOwner
{
// Promote initializers which use proper parameter types to enable compiler to catch more mistakes.
NSAssert(NO, @"Use initWithDocPrimitive:owner:");
return nil;
}
/**
* Initializes and returns a DDXMLDocument object created from an NSData object.
*
* Returns an initialized DDXMLDocument object, or nil if initialization fails
* because of parsing errors or other reasons.
**/
- (id)initWithXMLString:(NSString *)string options:(NSUInteger)mask error:(NSError **)error
{
return [self initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]
options:mask
error:error];
}
/**
* Initializes and returns a DDXMLDocument object created from an NSData object.
*
* Returns an initialized DDXMLDocument object, or nil if initialization fails
* because of parsing errors or other reasons.
**/
- (id)initWithData:(NSData *)data options:(NSUInteger)mask error:(NSError **)error
{
if (data == nil || [data length] == 0)
{
if (error) *error = [NSError errorWithDomain:@"DDXMLErrorDomain" code:0 userInfo:nil];
return nil;
}
// Even though xmlKeepBlanksDefault(0) is called in DDXMLNode's initialize method,
// it has been documented that this call seems to get reset on the iPhone:
// http://code.google.com/p/kissxml/issues/detail?id=8
//
// Therefore, we call it again here just to be safe.
xmlKeepBlanksDefault(0);
xmlDocPtr doc = xmlParseMemory([data bytes], (int)[data length]);
if (doc == NULL)
{
if (error) *error = [NSError errorWithDomain:@"DDXMLErrorDomain" code:1 userInfo:nil];
return nil;
}
return [self initWithDocPrimitive:doc owner:nil];
}
/**
* Returns the root element of the receiver.
**/
- (DDXMLElement *)rootElement
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
xmlDocPtr doc = (xmlDocPtr)genericPtr;
// doc->children is a list containing possibly comments, DTDs, etc...
xmlNodePtr rootNode = xmlDocGetRootElement(doc);
if (rootNode != NULL)
return [DDXMLElement nodeWithElementPrimitive:rootNode owner:self];
else
return nil;
}
- (NSData *)XMLData
{
// Zombie test occurs in XMLString
return [[self XMLString] dataUsingEncoding:NSUTF8StringEncoding];
}
- (NSData *)XMLDataWithOptions:(NSUInteger)options
{
// Zombie test occurs in XMLString
return [[self XMLStringWithOptions:options] dataUsingEncoding:NSUTF8StringEncoding];
}
@end
+66
View File
@@ -0,0 +1,66 @@
#import <Foundation/Foundation.h>
#import "DDXMLNode.h"
/**
* Welcome to KissXML.
*
* The project page has documentation if you have questions.
* https://github.com/robbiehanson/KissXML
*
* If you're new to the project you may wish to read the "Getting Started" wiki.
* https://github.com/robbiehanson/KissXML/wiki/GettingStarted
*
* KissXML provides a drop-in replacement for Apple's NSXML class cluster.
* The goal is to get the exact same behavior as the NSXML classes.
*
* For API Reference, see Apple's excellent documentation,
* either via Xcode's Mac OS X documentation, or via the web:
*
* https://github.com/robbiehanson/KissXML/wiki/Reference
**/
@interface DDXMLElement : DDXMLNode
{
}
- (id)initWithName:(NSString *)name;
- (id)initWithName:(NSString *)name URI:(NSString *)URI;
- (id)initWithName:(NSString *)name stringValue:(NSString *)string;
- (id)initWithXMLString:(NSString *)string error:(NSError **)error;
#pragma mark --- Elements by name ---
- (NSArray *)elementsForName:(NSString *)name;
- (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI;
#pragma mark --- Attributes ---
- (void)addAttribute:(DDXMLNode *)attribute;
- (void)removeAttributeForName:(NSString *)name;
- (void)setAttributes:(NSArray *)attributes;
//- (void)setAttributesAsDictionary:(NSDictionary *)attributes;
- (NSArray *)attributes;
- (DDXMLNode *)attributeForName:(NSString *)name;
//- (DDXMLNode *)attributeForLocalName:(NSString *)localName URI:(NSString *)URI;
#pragma mark --- Namespaces ---
- (void)addNamespace:(DDXMLNode *)aNamespace;
- (void)removeNamespaceForPrefix:(NSString *)name;
- (void)setNamespaces:(NSArray *)namespaces;
- (NSArray *)namespaces;
- (DDXMLNode *)namespaceForPrefix:(NSString *)prefix;
- (DDXMLNode *)resolveNamespaceForName:(NSString *)name;
- (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI;
#pragma mark --- Children ---
- (void)insertChild:(DDXMLNode *)child atIndex:(NSUInteger)index;
//- (void)insertChildren:(NSArray *)children atIndex:(NSUInteger)index;
- (void)removeChildAtIndex:(NSUInteger)index;
- (void)setChildren:(NSArray *)children;
- (void)addChild:(DDXMLNode *)child;
//- (void)replaceChildAtIndex:(NSUInteger)index withNode:(DDXMLNode *)node;
//- (void)normalizeAdjacentTextNodesPreservingCDATA:(BOOL)preserve;
@end
+801
View File
@@ -0,0 +1,801 @@
#import "DDXMLPrivate.h"
#import "NSString+DDXML.h"
#if ! __has_feature(objc_arc)
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
#endif
/**
* Welcome to KissXML.
*
* The project page has documentation if you have questions.
* https://github.com/robbiehanson/KissXML
*
* If you're new to the project you may wish to read the "Getting Started" wiki.
* https://github.com/robbiehanson/KissXML/wiki/GettingStarted
*
* KissXML provides a drop-in replacement for Apple's NSXML class cluster.
* The goal is to get the exact same behavior as the NSXML classes.
*
* For API Reference, see Apple's excellent documentation,
* either via Xcode's Mac OS X documentation, or via the web:
*
* https://github.com/robbiehanson/KissXML/wiki/Reference
**/
@implementation DDXMLElement
/**
* Returns a DDXML wrapper object for the given primitive node.
* The given node MUST be non-NULL and of the proper type.
**/
+ (id)nodeWithElementPrimitive:(xmlNodePtr)node owner:(DDXMLNode *)owner
{
return [[DDXMLElement alloc] initWithElementPrimitive:node owner:owner];
}
- (id)initWithElementPrimitive:(xmlNodePtr)node owner:(DDXMLNode *)inOwner
{
self = [super initWithPrimitive:(xmlKindPtr)node owner:inOwner];
return self;
}
+ (id)nodeWithPrimitive:(xmlKindPtr)kindPtr owner:(DDXMLNode *)owner
{
// Promote initializers which use proper parameter types to enable compiler to catch more mistakes
NSAssert(NO, @"Use nodeWithElementPrimitive:owner:");
return nil;
}
- (id)initWithPrimitive:(xmlKindPtr)kindPtr owner:(DDXMLNode *)inOwner
{
// Promote initializers which use proper parameter types to enable compiler to catch more mistakes.
NSAssert(NO, @"Use initWithElementPrimitive:owner:");
return nil;
}
- (id)initWithName:(NSString *)name
{
// Note: Make every guarantee that genericPtr is not null
xmlNodePtr node = xmlNewNode(NULL, [name xmlChar]);
if (node == NULL)
{
return nil;
}
return [self initWithElementPrimitive:node owner:nil];
}
- (id)initWithName:(NSString *)name URI:(NSString *)URI
{
// Note: Make every guarantee that genericPtr is not null
xmlNodePtr node = xmlNewNode(NULL, [name xmlChar]);
if (node == NULL)
{
return nil;
}
DDXMLElement *result = [self initWithElementPrimitive:node owner:nil];
[result setURI:URI];
return result;
}
- (id)initWithName:(NSString *)name stringValue:(NSString *)string
{
// Note: Make every guarantee that genericPtr is not null
xmlNodePtr node = xmlNewNode(NULL, [name xmlChar]);
if (node == NULL)
{
return nil;
}
DDXMLElement *result = [self initWithElementPrimitive:node owner:nil];
[result setStringValue:string];
return result;
}
- (id)initWithXMLString:(NSString *)string error:(NSError **)error
{
DDXMLDocument *doc = [[DDXMLDocument alloc] initWithXMLString:string options:0 error:error];
if (doc == nil)
{
return nil;
}
DDXMLElement *result = [doc rootElement];
[result detach];
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Elements by name
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Helper method elementsForName and elementsForLocalName:URI: so work isn't duplicated.
* The name parameter is required, all others are optional.
**/
- (NSArray *)_elementsForName:(NSString *)name
localName:(NSString *)localName
prefix:(NSString *)prefix
uri:(NSString *)uri
{
// This is a private/internal method
// Rule : !uri => match: name
// Rule : uri && hasPrefix => match: name || (localName && uri)
// Rule : uri && !hasPefix => match: name && uri
xmlNodePtr node = (xmlNodePtr)genericPtr;
NSMutableArray *result = [NSMutableArray array];
BOOL hasPrefix = [prefix length] > 0;
const xmlChar *xmlName = [name xmlChar];
const xmlChar *xmlLocalName = [localName xmlChar];
const xmlChar *xmlUri = [uri xmlChar];
xmlNodePtr child = node->children;
while (child)
{
if (IsXmlNodePtr(child))
{
BOOL match = NO;
if (uri == nil)
{
match = xmlStrEqual(child->name, xmlName);
}
else
{
BOOL nameMatch = xmlStrEqual(child->name, xmlName);
BOOL localNameMatch = xmlStrEqual(child->name, xmlLocalName);
BOOL uriMatch = NO;
if (child->ns)
{
uriMatch = xmlStrEqual(child->ns->href, xmlUri);
}
if (hasPrefix)
match = nameMatch || (localNameMatch && uriMatch);
else
match = nameMatch && uriMatch;
}
if (match)
{
[result addObject:[DDXMLElement nodeWithElementPrimitive:child owner:self]];
}
}
child = child->next;
}
return result;
}
/**
* Returns the child element nodes (as DDXMLElement objects) of the receiver that have a specified name.
*
* If name is a qualified name, then this method invokes elementsForLocalName:URI: with the URI parameter set to
* the URI associated with the prefix. Otherwise comparison is based on string equality of the qualified or
* non-qualified name.
**/
- (NSArray *)elementsForName:(NSString *)name
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
if (name == nil) return [NSArray array];
// We need to check to see if name has a prefix.
// If it does have a prefix, we need to figure out what the corresponding URI is for that prefix,
// and then search for any elements that have the same name (including prefix) OR have the same URI.
// Otherwise we loop through the children as usual and do a string compare on the name
NSString *prefix;
NSString *localName;
[DDXMLNode getPrefix:&prefix localName:&localName forName:name];
if ([prefix length] > 0)
{
xmlNodePtr node = (xmlNodePtr)genericPtr;
// Note: We use xmlSearchNs instead of resolveNamespaceForName: because
// we want to avoid creating wrapper objects when possible.
xmlNsPtr ns = xmlSearchNs(node->doc, node, [prefix xmlChar]);
if (ns)
{
NSString *uri = [NSString stringWithUTF8String:((const char *)ns->href)];
return [self _elementsForName:name localName:localName prefix:prefix uri:uri];
}
}
return [self _elementsForName:name localName:localName prefix:prefix uri:nil];
}
- (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)uri
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
if (localName == nil) return [NSArray array];
// We need to figure out what the prefix is for this URI.
// Then we search for elements that are named prefix:localName OR (named localName AND have the given URI).
NSString *prefix = [self _recursiveResolvePrefixForURI:uri atNode:(xmlNodePtr)genericPtr];
if (prefix)
{
NSString *name = [NSString stringWithFormat:@"%@:%@", prefix, localName];
return [self _elementsForName:name localName:localName prefix:prefix uri:uri];
}
else
{
NSString *prefix;
NSString *realLocalName;
[DDXMLNode getPrefix:&prefix localName:&realLocalName forName:localName];
return [self _elementsForName:localName localName:realLocalName prefix:prefix uri:uri];
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Attributes
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (BOOL)_hasAttributeWithName:(NSString *)name
{
// This is a private/internal method
xmlAttrPtr attr = ((xmlNodePtr)genericPtr)->properties;
if (attr)
{
const xmlChar *xmlName = [name xmlChar];
do
{
if (xmlStrEqual(attr->name, xmlName))
{
return YES;
}
attr = attr->next;
} while (attr);
}
return NO;
}
- (void)_removeAttributeForName:(NSString *)name
{
// This is a private/internal method
xmlAttrPtr attr = ((xmlNodePtr)genericPtr)->properties;
if (attr)
{
const xmlChar *xmlName = [name xmlChar];
do
{
if (xmlStrEqual(attr->name, xmlName))
{
[DDXMLNode removeAttribute:attr];
return;
}
attr = attr->next;
} while(attr);
}
}
- (void)addAttribute:(DDXMLNode *)attribute
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
// NSXML version uses this same assertion
DDXMLAssert([attribute _hasParent] == NO, @"Cannot add an attribute with a parent; detach or copy first");
DDXMLAssert(IsXmlAttrPtr(attribute->genericPtr), @"Not an attribute");
[self _removeAttributeForName:[attribute name]];
// xmlNodePtr xmlAddChild(xmlNodePtr parent, xmlNodePtr cur)
// Add a new node to @parent, at the end of the child (or property) list merging
// adjacent TEXT nodes (in which case @cur is freed). If the new node is ATTRIBUTE, it is added
// into properties instead of children. If there is an attribute with equal name, it is first destroyed.
xmlAddChild((xmlNodePtr)genericPtr, (xmlNodePtr)attribute->genericPtr);
// The attribute is now part of the xml tree heirarchy
attribute->owner = self;
}
- (void)removeAttributeForName:(NSString *)name
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
[self _removeAttributeForName:name];
}
- (NSArray *)attributes
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
NSMutableArray *result = [NSMutableArray array];
xmlAttrPtr attr = ((xmlNodePtr)genericPtr)->properties;
while (attr != NULL)
{
[result addObject:[DDXMLAttributeNode nodeWithAttrPrimitive:attr owner:self]];
attr = attr->next;
}
return result;
}
- (DDXMLNode *)attributeForName:(NSString *)name
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
xmlAttrPtr attr = ((xmlNodePtr)genericPtr)->properties;
if (attr)
{
const xmlChar *xmlName = [name xmlChar];
do
{
if (attr->ns && attr->ns->prefix)
{
// If the attribute name was originally something like "xml:quack",
// then attr->name is "quack" and attr->ns->prefix is "xml".
//
// So if the user is searching for "xml:quack" we need to take the prefix into account.
// Note that "xml:quack" is what would be printed if we output the attribute.
if (xmlStrQEqual(attr->ns->prefix, attr->name, xmlName))
{
return [DDXMLAttributeNode nodeWithAttrPrimitive:attr owner:self];
}
}
else
{
if (xmlStrEqual(attr->name, xmlName))
{
return [DDXMLAttributeNode nodeWithAttrPrimitive:attr owner:self];
}
}
attr = attr->next;
} while (attr);
}
return nil;
}
/**
* Sets the list of attributes for the element.
* Any previously set attributes are removed.
**/
- (void)setAttributes:(NSArray *)attributes
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
[DDXMLNode removeAllAttributesFromNode:(xmlNodePtr)genericPtr];
NSUInteger i;
for (i = 0; i < [attributes count]; i++)
{
DDXMLNode *attribute = [attributes objectAtIndex:i];
[self addAttribute:attribute];
// Note: The addAttributes method properly sets the freeOnDealloc ivar.
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Namespaces
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)_removeNamespaceForPrefix:(NSString *)name
{
xmlNodePtr node = (xmlNodePtr)genericPtr;
// If name is nil or the empty string, the user is wishing to remove the default namespace
const xmlChar *xmlName = [name length] > 0 ? [name xmlChar] : NULL;
xmlNsPtr ns = node->nsDef;
while (ns != NULL)
{
if (xmlStrEqual(ns->prefix, xmlName))
{
[DDXMLNode removeNamespace:ns fromNode:node];
break;
}
ns = ns->next;
}
// Note: The removeNamespace method properly handles the situation where the namespace is the default namespace
}
- (void)_addNamespace:(DDXMLNode *)namespace
{
// NSXML version uses this same assertion
DDXMLAssert([namespace _hasParent] == NO, @"Cannot add a namespace with a parent; detach or copy first");
DDXMLAssert(IsXmlNsPtr(namespace->genericPtr), @"Not a namespace");
xmlNodePtr node = (xmlNodePtr)genericPtr;
xmlNsPtr ns = (xmlNsPtr)namespace->genericPtr;
// Beware: [namespace prefix] does NOT return what you might expect. Use [namespace name] instead.
NSString *namespaceName = [namespace name];
[self _removeNamespaceForPrefix:namespaceName];
xmlNsPtr currentNs = node->nsDef;
if (currentNs == NULL)
{
node->nsDef = ns;
}
else
{
while (currentNs->next != NULL)
{
currentNs = currentNs->next;
}
currentNs->next = ns;
}
// The namespace is now part of the xml tree heirarchy
namespace->owner = self;
if ([namespace isKindOfClass:[DDXMLNamespaceNode class]])
{
DDXMLNamespaceNode *ddNamespace = (DDXMLNamespaceNode *)namespace;
// The xmlNs structure doesn't contain a reference to the parent, so we manage our own reference
[ddNamespace _setNsParentPtr:node];
}
// Did we just add a default namespace
if ([namespaceName isEqualToString:@""])
{
node->ns = ns;
// Note: The removeNamespaceForPrefix method above properly handled removing any previous default namespace
}
}
- (void)addNamespace:(DDXMLNode *)namespace
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
[self _addNamespace:namespace];
}
- (void)removeNamespaceForPrefix:(NSString *)name
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
[self _removeNamespaceForPrefix:name];
}
- (NSArray *)namespaces
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
NSMutableArray *result = [NSMutableArray array];
xmlNsPtr ns = ((xmlNodePtr)genericPtr)->nsDef;
while (ns != NULL)
{
[result addObject:[DDXMLNamespaceNode nodeWithNsPrimitive:ns nsParent:(xmlNodePtr)genericPtr owner:self]];
ns = ns->next;
}
return result;
}
- (DDXMLNode *)namespaceForPrefix:(NSString *)prefix
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
// If the prefix is nil or the empty string, the user is requesting the default namespace
if ([prefix length] == 0)
{
// Requesting the default namespace
xmlNsPtr ns = ((xmlNodePtr)genericPtr)->ns;
if (ns != NULL)
{
return [DDXMLNamespaceNode nodeWithNsPrimitive:ns nsParent:(xmlNodePtr)genericPtr owner:self];
}
}
else
{
xmlNsPtr ns = ((xmlNodePtr)genericPtr)->nsDef;
if (ns)
{
const xmlChar *xmlPrefix = [prefix xmlChar];
do
{
if (xmlStrEqual(ns->prefix, xmlPrefix))
{
return [DDXMLNamespaceNode nodeWithNsPrimitive:ns nsParent:(xmlNodePtr)genericPtr owner:self];
}
ns = ns->next;
} while (ns);
}
}
return nil;
}
- (void)setNamespaces:(NSArray *)namespaces
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
[DDXMLNode removeAllNamespacesFromNode:(xmlNodePtr)genericPtr];
NSUInteger i;
for (i = 0; i < [namespaces count]; i++)
{
DDXMLNode *namespace = [namespaces objectAtIndex:i];
[self _addNamespace:namespace];
// Note: The addNamespace method properly sets the freeOnDealloc ivar.
}
}
/**
* Recursively searches the given node for the given namespace
**/
- (DDXMLNode *)_recursiveResolveNamespaceForPrefix:(NSString *)prefix atNode:(xmlNodePtr)nodePtr
{
// This is a private/internal method
if (nodePtr == NULL) return nil;
xmlNsPtr ns = nodePtr->nsDef;
if (ns)
{
const xmlChar *xmlPrefix = [prefix xmlChar];
do
{
if (xmlStrEqual(ns->prefix, xmlPrefix))
{
return [DDXMLNamespaceNode nodeWithNsPrimitive:ns nsParent:nodePtr owner:self];
}
ns = ns->next;
} while(ns);
}
return [self _recursiveResolveNamespaceForPrefix:prefix atNode:nodePtr->parent];
}
/**
* Returns the namespace node with the prefix matching the given qualified name.
* Eg: You pass it "a:dog", it returns the namespace (defined in this node or parent nodes) that has the "a" prefix.
**/
- (DDXMLNode *)resolveNamespaceForName:(NSString *)name
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
// If the user passes nil or an empty string for name, they're looking for the default namespace.
if ([name length] == 0)
{
return [self _recursiveResolveNamespaceForPrefix:nil atNode:(xmlNodePtr)genericPtr];
}
NSString *prefix = [[self class] prefixForName:name];
if ([prefix length] > 0)
{
// Unfortunately we can't use xmlSearchNs because it returns an xmlNsPtr.
// This gives us mostly what we want, except we also need to know the nsParent.
// So we do the recursive search ourselves.
return [self _recursiveResolveNamespaceForPrefix:prefix atNode:(xmlNodePtr)genericPtr];
}
return nil;
}
/**
* Recursively searches the given node for a namespace with the given URI, and a set prefix.
**/
- (NSString *)_recursiveResolvePrefixForURI:(NSString *)uri atNode:(xmlNodePtr)nodePtr
{
// This is a private/internal method
if (nodePtr == NULL) return nil;
xmlNsPtr ns = nodePtr->nsDef;
if (ns)
{
const xmlChar *xmlUri = [uri xmlChar];
do
{
if (xmlStrEqual(ns->href, xmlUri))
{
if (ns->prefix != NULL)
{
return [NSString stringWithUTF8String:((const char *)ns->prefix)];
}
}
ns = ns->next;
} while (ns);
}
return [self _recursiveResolvePrefixForURI:uri atNode:nodePtr->parent];
}
/**
* Returns the prefix associated with the specified URI.
* Returns a string that is the matching prefix or nil if it finds no matching prefix.
**/
- (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
// We can't use xmlSearchNsByHref because it will return xmlNsPtr's with NULL prefixes.
// We're looking for a definitive prefix for the given URI.
return [self _recursiveResolvePrefixForURI:namespaceURI atNode:(xmlNodePtr)genericPtr];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Children
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)addChild:(DDXMLNode *)child
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
// NSXML version uses these same assertions
DDXMLAssert([child _hasParent] == NO, @"Cannot add a child that has a parent; detach or copy first");
DDXMLAssert(IsXmlNodePtr(child->genericPtr),
@"Elements can only have text, elements, processing instructions, and comments as children");
xmlAddChild((xmlNodePtr)genericPtr, (xmlNodePtr)child->genericPtr);
// The node is now part of the xml tree heirarchy
child->owner = self;
}
- (void)insertChild:(DDXMLNode *)child atIndex:(NSUInteger)index
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
// NSXML version uses these same assertions
DDXMLAssert([child _hasParent] == NO, @"Cannot add a child that has a parent; detach or copy first");
DDXMLAssert(IsXmlNodePtr(child->genericPtr),
@"Elements can only have text, elements, processing instructions, and comments as children");
NSUInteger i = 0;
xmlNodePtr childNodePtr = ((xmlNodePtr)genericPtr)->children;
while (childNodePtr != NULL)
{
// Ignore all but element, comment, text, or processing instruction nodes
if (IsXmlNodePtr(childNodePtr))
{
if (i == index)
{
xmlAddPrevSibling(childNodePtr, (xmlNodePtr)child->genericPtr);
child->owner = self;
return;
}
i++;
}
childNodePtr = childNodePtr->next;
}
if (i == index)
{
xmlAddChild((xmlNodePtr)genericPtr, (xmlNodePtr)child->genericPtr);
child->owner = self;
return;
}
// NSXML version uses this same assertion
DDXMLAssert(NO, @"index (%u) beyond bounds (%u)", (unsigned)index, (unsigned)++i);
}
- (void)removeChildAtIndex:(NSUInteger)index
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
NSUInteger i = 0;
xmlNodePtr child = ((xmlNodePtr)genericPtr)->children;
while (child != NULL)
{
// Ignore all but element, comment, text, or processing instruction nodes
if (IsXmlNodePtr(child))
{
if (i == index)
{
[DDXMLNode removeChild:child];
return;
}
i++;
}
child = child->next;
}
}
- (void)setChildren:(NSArray *)children
{
#if DDXML_DEBUG_MEMORY_ISSUES
DDXMLNotZombieAssert();
#endif
[DDXMLNode removeAllChildrenFromNode:(xmlNodePtr)genericPtr];
NSUInteger i;
for (i = 0; i < [children count]; i++)
{
DDXMLNode *child = [children objectAtIndex:i];
[self addChild:child];
// Note: The addChild method properly sets the freeOnDealloc ivar.
}
}
@end
+161
View File
@@ -0,0 +1,161 @@
#import <Foundation/Foundation.h>
#if !(TARGET_IPHONE_SIMULATOR)
@import libxml;
#else
@import libxmlSimu;
#endif
@class DDXMLDocument;
/**
* Welcome to KissXML.
*
* The project page has documentation if you have questions.
* https://github.com/robbiehanson/KissXML
*
* If you're new to the project you may wish to read the "Getting Started" wiki.
* https://github.com/robbiehanson/KissXML/wiki/GettingStarted
*
* KissXML provides a drop-in replacement for Apple's NSXML class cluster.
* The goal is to get the exact same behavior as the NSXML classes.
*
* For API Reference, see Apple's excellent documentation,
* either via Xcode's Mac OS X documentation, or via the web:
*
* https://github.com/robbiehanson/KissXML/wiki/Reference
**/
enum {
DDXMLInvalidKind = 0,
DDXMLDocumentKind = XML_DOCUMENT_NODE,
DDXMLElementKind = XML_ELEMENT_NODE,
DDXMLAttributeKind = XML_ATTRIBUTE_NODE,
DDXMLNamespaceKind = XML_NAMESPACE_DECL,
DDXMLProcessingInstructionKind = XML_PI_NODE,
DDXMLCommentKind = XML_COMMENT_NODE,
DDXMLTextKind = XML_TEXT_NODE,
DDXMLDTDKind = XML_DTD_NODE,
DDXMLEntityDeclarationKind = XML_ENTITY_DECL,
DDXMLAttributeDeclarationKind = XML_ATTRIBUTE_DECL,
DDXMLElementDeclarationKind = XML_ELEMENT_DECL,
DDXMLNotationDeclarationKind = XML_NOTATION_NODE
};
typedef NSUInteger DDXMLNodeKind;
enum {
DDXMLNodeOptionsNone = 0,
DDXMLNodeExpandEmptyElement = 1 << 1,
DDXMLNodeCompactEmptyElement = 1 << 2,
DDXMLNodePrettyPrint = 1 << 17,
};
//extern struct _xmlKind;
@interface DDXMLNode : NSObject <NSCopying>
{
// Every DDXML object is simply a wrapper around an underlying libxml node
struct _xmlKind *genericPtr;
// Every libxml node resides somewhere within an xml tree heirarchy.
// We cannot free the tree heirarchy until all referencing nodes have been released.
// So all nodes retain a reference to the node that created them,
// and when the last reference is released the tree gets freed.
DDXMLNode *owner;
}
//- (id)initWithKind:(DDXMLNodeKind)kind;
//- (id)initWithKind:(DDXMLNodeKind)kind options:(NSUInteger)options;
//+ (id)document;
//+ (id)documentWithRootElement:(DDXMLElement *)element;
+ (id)elementWithName:(NSString *)name;
+ (id)elementWithName:(NSString *)name URI:(NSString *)URI;
+ (id)elementWithName:(NSString *)name stringValue:(NSString *)string;
+ (id)elementWithName:(NSString *)name children:(NSArray *)children attributes:(NSArray *)attributes;
+ (id)attributeWithName:(NSString *)name stringValue:(NSString *)stringValue;
+ (id)attributeWithName:(NSString *)name URI:(NSString *)URI stringValue:(NSString *)stringValue;
+ (id)namespaceWithName:(NSString *)name stringValue:(NSString *)stringValue;
+ (id)processingInstructionWithName:(NSString *)name stringValue:(NSString *)stringValue;
+ (id)commentWithStringValue:(NSString *)stringValue;
+ (id)textWithStringValue:(NSString *)stringValue;
//+ (id)DTDNodeWithXMLString:(NSString *)string;
#pragma mark --- Properties ---
- (DDXMLNodeKind)kind;
- (void)setName:(NSString *)name;
- (NSString *)name;
//- (void)setObjectValue:(id)value;
//- (id)objectValue;
- (void)setStringValue:(NSString *)string;
//- (void)setStringValue:(NSString *)string resolvingEntities:(BOOL)resolve;
- (NSString *)stringValue;
#pragma mark --- Tree Navigation ---
- (NSUInteger)index;
- (NSUInteger)level;
- (DDXMLDocument *)rootDocument;
- (DDXMLNode *)parent;
- (NSUInteger)childCount;
- (NSArray *)children;
- (DDXMLNode *)childAtIndex:(NSUInteger)index;
- (DDXMLNode *)previousSibling;
- (DDXMLNode *)nextSibling;
- (DDXMLNode *)previousNode;
- (DDXMLNode *)nextNode;
- (void)detach;
- (NSString *)XPath;
#pragma mark --- QNames ---
- (NSString *)localName;
- (NSString *)prefix;
- (void)setURI:(NSString *)URI;
- (NSString *)URI;
+ (NSString *)localNameForName:(NSString *)name;
+ (NSString *)prefixForName:(NSString *)name;
//+ (DDXMLNode *)predefinedNamespaceForPrefix:(NSString *)name;
#pragma mark --- Output ---
- (NSString *)description;
- (NSString *)XMLString;
- (NSString *)XMLStringWithOptions:(NSUInteger)options;
//- (NSString *)canonicalXMLStringPreservingComments:(BOOL)comments;
#pragma mark --- XPath/XQuery ---
- (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error;
//- (NSArray *)objectsForXQuery:(NSString *)xquery constants:(NSDictionary *)constants error:(NSError **)error;
//- (NSArray *)objectsForXQuery:(NSString *)xquery error:(NSError **)error;
@end
+2905
View File
File diff suppressed because it is too large. Load diff
+229
View File
@@ -0,0 +1,229 @@
#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