2002-03-06 15:50:14 +00:00
/ * * Implementation for GSXML classes
Copyright ( C ) 2000 , 2001 , 2002 Free Software Foundation , Inc .
Written by : Michael Pakhantsov < mishel @ berest . dp . ua > on behalf of
Brainstorm computer solutions .
Date : Jule 2000
Integration / updates / rewrites by : Richard Frith - Macdonald < rfm @ gnu . org >
Date : Sep2000 , Dec2001 / Jan2002
This file is part of the GNUstep Base Library .
This library is free software ; you can redistribute it and / or
2007-09-14 11:36:11 +00:00
modify it under the terms of the GNU Lesser General Public
2002-03-06 15:50:14 +00:00
License as published by the Free Software Foundation ; either
2008-06-08 10:38:33 +00:00
version 2 of the License , or ( at your option ) any later version .
2002-03-06 15:50:14 +00:00
This library is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Library General Public License for more details .
2007-09-14 11:36:11 +00:00
You should have received a copy of the GNU Lesser General Public
2002-03-06 15:50:14 +00:00
License along with this library ; if not , write to the Free
2006-04-28 10:57:47 +00:00
Software Foundation , Inc . , 51 Franklin Street , Fifth Floor ,
Boston , MA 02111 USA .
2002-03-06 15:50:14 +00:00
< title > The XML and HTML parsing system < / title >
< chapter >
< heading > The XML and HTML parsing system < / heading >
< p >
The GNUstep XML parser is a collection Objective - C classes
wrapping the C XML parsing library ( libxml ) .
< / p >
< p >
The underlying C library handles high performance parsing , while
the ObjectiveC classes provide ease of use / integration .
< / p >
< / chapter >
* /
A huge blob of changes to make -base build with libobjc2, without using the old libobjc2 headers.
Most of these changes involve simply removing direct manipulation of any runtime structures and replacing them with runtime function calls. For example class->name becomes class_getName(class) and so on.
libobjc2, like the Apple runtime, the NeXT runtime, and every version of the Objective-C spec, calls the class pointer in id isa. A few files now have #define class_pointer isa at the top. This line replaces class_pointer in the old GNU libobjc headers with isa so either class_pointer or isa can be used for accessing the class of an object. Note: object_getClass() should be used in most cases because, in some future version of the runtime, this will skip things like lock classes and other hidden classes (e.g. KVO classes).
All of the old forwarding stuff has been removed. Most of this stuff followed convoluted code paths that ended with an exception. A few simply broke in exciting ways. Hopefully no one has used them for the last ten years or so, but we can bring them back with some #ifndef stuff if they're really needed by anyone.
There is currently a bug in configure, which prevents dladdr() from being detected, so you need to manually tweak config.h to build - I have not fixed the fall-back code in objc-load.m to work with libobjc2, I just added a new version that uses the loader's functionality directly.
Although -base now builds, it builds with a lot of warnings. <string.h> is missing from a lot of files, so memcpy() and strlen() generate implicit function declaration warnings.
Additionally, libobjc2 does still provide the sel_{get,register}_*() functions, but they're wrappers around the newer API ones. These are deprecated and are not exposed in the headers. Although they work, we should be replacing them with the libobjc2 versions as soon as possible.
This incorporates a patch by Eric.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@31265 72102866-910b-0410-8b05-ffd578937521
2010-09-09 15:06:09 +00:00
# include < string . h >
2010-02-19 08:12:46 +00:00
# import "common.h"
2010-02-14 10:48:10 +00:00
# import "GNUstepBase/preface.h"
# import "GNUstepBase/Unicode.h"
2002-03-06 15:50:14 +00:00
2005-02-23 16:05:09 +00:00
2002-03-06 15:50:14 +00:00
# ifdef HAVE_LIBXML
2004-06-24 09:26:01 +00:00
// # undef HAVE_LIBXML _SAX2 _H
2010-04-23 04:06:17 +00:00
# import "GNUstepBase/GSObjCRuntime.h"
2004-06-24 09:26:01 +00:00
2010-02-14 10:48:10 +00:00
# import "GNUstepBase/GSMime.h"
# import "GNUstepBase/GSXML.h"
# import "Foundation/NSArray.h"
2010-02-14 11:01:08 +00:00
# import "Foundation/NSBundle.h"
# import "Foundation/NSCalendarDate.h"
# import "Foundation/NSCharacterSet.h"
# import "Foundation/NSData.h"
2010-02-14 10:48:10 +00:00
# import "Foundation/NSDictionary.h"
# import "Foundation/NSEnumerator.h"
2010-02-14 11:01:08 +00:00
# import "Foundation/NSException.h"
# import "Foundation/NSFileManager.h"
# import "Foundation/NSRunLoop.h"
2010-02-26 08:56:26 +00:00
# import "Foundation/NSString.h"
2010-02-14 11:01:08 +00:00
# import "Foundation/NSTimer.h"
# import "Foundation/NSTimeZone.h"
# import "Foundation/NSURL.h"
2010-02-26 09:03:46 +00:00
# import "Foundation/NSURLHandle.h"
2010-02-14 11:01:08 +00:00
# import "Foundation/NSValue.h"
2002-03-06 15:50:14 +00:00
2008-12-06 16:52:03 +00:00
/ * Avoid problems on systems where the xml headers use ' id '
* /
# define id GSXMLID
2002-03-06 15:50:14 +00:00
/ * libxml headers * /
2002-05-23 15:58:15 +00:00
# include < libxml / tree . h >
# include < libxml / entities . h >
# include < libxml / parser . h >
# include < libxml / parserInternals . h >
2010-02-16 17:34:05 +00:00
# include < libxml / catalog . h >
2004-05-18 09:55:33 +00:00
# ifdef HAVE_LIBXML _SAX2 _H
# include < libxml / SAX2 . h >
# else
# define xmlSAX2GetColumnNumber getColumnNumber
# define xmlSAX2GetLineNumber getLineNumber
# define xmlSAX2GetPublicId getPublicId
# define xmlSAX2GetSystemId getSystemId
2010-02-16 17:34:05 +00:00
# define xmlSAX2ResolveEntity resolveEntity
2004-05-18 09:55:33 +00:00
# endif
2002-05-23 15:58:15 +00:00
# include < libxml / HTMLparser . h >
# include < libxml / xmlmemory . h >
2002-08-27 15:46:15 +00:00
# include < libxml / xpath . h >
2008-01-05 21:01:40 +00:00
# include < libxml / xpathInternals . h >
2002-03-06 15:50:14 +00:00
2004-03-28 04:42:11 +00:00
# ifdef HAVE_LIBXSLT
# include < libxslt / xslt . h >
# include < libxslt / xsltInternals . h >
# include < libxslt / transform . h >
# include < libxslt / xsltutils . h >
# endif / * HAVE_LIBXSLT * /
2008-12-06 16:52:03 +00:00
# undef id
2002-03-06 15:50:14 +00:00
/ *
* optimization
*
* /
static Class NSString_class ;
2003-05-23 08:58:52 +00:00
static Class treeClass ;
2002-03-06 15:50:14 +00:00
static IMP usImp ;
static SEL usSel ;
2005-07-08 11:48:37 +00:00
/ *
* Macro to cast results to correct type for libxml2
* /
# define UTF8STRING ( X ) ( ( const unsigned char * ) [ X UTF8String ] )
2002-03-06 15:50:14 +00:00
inline static NSString *
2003-05-23 08:58:52 +00:00
UTF8Str ( const unsigned char * bytes )
2002-03-06 15:50:14 +00:00
{
2010-06-09 20:40:41 +00:00
// stringWithUTF8String : raises on OSX if you feed it with a NULL string .
if ( ( bytes = = NULL ) ) {
return nil ;
}
2002-03-06 15:50:14 +00:00
return ( * usImp ) ( NSString_class , usSel , bytes ) ;
}
inline static NSString *
2003-05-23 08:58:52 +00:00
UTF8StrLen ( const unsigned char * bytes , unsigned length )
2002-03-06 15:50:14 +00:00
{
NSString * str ;
2006-10-09 14:00:01 +00:00
str = [ [ NSString_class alloc ] initWithBytes : bytes
length : length
encoding : NSUTF8StringEncoding ] ;
return AUTORELEASE ( str ) ;
2002-03-06 15:50:14 +00:00
}
static BOOL cacheDone = NO ;
2004-01-15 04:07:08 +00:00
# ifdef NeXT_Foundation _LIBRARY
@ interface NSObject ( MissingFromMacOSX )
+ ( IMP ) methodForSelector : ( SEL ) aSelector ;
@ end
# endif
2010-02-26 09:03:46 +00:00
static char * xml_strdup ( const char * from )
2005-02-16 17:40:48 +00:00
{
unsigned len = ( from = = 0 ) ? 1 : ( strlen ( from ) + 1 ) ;
2010-02-26 09:03:46 +00:00
char * to = malloc ( len ) ;
2005-02-16 17:40:48 +00:00
strcpy ( to , from ) ;
return to ;
}
2002-03-06 15:50:14 +00:00
static void
setupCache ( )
{
if ( cacheDone = = NO )
{
cacheDone = YES ;
2010-02-26 09:03:46 +00:00
xmlMemSetup ( free , malloc , realloc , xml_strdup ) ;
2010-02-16 17:34:05 +00:00
xmlInitializeCatalog ( ) ;
2004-05-30 09:05:10 +00:00
# if HAVE_LIBXML _SAX2 _H
xmlDefaultSAXHandlerInit ( ) ;
# endif
2002-03-06 15:50:14 +00:00
NSString_class = [ NSString class ] ;
usSel = @ selector ( stringWithUTF8String : ) ;
usImp = [ NSString_class methodForSelector : usSel ] ;
2003-05-23 08:58:52 +00:00
treeClass = [ GSTreeSAXHandler class ] ;
2002-03-06 15:50:14 +00:00
}
}
static xmlParserInputPtr
2006-02-27 16:54:36 +00:00
loadEntityFunction ( void * ctx ,
const unsigned char * eid , const unsigned char * url ) ;
2002-03-06 15:50:14 +00:00
2004-01-12 19:42:18 +00:00
@ interface GSXPathObject ( Private )
+ ( id ) _newWithNativePointer : ( xmlXPathObject * ) lib
context : ( GSXPathContext * ) context ;
@ end
2002-05-22 14:23:17 +00:00
@ interface GSXMLDocument ( GSPrivate )
2002-05-22 16:26:42 +00:00
- ( id ) _initFrom : ( void * ) data parent : ( id ) p ownsLib : ( BOOL ) f ;
2002-05-22 14:23:17 +00:00
@ end
2002-03-06 15:50:14 +00:00
@ interface GSXMLNamespace ( GSPrivate )
2002-05-22 16:26:42 +00:00
- ( id ) _initFrom : ( void * ) data parent : ( id ) p ;
2002-03-06 15:50:14 +00:00
@ end
@ interface GSXMLNode ( GSPrivate )
2002-05-22 16:26:42 +00:00
- ( id ) _initFrom : ( void * ) data parent : ( id ) p ;
2002-03-06 15:50:14 +00:00
@ end
@ interface GSXMLParser ( Private )
- ( BOOL ) _initLibXML ;
2003-05-22 19:02:38 +00:00
- ( NSMutableString * ) _messages ;
2002-03-06 15:50:14 +00:00
- ( void ) _parseChunk : ( NSData * ) data ;
@ end
@ interface GSSAXHandler ( Private )
- ( BOOL ) _initLibXML ;
- ( void ) _setParser : ( GSXMLParser * ) value ;
@ end
2002-11-22 10:47:48 +00:00
/ * *
* A class wrapping attributes of an XML element node . Generally when
* examining a GSXMLDocument , you need not concern yourself with
* GSXMLAttribute objects as you will probably use the
* [ GSXMLNode - objectForKey : ] method to return the string value of any
* attribute you are interested in .
* /
2002-05-26 17:05:46 +00:00
@ implementation GSXMLAttribute
2002-03-06 15:50:14 +00:00
2002-05-22 14:23:17 +00:00
static NSMapTable * attrNames = 0 ;
+ ( void ) initialize
{
if ( self = = [ GSXMLAttribute class ] )
{
if ( cacheDone = = NO )
setupCache ( ) ;
attrNames = NSCreateMapTable ( NSIntMapKeyCallBacks ,
NSNonRetainedObjectMapValueCallBacks , 0 ) ;
NSMapInsert ( attrNames ,
( void * ) XML_ATTRIBUTE _CDATA , ( void * ) @ "XML_ATTRIBUTE_CDATA" ) ;
NSMapInsert ( attrNames ,
( void * ) XML_ATTRIBUTE _ID , ( void * ) @ "XML_ATTRIBUTE_ID" ) ;
NSMapInsert ( attrNames ,
( void * ) XML_ATTRIBUTE _IDREF , ( void * ) @ "XML_ATTRIBUTE_IDREF" ) ;
NSMapInsert ( attrNames ,
( void * ) XML_ATTRIBUTE _IDREFS , ( void * ) @ "XML_ATTRIBUTE_IDREFS" ) ;
NSMapInsert ( attrNames ,
( void * ) XML_ATTRIBUTE _ENTITY , ( void * ) @ "XML_ATTRIBUTE_ENTITY" ) ;
NSMapInsert ( attrNames ,
( void * ) XML_ATTRIBUTE _ENTITIES , ( void * ) @ "XML_ATTRIBUTE_ENTITIES" ) ;
NSMapInsert ( attrNames ,
( void * ) XML_ATTRIBUTE _NMTOKEN , ( void * ) @ "XML_ATTRIBUTE_NMTOKEN" ) ;
NSMapInsert ( attrNames ,
( void * ) XML_ATTRIBUTE _NMTOKENS , ( void * ) @ "XML_ATTRIBUTE_NMTOKENS" ) ;
NSMapInsert ( attrNames ,
( void * ) XML_ATTRIBUTE _ENUMERATION , ( void * ) @ "XML_ATTRIBUTE_ENUMERATION" ) ;
NSMapInsert ( attrNames ,
( void * ) XML_ATTRIBUTE _NOTATION , ( void * ) @ "XML_ATTRIBUTE_NOTATION" ) ;
}
}
2009-02-23 20:42:32 +00:00
+ ( NSInteger ) typeFromDescription : ( NSString * ) desc
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
NSMapEnumerator enumerator ;
NSString * val ;
2004-10-31 13:02:58 +00:00
void * key ;
2002-05-22 14:23:17 +00:00
enumerator = NSEnumerateMapTable ( attrNames ) ;
2004-10-31 13:02:58 +00:00
while ( NSNextMapEnumeratorPair ( & enumerator , & key , ( void * * ) & val ) )
2002-05-22 14:23:17 +00:00
{
if ( [ desc isEqual : val ] = = YES )
{
2009-02-23 20:42:32 +00:00
return ( NSInteger ) ( intptr_t ) key ;
2002-05-22 14:23:17 +00:00
}
}
return -1 ;
2002-03-06 15:50:14 +00:00
}
2009-02-23 20:42:32 +00:00
+ ( NSString * ) descriptionFromType : ( NSInteger ) type
2002-05-22 14:23:17 +00:00
{
2006-01-10 10:29:11 +00:00
NSString * desc = ( NSString * ) NSMapGet ( attrNames , ( void * ) ( intptr_t ) type ) ;
2002-05-22 14:23:17 +00:00
return desc ;
}
2009-02-23 20:42:32 +00:00
- ( NSInteger ) type
2002-05-22 14:23:17 +00:00
{
2009-02-23 20:42:32 +00:00
return ( NSInteger ) ( ( xmlAttrPtr ) ( lib ) ) -> atype ;
2002-05-22 14:23:17 +00:00
}
- ( NSString * ) typeDescription
{
2006-01-10 10:29:11 +00:00
NSString * desc ;
2002-05-22 14:23:17 +00:00
2006-01-10 10:29:11 +00:00
desc = ( NSString * ) NSMapGet ( attrNames , ( void * ) ( intptr_t ) [ self type ] ) ;
2002-05-22 14:23:17 +00:00
if ( desc = = nil )
{
desc = @ "Unknown attribute type" ;
}
return desc ;
}
2002-09-25 15:32:11 +00:00
/ * *
2002-11-22 10:47:48 +00:00
* Return the next sibling node . . . another GSXMLAttribute instance .
2002-09-25 15:32:11 +00:00
* /
2002-05-22 14:23:17 +00:00
- ( GSXMLNode * ) next
{
if ( ( ( xmlAttrPtr ) ( lib ) ) -> next ! = NULL )
{
return AUTORELEASE ( [ [ GSXMLAttribute alloc ]
2002-05-22 16:26:42 +00:00
_initFrom : ( ( xmlAttrPtr ) ( lib ) ) -> next parent : self ] ) ;
2002-05-22 14:23:17 +00:00
}
else
{
return nil ;
}
}
2002-11-22 10:47:48 +00:00
/ * *
* Return the previous sibling node . . . another GSXMLAttribute instance .
* /
2002-05-22 14:23:17 +00:00
- ( GSXMLNode * ) previous
{
if ( ( ( xmlAttrPtr ) ( lib ) ) -> prev ! = NULL )
{
return AUTORELEASE ( [ [ GSXMLAttribute alloc ]
2002-05-22 16:26:42 +00:00
_initFrom : ( ( xmlAttrPtr ) ( lib ) ) -> prev parent : self ] ) ;
2002-05-22 14:23:17 +00:00
}
else
{
return nil ;
}
}
2002-11-22 10:47:48 +00:00
/ * *
* Returns the string value of the attribute .
* /
2002-05-22 14:23:17 +00:00
- ( NSString * ) value
{
if ( ( ( xmlNodePtr ) lib ) -> children ! = NULL
&& ( ( xmlNodePtr ) lib ) -> children -> content ! = NULL )
{
return UTF8Str ( ( ( xmlNodePtr ) ( lib ) ) -> children -> content ) ;
}
return nil ;
}
@ end
/ * *
* A GSXML document wraps the document structure of the underlying
2002-05-22 16:26:42 +00:00
* libxml library .
2002-05-22 14:23:17 +00:00
* /
2002-05-26 17:05:46 +00:00
@ implementation GSXMLDocument
2002-05-22 14:23:17 +00:00
2002-03-06 15:50:14 +00:00
/ * *
* Create a new document with the specified version .
* < example >
* id d = [ GSXMLDocument documentWithVersion : @ "1.0" ] ;
*
* [ d setRoot : [ d makeNodeWithNamespace : nil name : @ "plist" content : nil ] ] ;
2002-05-22 14:23:17 +00:00
* [ [ d root ] setObject : @ "0.9" forKey : @ "version" ] ;
2002-03-06 15:50:14 +00:00
* n1 = [ [ d root ] makeChildWithNamespace : nil name : @ "dict" content : nil ] ;
* [ n1 makeComment : @ " this is a comment " ] ;
* [ n1 makePI : @ "pi1" content : @ "this is a process instruction" ] ;
* [ n1 makeChildWithNamespace : nil name : @ "key" content : @ "Year Of Birth" ] ;
* [ n1 makeChildWithNamespace : nil name : @ "integer" content : @ "65" ] ;
2002-03-12 10:01:54 +00:00
* [ n1 makeChildWithNamespace : nil name : @ "key" content : @ "Pets Names" ] ;
2002-03-06 15:50:14 +00:00
* < / example >
* /
+ ( GSXMLDocument * ) documentWithVersion : ( NSString * ) version
{
2005-07-08 11:48:37 +00:00
void * data = xmlNewDoc ( UTF8STRING ( version ) ) ;
2002-05-23 15:58:15 +00:00
GSXMLDocument * document = nil ;
2002-05-22 14:23:17 +00:00
if ( data = = 0 )
{
NSLog ( @ "Can't create GSXMLDocument object" ) ;
}
2002-05-23 15:58:15 +00:00
else
{
document = [ GSXMLDocument alloc ] ;
document = [ document _initFrom : data parent : nil ownsLib : YES ] ;
}
return AUTORELEASE ( document ) ;
2002-03-06 15:50:14 +00:00
}
+ ( void ) initialize
{
if ( cacheDone = = NO )
setupCache ( ) ;
}
- ( id ) copyWithZone : ( NSZone * ) z
{
return RETAIN ( self ) ;
}
- ( void ) dealloc
{
2002-05-22 16:26:42 +00:00
if ( _ownsLib = = YES && lib ! = NULL )
2002-03-06 15:50:14 +00:00
{
xmlFreeDoc ( lib ) ;
}
2002-05-22 16:26:42 +00:00
RELEASE ( _parent ) ;
2002-03-06 15:50:14 +00:00
[ super dealloc ] ;
}
/ * *
* Returns a string representation of the document ( ie the XML )
* or nil if the document does not have reasonable contents .
* /
- ( NSString * ) description
{
NSString * string = nil ;
xmlChar * buf = NULL ;
int length ;
2003-06-18 10:08:02 +00:00
xmlDocDumpFormatMemoryEnc ( lib , & buf , & length , "utf-8" , 1 ) ;
2002-03-06 15:50:14 +00:00
if ( buf ! = 0 && length > 0 )
{
2002-05-11 03:06:51 +00:00
string = UTF8StrLen ( buf , length ) ;
2010-02-26 09:03:46 +00:00
free ( buf ) ;
2002-03-06 15:50:14 +00:00
}
return string ;
}
/ * *
* Returns the name of the encoding for this document .
* /
- ( NSString * ) encoding
{
2002-05-11 03:06:51 +00:00
return UTF8Str ( ( ( xmlDocPtr ) ( lib ) ) -> encoding ) ;
2002-03-06 15:50:14 +00:00
}
2009-02-23 20:42:32 +00:00
- ( NSUInteger ) hash
2002-03-06 15:50:14 +00:00
{
2009-02-23 20:42:32 +00:00
return ( ( ( NSUInteger ) ( intptr_t ) lib ) > > 3 ) ;
2002-03-06 15:50:14 +00:00
}
- ( id ) init
{
NSLog ( @ "GSXMLDocument: calling -init is not legal" ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-03-06 15:50:14 +00:00
return nil ;
}
/ * *
2002-05-22 14:23:17 +00:00
* Returns a pointer to the raw libxml data used by this document . < br / >
* Only for use by libxml experts !
2002-03-06 15:50:14 +00:00
* /
- ( void * ) lib
{
return lib ;
}
/ * *
* Creates a new node within the document .
* < example >
* GSXMLNode * n1 , * n2 ;
* GSXMLDocument * d ;
*
* d = [ GSXMLDocument documentWithVersion : @ "1.0" ] ;
* [ d setRoot : [ d makeNodeWithNamespace : nil name : @ "plist" content : nil ] ] ;
2002-05-22 14:23:17 +00:00
* [ [ d root ] setObject : @ "0.9" forKey : @ "version" ] ;
2002-03-06 15:50:14 +00:00
* n1 = [ [ d root ] makeChildWithNamespace : nil name : @ "dict" content : nil ] ;
* < / example >
* /
- ( GSXMLNode * ) makeNodeWithNamespace : ( GSXMLNamespace * ) ns
name : ( NSString * ) name
content : ( NSString * ) content
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
n = [ n _initFrom :
2005-07-08 11:48:37 +00:00
xmlNewDocNode ( lib , [ ns lib ] , UTF8STRING ( name ) , UTF8STRING ( content ) )
2002-05-22 16:26:42 +00:00
parent : self ] ;
return AUTORELEASE ( n ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Returns the root node of the document .
* /
- ( GSXMLNode * ) root
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
n = [ n _initFrom : xmlDocGetRootElement ( lib ) parent : self ] ;
return AUTORELEASE ( n ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
2006-11-18 08:03:05 +00:00
* Sets the root of the document . < br / >
* NB . The node must have been created as part of the receiving document
* ( eg . using the - makeNodeWithNamespace : name : content : method ) .
2002-03-06 15:50:14 +00:00
* /
- ( GSXMLNode * ) setRoot : ( GSXMLNode * ) node
{
2006-11-18 08:03:05 +00:00
xmlNodePtr nodeLib = ( xmlNodePtr ) [ node lib ] ;
xmlNodePtr selfLib = ( xmlNodePtr ) [ self lib ] ;
2002-05-22 16:26:42 +00:00
2006-11-18 08:03:05 +00:00
if ( node = = nil )
{
[ NSException raise : NSInvalidArgumentException
format : @ "Attempt to set root of document to nil" ] ;
}
if ( nodeLib -> doc ! = selfLib -> doc )
{
[ NSException raise : NSInvalidArgumentException
format : @ "Attempt to set root to node from other document" ] ;
}
xmlDocSetRootElement ( lib , nodeLib ) ;
return node ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Returns the version string for this document .
* /
- ( NSString * ) version
{
2002-05-11 03:06:51 +00:00
return UTF8Str ( ( ( xmlDocPtr ) ( lib ) ) -> version ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Uses the - description method to produce a string representation of
* the document and writes that to filename .
* /
- ( BOOL ) writeToFile : ( NSString * ) filename atomically : ( BOOL ) useAuxilliaryFile
{
NSString * s = [ self description ] ;
if ( s = = nil )
{
return NO ;
}
return [ s writeToFile : filename atomically : useAuxilliaryFile ] ;
}
/ * *
* Uses the - description method to produce a string representation of
* the document and writes that to url .
* /
- ( BOOL ) writeToURL : ( NSURL * ) url atomically : ( BOOL ) useAuxilliaryFile
{
NSString * s = [ self description ] ;
if ( s = = nil )
{
return NO ;
}
return [ s writeToURL : url atomically : useAuxilliaryFile ] ;
}
@ end
2002-05-22 14:23:17 +00:00
@ implementation GSXMLDocument ( GSPrivate )
/ * *
* < init / >
* Initialise a new document object using raw libxml data .
* The resulting document does not ' own ' the data , and will not free it .
* /
2002-05-22 16:26:42 +00:00
- ( id ) _initFrom : ( void * ) data parent : ( id ) p ownsLib : ( BOOL ) f
2002-05-22 14:23:17 +00:00
{
if ( data = = NULL )
{
NSLog ( @ "%@ - no data for initialization" ,
NSStringFromClass ( [ self class ] ) ) ;
DESTROY ( self ) ;
return nil ;
}
lib = data ;
2002-05-22 16:26:42 +00:00
_ownsLib = f ;
ASSIGN ( _parent , p ) ;
2002-05-22 14:23:17 +00:00
return self ;
}
@ end
/ * *
* A GSXMLNamespace object wraps part of the document structure of
2002-05-22 16:26:42 +00:00
* the underlying libxml library .
2002-05-22 14:23:17 +00:00
* /
2002-05-26 17:05:46 +00:00
@ implementation GSXMLNamespace
2002-03-06 15:50:14 +00:00
static NSMapTable * nsNames = 0 ;
/ * *
* Return the string representation of the specified numeric type .
* /
2009-02-23 20:42:32 +00:00
+ ( NSString * ) descriptionFromType : ( NSInteger ) type
2002-03-06 15:50:14 +00:00
{
2006-01-10 10:29:11 +00:00
NSString * desc = ( NSString * ) NSMapGet ( nsNames , ( void * ) ( intptr_t ) type ) ;
2002-03-06 15:50:14 +00:00
return desc ;
}
+ ( void ) initialize
{
if ( self = = [ GSXMLNamespace class ] )
{
if ( cacheDone = = NO )
setupCache ( ) ;
nsNames = NSCreateMapTable ( NSIntMapKeyCallBacks ,
NSNonRetainedObjectMapValueCallBacks , 0 ) ;
NSMapInsert ( nsNames ,
( void * ) XML_LOCAL _NAMESPACE , ( void * ) @ "XML_LOCAL_NAMESPACE" ) ;
}
}
/ * *
* Return the numeric constant value for the namespace
* type named . This method is inefficient , so the returned
* value should be saved for re - use later . The possible
* values are -
* < list >
* < item > XML_LOCAL _NAMESPACE < / item >
* < / list >
* /
2009-02-23 20:42:32 +00:00
+ ( NSInteger ) typeFromDescription : ( NSString * ) desc
2002-03-06 15:50:14 +00:00
{
NSMapEnumerator enumerator ;
NSString * val ;
2004-10-31 13:02:58 +00:00
void * key ;
2002-03-06 15:50:14 +00:00
enumerator = NSEnumerateMapTable ( nsNames ) ;
2004-10-31 13:02:58 +00:00
while ( NSNextMapEnumeratorPair ( & enumerator , & key , ( void * * ) & val ) )
2002-03-06 15:50:14 +00:00
{
if ( [ desc isEqual : val ] = = YES )
{
2009-02-23 20:42:32 +00:00
return ( NSInteger ) ( intptr_t ) key ;
2002-03-06 15:50:14 +00:00
}
}
return -1 ;
}
- ( id ) copyWithZone : ( NSZone * ) z
{
return RETAIN ( self ) ;
}
2002-05-22 16:26:42 +00:00
- ( void ) dealloc
{
RELEASE ( _parent ) ;
[ super dealloc ] ;
}
2009-02-23 20:42:32 +00:00
- ( NSUInteger ) hash
2002-03-06 15:50:14 +00:00
{
2009-02-23 20:42:32 +00:00
return ( ( ( NSUInteger ) ( intptr_t ) lib ) > > 3 ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Returns the namespace reference
* /
- ( NSString * ) href
{
return UTF8Str ( ( ( xmlNsPtr ) ( lib ) ) -> href ) ;
}
- ( id ) init
{
NSLog ( @ "GSXMLNamespace: calling -init is not legal" ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-03-06 15:50:14 +00:00
return nil ;
}
2002-03-12 13:23:27 +00:00
- ( BOOL ) isEqual : ( id ) other
2002-03-06 15:50:14 +00:00
{
if ( [ other isKindOfClass : [ self class ] ] = = YES && [ other lib ] = = lib )
return YES ;
else
return NO ;
}
/ * *
2002-05-22 14:23:17 +00:00
* Returns a pointer to the raw libxml data used by this document . < br / >
* Only for use by libxml experts !
2002-03-06 15:50:14 +00:00
* /
- ( void * ) lib
{
return lib ;
}
/ * *
* return the next namespace .
* /
- ( GSXMLNamespace * ) next
{
if ( ( ( xmlNsPtr ) ( lib ) ) -> next ! = NULL )
{
2002-05-22 16:26:42 +00:00
GSXMLNamespace * ns = [ GSXMLNamespace alloc ] ;
ns = [ ns _initFrom : ( ( xmlNsPtr ) ( lib ) ) -> next parent : self ] ;
return AUTORELEASE ( ns ) ;
2002-03-06 15:50:14 +00:00
}
else
{
return nil ;
}
}
/ * *
* Return the namespace prefix .
* /
- ( NSString * ) prefix
{
return UTF8Str ( ( ( xmlNsPtr ) ( lib ) ) -> prefix ) ;
}
/ * *
* Return type of namespace
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) type
2002-03-06 15:50:14 +00:00
{
2009-02-23 20:42:32 +00:00
return ( NSInteger ) ( ( xmlNsPtr ) ( lib ) ) -> type ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Return string representation of the type of the namespace .
* /
- ( NSString * ) typeDescription
{
2006-01-10 10:29:11 +00:00
NSString * desc ;
2002-03-06 15:50:14 +00:00
2006-01-10 10:29:11 +00:00
desc = ( NSString * ) NSMapGet ( nsNames , ( void * ) ( intptr_t ) [ self type ] ) ;
2002-03-06 15:50:14 +00:00
if ( desc = = nil )
{
desc = @ "Unknown namespace type" ;
}
return desc ;
}
@ end
@ implementation GSXMLNamespace ( GSPrivate )
2002-05-22 14:23:17 +00:00
/ * *
* Initialise a new namespace object using raw libxml data .
* The resulting namespace does not ' own ' the data , and will not free it .
* /
2002-05-22 16:26:42 +00:00
- ( id ) _initFrom : ( void * ) data parent : ( id ) p
2002-05-22 14:23:17 +00:00
{
if ( data = = NULL )
{
NSLog ( @ "%@ - no data for initialization" ,
NSStringFromClass ( [ self class ] ) ) ;
DESTROY ( self ) ;
return nil ;
}
lib = data ;
2002-05-22 16:26:42 +00:00
ASSIGN ( _parent , p ) ;
2002-05-22 14:23:17 +00:00
return self ;
}
2002-03-06 15:50:14 +00:00
@ end
2002-05-22 14:23:17 +00:00
/ * *
* A GSXMLNode object wraps part of the document structure of the
2002-11-22 10:47:48 +00:00
* underlying libxml library . It may have a parent , siblings , and children .
2002-05-22 14:23:17 +00:00
* /
2002-05-26 17:05:46 +00:00
@ implementation GSXMLNode
2002-03-06 15:50:14 +00:00
static NSMapTable * nodeNames = 0 ;
/ * *
* Return the string constant value for the node type given .
* /
2009-02-23 20:42:32 +00:00
+ ( NSString * ) descriptionFromType : ( NSInteger ) type
2002-03-06 15:50:14 +00:00
{
2006-01-10 10:29:11 +00:00
NSString * desc = ( NSString * ) NSMapGet ( nodeNames , ( void * ) ( intptr_t ) type ) ;
2002-03-06 15:50:14 +00:00
return desc ;
}
+ ( void ) initialize
{
if ( self = = [ GSXMLNode class ] )
{
if ( cacheDone = = NO )
setupCache ( ) ;
nodeNames = NSCreateMapTable ( NSIntMapKeyCallBacks ,
NSNonRetainedObjectMapValueCallBacks , 0 ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_ELEMENT _NODE , ( void * ) @ "XML_ELEMENT_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_ATTRIBUTE _NODE , ( void * ) @ "XML_ATTRIBUTE_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_TEXT _NODE , ( void * ) @ "XML_TEXT_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_CDATA _SECTION _NODE , ( void * ) @ "XML_CDATA_SECTION_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_ENTITY _REF _NODE , ( void * ) @ "XML_ENTITY_REF_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_ENTITY _NODE , ( void * ) @ "XML_ENTITY_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_PI _NODE , ( void * ) @ "XML_PI_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_COMMENT _NODE , ( void * ) @ "XML_COMMENT_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_DOCUMENT _NODE , ( void * ) @ "XML_DOCUMENT_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_DOCUMENT _TYPE _NODE , ( void * ) @ "XML_DOCUMENT_TYPE_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_DOCUMENT _FRAG _NODE , ( void * ) @ "XML_DOCUMENT_FRAG_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_NOTATION _NODE , ( void * ) @ "XML_NOTATION_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_HTML _DOCUMENT _NODE , ( void * ) @ "XML_HTML_DOCUMENT_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_DTD _NODE , ( void * ) @ "XML_DTD_NODE" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_ELEMENT _DECL , ( void * ) @ "XML_ELEMENT_DECL" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_ATTRIBUTE _DECL , ( void * ) @ "XML_ATTRIBUTE_DECL" ) ;
NSMapInsert ( nodeNames ,
( void * ) XML_ENTITY _DECL , ( void * ) @ "XML_ENTITY_DECL" ) ;
}
}
2002-11-22 10:47:48 +00:00
/ * *
* < p > Converts a node type string to a numeric constant which can be compared
* with the result of the - type method to determine what sort of node an
* instance is . Because this method is quite inefficient , you should cache
* the numeric type returned and re - use the cached value .
* < / p >
* The node type names are -
* < list >
* < item > XML_ELEMENT _NODE < / item >
* < item > XML_ATTRIBUTE _NODE < / item >
* < item > XML_TEXT _NODE < / item >
* < item > XML_CDATA _SECTION _NODE < / item >
* < item > XML_ENTITY _REF _NODE < / item >
* < item > XML_ENTITY _NODE < / item >
* < item > XML_PI _NODE < / item >
* < item > XML_COMMENT _NODE < / item >
* < item > XML_DOCUMENT _NODE < / item >
* < item > XML_DOCUMENT _TYPE _NODE < / item >
* < item > XML_DOCUMENT _FRAG _NODE < / item >
* < item > XML_NOTATION _NODE < / item >
* < item > XML_HTML _DOCUMENT _NODE < / item >
* < item > XML_DTD _NODE < / item >
* < item > XML_ELEMENT _DECL < / item >
* < item > XML_ATTRIBUTE _DECL < / item >
* < item > XML_ENTITY _DECL < / item >
* < / list >
* /
2009-02-23 20:42:32 +00:00
+ ( NSInteger ) typeFromDescription : ( NSString * ) desc
2002-03-06 15:50:14 +00:00
{
NSMapEnumerator enumerator ;
NSString * val ;
2004-10-31 13:02:58 +00:00
void * key ;
2002-03-06 15:50:14 +00:00
enumerator = NSEnumerateMapTable ( nodeNames ) ;
2004-10-31 13:02:58 +00:00
while ( NSNextMapEnumeratorPair ( & enumerator , & key , ( void * * ) & val ) )
2002-03-06 15:50:14 +00:00
{
if ( [ desc isEqual : val ] = = YES )
{
2009-02-23 20:42:32 +00:00
return ( NSInteger ) ( intptr_t ) key ;
2002-03-06 15:50:14 +00:00
}
}
return -1 ;
}
/ * *
2002-05-22 14:23:17 +00:00
* < p >
* Return attributes and values as a dictionary
* < / p >
2002-04-12 11:37:00 +00:00
* /
2002-05-22 14:23:17 +00:00
- ( NSDictionary * ) attributes
2002-04-12 11:37:00 +00:00
{
2002-05-22 14:23:17 +00:00
xmlAttrPtr prop ;
NSMutableDictionary * d = [ NSMutableDictionary dictionary ] ;
2002-04-12 11:37:00 +00:00
2002-05-22 14:23:17 +00:00
prop = ( ( xmlNodePtr ) ( lib ) ) -> properties ;
while ( prop ! = NULL )
2002-04-12 11:37:00 +00:00
{
2002-05-22 14:23:17 +00:00
const void * name = prop -> name ;
NSString * key = UTF8Str ( name ) ;
2002-10-12 08:20:49 +00:00
NSString * value = @ "" ;
xmlNodePtr child = prop -> children ;
2002-05-22 14:23:17 +00:00
2002-10-12 08:20:49 +00:00
while ( child ! = NULL )
2002-04-12 11:37:00 +00:00
{
2002-10-12 08:20:49 +00:00
const void * content = child -> content ;
2002-05-22 14:23:17 +00:00
2002-10-12 08:20:49 +00:00
value = [ value stringByAppendingString : UTF8Str ( content ) ] ;
child = child -> next ;
2002-05-22 14:23:17 +00:00
}
2002-10-12 08:20:49 +00:00
[ d setObject : value forKey : key ] ;
2002-05-22 14:23:17 +00:00
prop = prop -> next ;
}
2002-04-12 11:37:00 +00:00
2002-05-22 14:23:17 +00:00
return d ;
2002-03-06 15:50:14 +00:00
}
- ( id ) copyWithZone : ( NSZone * ) z
{
return RETAIN ( self ) ;
}
2002-11-22 10:47:48 +00:00
/ * *
2003-04-02 04:51:54 +00:00
* Return node content as a string . This should return meaningful
* information for text nodes and for entity nodes containing only
* text nodes . < br / >
* If entity substitution was not enabled during parsing , an
* element containing text may actually contain both text nodes and
* entity reference nodes , in this case you should not use this
* method to get the content of the element , but should examine
* the child nodes of the element individually and perform any
2003-05-12 19:23:02 +00:00
* entity reference you need to do explicitly . < br / >
* NB . There are five standard entities which are automatically
* substituted into the content text rather than appearing as
* entity nodes in their own right . These are ' & lt ; ' , ' & gt ; ' , ' & apos ; ' ,
* ' & quot ; ' and ' & amp ; ' . If you with to receive content in which these
* characters are represented by the original entity escapes , you need
* to use the - escapedContent method .
2002-03-06 15:50:14 +00:00
* /
- ( NSString * ) content
{
2003-04-02 04:51:54 +00:00
xmlNodePtr ptr = ( xmlNodePtr ) lib ;
if ( ptr = = NULL )
2002-03-06 15:50:14 +00:00
{
2003-04-02 04:51:54 +00:00
return nil ;
2002-03-06 15:50:14 +00:00
}
2003-04-02 04:51:54 +00:00
if ( ptr -> content ! = NULL )
2002-03-06 15:50:14 +00:00
{
2003-04-02 04:51:54 +00:00
return UTF8Str ( ptr -> content ) ;
}
2009-02-23 20:42:32 +00:00
if ( ( NSInteger ) ptr -> type = = XML_TEXT _NODE )
2003-04-02 04:51:54 +00:00
{
return @ "" ;
2002-03-06 15:50:14 +00:00
}
2009-02-23 20:42:32 +00:00
else if ( ( NSInteger ) ptr -> type = = XML_ELEMENT _NODE )
2003-04-02 04:51:54 +00:00
{
ptr = ptr -> children ;
if ( ptr ! = NULL )
{
if ( ptr -> next = = NULL )
{
if ( ptr -> content ! = NULL )
{
return UTF8Str ( ptr -> content ) ;
}
}
else
{
NSMutableString * m = [ NSMutableString new ] ;
while ( ptr ! = NULL )
{
if ( ptr -> content ! = NULL )
{
[ m appendString : UTF8Str ( ptr -> content ) ] ;
}
ptr = ptr -> next ;
}
return AUTORELEASE ( m ) ;
}
}
}
return nil ;
2002-03-06 15:50:14 +00:00
}
2002-05-22 16:26:42 +00:00
- ( void ) dealloc
{
RELEASE ( _parent ) ;
[ super dealloc ] ;
}
2003-06-18 10:08:02 +00:00
/ * *
* Returns a string representation of the node and all its children
* ( ie the XML text ) or nil if the node does not have reasonable contents .
* /
- ( NSString * ) description
{
NSString * string = nil ;
xmlOutputBufferPtr buf ;
buf = xmlAllocOutputBuffer ( 0 ) ;
if ( buf ! = 0 )
{
xmlNodeDumpOutput ( buf ,
( ( xmlNodePtr ) ( lib ) ) -> doc ,
( xmlNodePtr ) ( lib ) ,
1 ,
1 ,
"utf-8" ) ;
xmlOutputBufferFlush ( buf ) ;
string = UTF8StrLen ( buf -> buffer -> content , buf -> buffer -> use ) ;
xmlOutputBufferClose ( buf ) ;
}
return string ;
}
2002-05-22 14:23:17 +00:00
/ * *
* Return the document in which this node exists .
* /
- ( GSXMLDocument * ) document
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
if ( ( ( xmlNodePtr ) ( lib ) ) -> doc ! = NULL )
2002-03-06 15:50:14 +00:00
{
2002-05-22 16:26:42 +00:00
GSXMLDocument * d = [ GSXMLDocument alloc ] ;
d = [ d _initFrom : ( ( xmlNodePtr ) ( lib ) ) -> doc parent : self ownsLib : NO ] ;
return AUTORELEASE ( d ) ;
2002-05-22 14:23:17 +00:00
}
else
{
return nil ;
2002-03-06 15:50:14 +00:00
}
}
2003-05-12 19:23:02 +00:00
/ * *
* This performs the same function as the - content method , but retains
2006-03-11 06:46:35 +00:00
* escaped character information ( the standard five entities & amp ; lt ; ,
2004-10-03 09:11:15 +00:00
* & amp ; gt ; , & amp ; apos ; , & amp ; quot ; , and & amp ; amp ; ) which are normally
* replaced with their standard equivalents
* ( & lt ; , & gt ; , & apos ; , & quot ; , and & amp ; ) .
2003-05-12 19:23:02 +00:00
* /
- ( NSString * ) escapedContent
{
NSString * str = [ self content ] ;
2004-10-03 09:11:15 +00:00
return [ str stringByEscapingXML ] ;
2003-05-12 19:23:02 +00:00
}
2002-03-06 15:50:14 +00:00
/ * *
2002-05-22 14:23:17 +00:00
* Return the first attribute in this node .
2002-03-06 15:50:14 +00:00
* /
2002-05-22 14:23:17 +00:00
- ( GSXMLAttribute * ) firstAttribute
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
if ( ( ( xmlNodePtr ) ( lib ) ) -> properties ! = NULL )
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
return AUTORELEASE ( [ [ GSXMLAttribute alloc ]
2002-05-22 16:26:42 +00:00
_initFrom : ( ( xmlNodePtr ) ( lib ) ) -> properties parent : self ] ) ;
2002-03-06 15:50:14 +00:00
}
else
{
return nil ;
}
}
/ * *
2002-05-22 14:23:17 +00:00
* Return the first child element of this node . If you wish to step
* through all children of the node ( including non - element nodes )
* you should use the - firstChild method instead .
2002-03-06 15:50:14 +00:00
* /
2002-05-22 14:23:17 +00:00
- ( GSXMLNode * ) firstChildElement
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
xmlNodePtr ptr = ( ( xmlNodePtr ) lib ) -> children ;
while ( ptr ! = NULL )
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
if ( ptr -> type = = XML_ELEMENT _NODE )
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
n = [ n _initFrom : ptr parent : self ] ;
return AUTORELEASE ( n ) ;
2002-05-22 14:23:17 +00:00
}
ptr = ptr -> next ;
2002-03-06 15:50:14 +00:00
}
2002-05-22 14:23:17 +00:00
return nil ;
2002-03-06 15:50:14 +00:00
}
/ * *
2002-05-22 14:23:17 +00:00
* Return the first child node of this node .
* < example >
* - ( GSXMLNode * ) elementRecursive : ( GSXMLNode * ) node
* {
* while ( node ! = nil )
* {
* if ( [ node type ] = = XML_ELEMENT _NODE )
* {
* return node ;
* }
* if ( [ node firstChild ] ! = nil )
* {
* node = [ self elementRecursive : [ node firstChild ] ] ;
* }
* else
* {
* node = [ node next ] ;
* }
* }
* return node ;
* }
* < / example >
2002-03-06 15:50:14 +00:00
* /
2002-05-22 14:23:17 +00:00
- ( GSXMLNode * ) firstChild
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
if ( ( ( xmlNodePtr ) ( lib ) ) -> children ! = NULL )
2002-03-06 15:50:14 +00:00
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
n = [ n _initFrom : ( ( xmlNodePtr ) ( lib ) ) -> children parent : self ] ;
return AUTORELEASE ( n ) ;
2002-05-22 14:23:17 +00:00
}
else
{
return nil ;
}
}
2009-02-23 20:42:32 +00:00
- ( NSUInteger ) hash
2002-05-22 14:23:17 +00:00
{
2009-02-23 20:42:32 +00:00
return ( ( ( NSUInteger ) ( intptr_t ) lib ) > > 3 ) ;
2002-05-22 14:23:17 +00:00
}
2002-03-06 15:50:14 +00:00
2002-05-22 14:23:17 +00:00
- ( id ) init
{
NSLog ( @ "GSXMLNode: calling -init is not legal" ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-05-22 14:23:17 +00:00
return nil ;
2002-03-06 15:50:14 +00:00
}
2003-07-28 10:53:18 +00:00
/ * *
* Convenience method , equivalent to calling - type and comparing it
* with the result of passing "XML_ELEMENT_NODE" to
* + typeFromDescription : ( but faster ) .
* /
- ( BOOL ) isElement
{
2009-02-23 20:42:32 +00:00
if ( ( NSInteger ) ( ( xmlNodePtr ) ( lib ) ) -> type = = XML_ELEMENT _NODE )
2003-07-28 10:53:18 +00:00
{
return YES ;
}
return NO ;
}
2002-03-12 13:23:27 +00:00
- ( BOOL ) isEqual : ( id ) other
2002-03-06 15:50:14 +00:00
{
if ( [ other isKindOfClass : [ self class ] ] = = YES
&& [ other lib ] = = lib )
{
return YES ;
}
else
{
return NO ;
}
}
2003-07-28 10:53:18 +00:00
/ * *
* Convenience method , equivalent to calling - type and comparing it
* with the result of passing "XML_TEXT_NODE" to
* + typeFromDescription : ( but faster ) .
* /
- ( BOOL ) isText
{
2009-02-23 20:42:32 +00:00
if ( ( NSInteger ) ( ( xmlNodePtr ) ( lib ) ) -> type = = XML_TEXT _NODE )
2003-07-28 10:53:18 +00:00
{
return YES ;
}
return NO ;
}
2002-03-06 15:50:14 +00:00
/ * *
2002-05-22 14:23:17 +00:00
* Returns a pointer to the raw libxml data used by this document . < br / >
* Only for use by libxml experts !
2002-03-06 15:50:14 +00:00
* /
- ( void * ) lib
{
return lib ;
}
2002-05-22 14:23:17 +00:00
/ * *
* Create and return an attribute ( unless the named attribute already exists ,
* in which case we update them value of the existing attribute and return it .
* /
- ( GSXMLAttribute * ) makeAttributeWithName : ( NSString * ) name
value : ( NSString * ) value
{
void * l ;
2005-07-08 11:48:37 +00:00
l = xmlNewProp ( ( xmlNodePtr ) [ self lib ] , UTF8STRING ( name ) , UTF8STRING ( value ) ) ;
2002-05-22 16:26:42 +00:00
return AUTORELEASE ( [ [ GSXMLAttribute alloc ] _initFrom : l parent : self ] ) ;
2002-05-22 14:23:17 +00:00
}
2002-03-06 15:50:14 +00:00
/ * *
* < p >
* Creation of a new child element , added at the end of
* parent children list .
* ns and content parameters are optional ( may be nil ) .
* If content is non nil , a child list containing the
* TEXTs and ENTITY_REFs node will be created .
* Return previous node .
* < / p >
* < example >
*
* GSXMLNode * n1 , * n2 ;
* GSXMLDocument * d , * d1 ;
*
* d = [ GSXMLDocument documentWithVersion : @ "1.0" ] ;
* [ d setRoot : [ d makeNodeWithNamespace : nil
* name : @ "plist"
* content : nil ] ] ;
2002-05-22 14:23:17 +00:00
* [ [ d root ] setObject : @ "0.9" forKey : @ "version" ] ;
2002-03-06 15:50:14 +00:00
* n1 = [ [ d root ] makeChildWithNamespace : nil
* name : @ "dict"
* content : nil ] ;
* [ n1 makeChildWithNamespace : nil name : @ "key" content : @ "Year Of Birth" ] ;
* [ n1 makeChildWithNamespace : nil name : @ "integer" content : @ "65" ] ;
*
* [ n1 makeChildWithNamespace : nil name : @ "key" content : @ "Pets Names" ] ;
* [ n1 makeChildWithNamespace : nil name : @ "array" content : nil ] ;
*
* < / example >
* /
- ( GSXMLNode * ) makeChildWithNamespace : ( GSXMLNamespace * ) ns
name : ( NSString * ) name
content : ( NSString * ) content
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
n = [ n _initFrom :
2005-07-08 11:48:37 +00:00
xmlNewTextChild ( lib , [ ns lib ] , UTF8STRING ( name ) , UTF8STRING ( content ) )
2002-05-22 16:26:42 +00:00
parent : self ] ;
return AUTORELEASE ( n ) ;
2002-05-11 03:06:51 +00:00
}
/ * *
* Creation of a new text element , added at the end of
* parent children list .
* < example >
* d = [ GSXMLDocument documentWithVersion : @ "1.0" ] ;
*
* [ d setRoot : [ d makeNodeWithNamespace : nil name : @ "plist" content : nil ] ] ;
2002-05-22 14:23:17 +00:00
* [ [ d root ] setObject : @ "0.9" forKey : @ "version" ] ;
2002-05-11 03:06:51 +00:00
* n1 = [ [ d root ] makeChildWithNamespace : nil name : @ "dict" content : nil ] ;
* [ n1 makeText : @ " this is a text " ] ;
* < / example >
* /
- ( GSXMLNode * ) makeText : ( NSString * ) content
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
n = [ n _initFrom :
2005-07-08 11:48:37 +00:00
xmlAddChild ( ( xmlNodePtr ) lib , xmlNewText ( UTF8STRING ( content ) ) )
2002-05-22 16:26:42 +00:00
parent : self ] ;
return AUTORELEASE ( n ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Creation of a new comment element , added at the end of
* parent children list .
* < example >
* d = [ GSXMLDocument documentWithVersion : @ "1.0" ] ;
*
* [ d setRoot : [ d makeNodeWithNamespace : nil name : @ "plist" content : nil ] ] ;
2002-05-22 14:23:17 +00:00
* [ [ d root ] setObject : @ "0.9" forKey : @ "version" ] ;
2002-03-06 15:50:14 +00:00
* n1 = [ [ d root ] makeChildWithNamespace : nil name : @ "dict" content : nil ] ;
* [ n1 makeComment : @ " this is a comment " ] ;
* < / example >
* /
- ( GSXMLNode * ) makeComment : ( NSString * ) content
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
n = [ n _initFrom :
2005-07-08 11:48:37 +00:00
xmlAddChild ( ( xmlNodePtr ) lib , xmlNewComment ( UTF8STRING ( content ) ) )
2002-05-22 16:26:42 +00:00
parent : self ] ;
return AUTORELEASE ( n ) ;
2002-03-06 15:50:14 +00:00
}
2002-05-22 14:23:17 +00:00
/ * *
* Create a namespace attached to this node .
* /
- ( GSXMLNamespace * ) makeNamespaceHref : ( NSString * ) href
prefix : ( NSString * ) prefix
{
2002-05-22 16:26:42 +00:00
void * data ;
2005-07-08 11:48:37 +00:00
data = xmlNewNs ( ( xmlNodePtr ) lib , UTF8STRING ( href ) , UTF8STRING ( prefix ) ) ;
2002-05-22 16:26:42 +00:00
if ( data = = NULL )
{
NSLog ( @ "Can't create GSXMLNamespace object" ) ;
return nil ;
}
return AUTORELEASE ( [ [ GSXMLNamespace alloc ] _initFrom : data parent : self ] ) ;
2002-05-22 14:23:17 +00:00
}
2002-03-06 15:50:14 +00:00
/ * *
* Creation of a new process instruction element ,
* added at the end of parent children list .
* < example >
* d = [ GSXMLDocument documentWithVersion : @ "1.0" ] ;
*
* [ d setRoot : [ d makeNodeWithNamespace : nil name : @ "plist" content : nil ] ] ;
2002-05-22 14:23:17 +00:00
* [ [ d root ] setObject : @ "0.9" forKey : @ "version" ] ;
2002-03-06 15:50:14 +00:00
* n1 = [ [ d root ] makeChildWithNamespace : nil name : @ "dict" content : nil ] ;
* [ n1 makeComment : @ " this is a comment " ] ;
* [ n1 makePI : @ "pi1" content : @ "this is a process instruction" ] ;
* < / example >
* /
- ( GSXMLNode * ) makePI : ( NSString * ) name content : ( NSString * ) content
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
n = [ n _initFrom :
2005-07-08 11:48:37 +00:00
xmlAddChild ( ( xmlNodePtr ) lib , xmlNewPI ( UTF8STRING ( name ) ,
UTF8STRING ( content ) ) ) parent : self ] ;
2002-05-22 16:26:42 +00:00
return AUTORELEASE ( n ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Return the node - name
* /
- ( NSString * ) name
{
if ( lib ! = NULL && ( ( xmlNodePtr ) lib ) -> name ! = NULL )
{
return UTF8Str ( ( ( xmlNodePtr ) lib ) -> name ) ;
}
else
{
return nil ;
}
}
/ * *
2002-04-12 11:10:37 +00:00
* Return the next node at this level . This method can return any type
* of node , and it may be more convenient to use the - nextElement node
* if you are parsing a document where you wish to ignore non - element
* nodes such as whitespace text separating elements .
2002-03-06 15:50:14 +00:00
* /
- ( GSXMLNode * ) next
{
if ( ( ( xmlNodePtr ) ( lib ) ) -> next ! = NULL )
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
2003-08-07 18:22:03 +00:00
n = [ n _initFrom : ( ( xmlNodePtr ) ( lib ) ) -> next parent : _parent ] ;
2002-05-22 16:26:42 +00:00
return AUTORELEASE ( n ) ;
2002-03-06 15:50:14 +00:00
}
else
{
return nil ;
}
}
2002-04-12 11:10:37 +00:00
/ * *
2005-11-06 13:53:40 +00:00
* Returns the next element node , skipping past any other node types
2002-04-12 11:10:37 +00:00
* ( such as text nodes ) . If there is no element node to be returned ,
2002-11-22 10:47:48 +00:00
* this method returns nil . < br / >
* NB . This method is not available in java , as the method name conflicts
* with that of java ' s Enumerator class .
2002-04-12 11:10:37 +00:00
* /
- ( GSXMLNode * ) nextElement
{
2002-04-12 11:27:51 +00:00
xmlNodePtr ptr = ( xmlNodePtr ) lib ;
2002-04-12 11:10:37 +00:00
while ( ptr -> next ! = NULL )
{
2002-04-12 11:27:51 +00:00
ptr = ptr -> next ;
2002-04-12 11:10:37 +00:00
if ( ptr -> type = = XML_ELEMENT _NODE )
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
2003-08-07 18:22:03 +00:00
n = [ n _initFrom : ptr parent : _parent ] ;
2002-05-22 16:26:42 +00:00
return AUTORELEASE ( n ) ;
2002-04-12 11:10:37 +00:00
}
}
return nil ;
}
2002-03-06 15:50:14 +00:00
/ * *
* Return the namespace of the node .
* /
2002-05-22 14:23:17 +00:00
- ( GSXMLNamespace * ) namespace
2002-03-06 15:50:14 +00:00
{
if ( lib ! = NULL && ( ( xmlNodePtr ) ( lib ) ) -> ns ! = NULL )
{
2002-05-22 16:26:42 +00:00
GSXMLNamespace * ns = [ GSXMLNamespace alloc ] ;
ns = [ ns _initFrom : ( ( xmlNodePtr ) ( lib ) ) -> ns parent : self ] ;
return AUTORELEASE ( ns ) ;
2002-03-06 15:50:14 +00:00
}
else
{
return nil ;
}
}
/ * *
* Return namespace definitions for the node
* /
2002-05-22 14:23:17 +00:00
- ( GSXMLNamespace * ) namespaceDefinitions
2002-03-06 15:50:14 +00:00
{
if ( lib ! = NULL && ( ( xmlNodePtr ) lib ) -> nsDef ! = NULL )
{
2002-05-22 16:26:42 +00:00
GSXMLNamespace * ns = [ GSXMLNamespace alloc ] ;
ns = [ ns _initFrom : ( ( xmlNodePtr ) ( lib ) ) -> nsDef parent : self ] ;
return AUTORELEASE ( ns ) ;
2002-03-06 15:50:14 +00:00
}
else
{
return nil ;
}
}
/ * *
2002-05-22 14:23:17 +00:00
* Return the attribute value for the specified key .
2002-03-06 15:50:14 +00:00
* /
2002-05-22 14:23:17 +00:00
- ( NSString * ) objectForKey : ( NSString * ) key
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
NSString * value = nil ;
xmlAttrPtr prop ;
prop = ( ( xmlNodePtr ) ( lib ) ) -> properties ;
while ( prop ! = NULL )
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
const void * name = prop -> name ;
NSString * n = UTF8Str ( name ) ;
if ( [ key isEqualToString : n ] = = YES )
{
2002-10-12 08:20:49 +00:00
xmlNodePtr child = prop -> children ;
2002-05-22 14:23:17 +00:00
2002-10-12 08:20:49 +00:00
while ( child ! = NULL )
{
const void * content = child -> content ;
if ( value = = nil )
{
value = UTF8Str ( content ) ;
}
else
{
value = [ value stringByAppendingString : UTF8Str ( content ) ] ;
}
child = child -> next ;
2002-05-22 14:23:17 +00:00
}
break ;
}
prop = prop -> next ;
2002-10-12 08:20:49 +00:00
}
2002-05-22 14:23:17 +00:00
return value ;
2002-03-06 15:50:14 +00:00
}
/ * *
2002-05-22 14:23:17 +00:00
* Return the parent of this node .
2002-03-06 15:50:14 +00:00
* /
2002-05-22 14:23:17 +00:00
- ( GSXMLNode * ) parent
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
if ( ( ( xmlNodePtr ) ( lib ) ) -> parent ! = NULL )
2002-03-06 15:50:14 +00:00
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
n = [ n _initFrom : ( ( xmlNodePtr ) ( lib ) ) -> parent parent : self ] ;
return AUTORELEASE ( n ) ;
2002-03-06 15:50:14 +00:00
}
else
{
return nil ;
}
}
/ * *
2002-05-22 14:23:17 +00:00
* Return the previous node at this level .
2002-03-06 15:50:14 +00:00
* /
2002-05-22 14:23:17 +00:00
- ( GSXMLNode * ) previous
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
if ( ( ( xmlNodePtr ) ( lib ) ) -> prev ! = NULL )
2002-03-06 15:50:14 +00:00
{
2002-05-22 16:26:42 +00:00
GSXMLNode * n = [ GSXMLNode alloc ] ;
2003-08-07 18:22:03 +00:00
n = [ n _initFrom : ( ( xmlNodePtr ) ( lib ) ) -> prev parent : _parent ] ;
2002-05-22 16:26:42 +00:00
return AUTORELEASE ( n ) ;
2002-03-06 15:50:14 +00:00
}
else
{
return nil ;
}
}
2002-09-25 15:32:11 +00:00
/ * *
2002-11-22 10:47:48 +00:00
* Return the previous element node at this level . < br / >
* NB . This method is not available in java , as the method name conflicts
* with that of java ' s Enumerator class .
2002-09-25 15:32:11 +00:00
* /
- ( GSXMLNode * ) previousElement
{
xmlNodePtr ptr = ( xmlNodePtr ) lib ;
while ( ptr -> prev ! = NULL )
{
ptr = ptr -> prev ;
if ( ptr -> type = = XML_ELEMENT _NODE )
{
GSXMLNode * n = [ GSXMLNode alloc ] ;
2003-08-07 18:22:03 +00:00
n = [ n _initFrom : ptr parent : _parent ] ;
2002-09-25 15:32:11 +00:00
return AUTORELEASE ( n ) ;
}
}
return nil ;
}
2002-03-06 15:50:14 +00:00
/ * *
* < p >
* Return attributes and values as a dictionary , but applies
* the specified selector to each key before adding the
* key and value to the dictionary . The selector must be a
* method of NSString taking no arguments and returning an
* object suitable for use as a dictionary key .
* < / p >
* < p >
* This method exists for the use of GSWeb . . . it is probably
* not of much use elsewhere .
* < / p >
* /
- ( NSMutableDictionary * ) propertiesAsDictionaryWithKeyTransformationSel :
( SEL ) keyTransformSel
{
xmlAttrPtr prop ;
NSMutableDictionary * d = [ NSMutableDictionary dictionary ] ;
prop = ( ( xmlNodePtr ) ( lib ) ) -> properties ;
while ( prop ! = NULL )
{
2002-10-12 08:20:49 +00:00
xmlNodePtr child = prop -> children ;
2002-03-06 15:50:14 +00:00
const void * name = prop -> name ;
NSString * key = UTF8Str ( name ) ;
2002-10-12 08:20:49 +00:00
NSString * value = @ "" ;
2002-03-06 15:50:14 +00:00
if ( keyTransformSel ! = 0 )
{
key = [ key performSelector : keyTransformSel ] ;
}
2002-10-12 08:20:49 +00:00
while ( child ! = NULL )
2002-03-06 15:50:14 +00:00
{
2002-10-12 08:20:49 +00:00
const void * content = child -> content ;
2002-03-06 15:50:14 +00:00
2002-10-12 08:20:49 +00:00
value = [ value stringByAppendingString : UTF8Str ( content ) ] ;
child = child -> next ;
2002-03-06 15:50:14 +00:00
}
2002-10-12 08:20:49 +00:00
[ d setObject : value forKey : key ] ;
2002-03-06 15:50:14 +00:00
prop = prop -> next ;
2002-10-12 08:20:49 +00:00
}
2002-03-06 15:50:14 +00:00
return d ;
}
/ * *
* Set ( or reset ) an attribute carried by a node .
* < example >
2002-05-22 14:23:17 +00:00
* [ n1 setObject : @ "prop1" forKey : @ "name1" ] ;
* [ n1 setObject : @ "prop2" forKey : @ "name2" ] ;
* [ n1 setObject : @ "prop3" forKey : @ "name3" ] ;
2002-03-06 15:50:14 +00:00
* < / example >
* /
2002-05-22 14:23:17 +00:00
- ( void ) setObject : ( NSString * ) value forKey : ( NSString * ) key
2002-03-06 15:50:14 +00:00
{
2005-07-08 11:48:37 +00:00
xmlSetProp ( lib , UTF8STRING ( key ) , UTF8STRING ( value ) ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
2002-11-22 10:47:48 +00:00
* Return node - type . The most efficient way of testing node types is to
* use this method and compare the return value with a value you previously
* obtained using the + typeFromDescription : method .
2002-03-06 15:50:14 +00:00
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) type
2002-03-06 15:50:14 +00:00
{
2009-02-23 20:42:32 +00:00
return ( NSInteger ) ( ( xmlNodePtr ) ( lib ) ) -> type ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Return node type as a string .
* /
- ( NSString * ) typeDescription
{
2006-01-10 10:29:11 +00:00
NSString * desc ;
2002-03-06 15:50:14 +00:00
2006-01-10 10:29:11 +00:00
desc = ( NSString * ) NSMapGet ( nodeNames , ( void * ) ( intptr_t ) [ self type ] ) ;
2002-03-06 15:50:14 +00:00
if ( desc = = nil )
{
desc = @ "Unknown node type" ;
}
return desc ;
}
2002-08-08 13:10:16 +00:00
/ * *
* Sets the namespace of the receiver to the value specified . < br / >
* Supplying a nil namespace removes any namespace previously set
* or any namespace that the node inherited from a parent when it
* was created .
* /
2002-07-29 19:37:40 +00:00
- ( void ) setNamespace : ( GSXMLNamespace * ) space
{
2005-02-22 11:22:44 +00:00
xmlSetNs ( lib , [ space lib ] ) ;
2002-07-29 19:37:40 +00:00
}
2002-03-06 15:50:14 +00:00
@ end
@ implementation GSXMLNode ( GSPrivate )
/ * *
2002-05-22 14:23:17 +00:00
* Initialise from raw libxml data
2002-03-06 15:50:14 +00:00
* /
2002-05-22 16:26:42 +00:00
- ( id ) _initFrom : ( void * ) data parent : ( id ) p
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
if ( data = = NULL )
2002-03-06 15:50:14 +00:00
{
2002-05-22 14:23:17 +00:00
NSLog ( @ "%@ - no data for initialization" ,
NSStringFromClass ( [ self class ] ) ) ;
DESTROY ( self ) ;
2002-03-06 15:50:14 +00:00
return nil ;
}
2002-05-22 14:23:17 +00:00
lib = data ;
2002-05-22 16:26:42 +00:00
ASSIGN ( _parent , p ) ;
2002-05-22 14:23:17 +00:00
return self ;
2002-03-06 15:50:14 +00:00
}
@ end
/ * *
* < p >
* The XML parser object is the pivotal part of parsing an XML
* document - it will either build a tree representing the
* document ( if initialized without a GSSAXHandler ) , or will
* cooperate with a GSSAXHandler object to provide parsing
* without the overhead of building a tree .
* < / p >
* < p >
* The parser may be initialized with an input source ( in which
* case it will expect to be asked to parse the entire input in
* a single operation ) , or without . If it is initialised without
* an input source , incremental parsing can be done by feeding
* successive parts of the XML document into the parser as
* NSData objects .
* < / p >
* /
2002-05-26 17:05:46 +00:00
@ implementation GSXMLParser
2002-03-06 15:50:14 +00:00
2010-02-16 19:51:52 +00:00
/ * To override location for DTDs
* /
static NSString * dtdPath = nil ;
2002-03-06 15:50:14 +00:00
static NSString * endMarker = @ "At end of incremental parse" ;
+ ( void ) initialize
{
2003-08-08 14:55:23 +00:00
static BOOL beenHere = NO ;
if ( beenHere = = NO )
{
beenHere = YES ;
if ( cacheDone = = NO )
setupCache ( ) ;
}
2002-03-06 15:50:14 +00:00
}
/ * *
* < p >
* This method controls the loading of external entities into
* the system . If it returns an empty string , the entity is not
* loaded . If it returns a filename , the entity is loaded from
* that file . If it returns nil , the default entity loading
* mechanism is used .
* < / p >
* < p >
* The default entity loading mechanism is to construct a file
* name from the locationURL , by replacing all path separators
* with underscores , then attempt to locate that file in the DTDs
* resource directory of the main bundle , and all the standard
* system locations .
* < / p >
* < p >
* As a special case , the default loader examines the publicID
* and if it is a GNUstep DTD , the loader constructs a special
* name from the ID ( by replacing dots with underscores and
* spaces with hyphens ) and looks for a file with that name
* and a ' . dtd ' extension in the GNUstep bundles .
* < / p >
* < p >
* NB . This method will only be called if there is no SAX
* handler in use , or if the corresponding method in the
* SAX handler returns nil .
* < / p >
* /
+ ( NSString * ) loadEntity : ( NSString * ) publicId
at : ( NSString * ) location
{
return nil ;
}
/ * *
* Creation of a new Parser ( for incremental parsing )
* by calling - initWithSAXHandler :
* /
+ ( GSXMLParser * ) parser
{
return AUTORELEASE ( [ [ self alloc ] initWithSAXHandler : nil ] ) ;
}
/ * *
* Creation of a new Parser by calling
* - initWithSAXHandler : withContentsOfFile :
* < example >
* GSXMLParser * p = [ GSXMLParser parserWithContentsOfFile : @ "macos.xml" ] ;
*
* if ( [ p parse ] )
* {
2002-11-22 10:47:48 +00:00
* [ [ p document ] dump ] ;
2002-03-06 15:50:14 +00:00
* }
* else
* {
* printf ( "error parse file\n" ) ;
* }
* < / example >
* /
+ ( GSXMLParser * ) parserWithContentsOfFile : ( NSString * ) path
{
return AUTORELEASE ( [ [ self alloc ] initWithSAXHandler : nil
withContentsOfFile : path ] ) ;
}
/ * *
* Creation of a new Parser by calling
* - initWithSAXHandler : withContentsOfURL :
* /
+ ( GSXMLParser * ) parserWithContentsOfURL : ( NSURL * ) url
{
return AUTORELEASE ( [ [ self alloc ] initWithSAXHandler : nil
withContentsOfURL : url ] ) ;
}
/ * *
* Creation of a new Parser by calling
* - initWithSAXHandler : withData :
* /
+ ( GSXMLParser * ) parserWithData : ( NSData * ) data
{
return AUTORELEASE ( [ [ self alloc ] initWithSAXHandler : nil
withData : data ] ) ;
}
/ * *
* < p >
* Creation of a new Parser by calling - initWithSAXHandler :
* < / p >
* < p >
* If the handler object supplied is nil , the parser will build
* a tree representing the parsed file rather than attempting
* to get the handler to deal with the parsed elements and entities .
* < / p >
* /
+ ( GSXMLParser * ) parserWithSAXHandler : ( GSSAXHandler * ) handler
{
return AUTORELEASE ( [ [ self alloc ] initWithSAXHandler : handler ] ) ;
}
/ * *
* Creation of a new Parser by calling
* - initWithSAXHandler : withContentsOfFile :
* < example >
* CREATE_AUTORELEASE _POOL ( arp ) ;
* GSSAXHandler * h = [ GSDebugSAXHandler handler ] ;
* GSXMLParser * p = [ GSXMLParser parserWithSAXHandler : h
* withContentsOfFile : @ "macos.xml" ] ;
* if ( [ p parse ] )
* {
* printf ( "ok\n" ) ;
* }
* RELEASE ( arp ) ;
* < / example >
* /
+ ( GSXMLParser * ) parserWithSAXHandler : ( GSSAXHandler * ) handler
withContentsOfFile : ( NSString * ) path
{
return AUTORELEASE ( [ [ self alloc ] initWithSAXHandler : handler
withContentsOfFile : path ] ) ;
}
/ * *
* Creation of a new Parser by calling
* - initWithSAXHandler : withContentsOfURL :
* /
+ ( GSXMLParser * ) parserWithSAXHandler : ( GSSAXHandler * ) handler
withContentsOfURL : ( NSURL * ) url
{
return AUTORELEASE ( [ [ self alloc ] initWithSAXHandler : handler
withContentsOfURL : url ] ) ;
}
/ * *
* Creation of a new Parser by calling
* - initWithSAXHandler : withData :
* /
+ ( GSXMLParser * ) parserWithSAXHandler : ( GSSAXHandler * ) handler
withData : ( NSData * ) data
{
return AUTORELEASE ( [ [ self alloc ] initWithSAXHandler : handler
withData : data ] ) ;
}
2010-02-16 19:51:52 +00:00
/ * * Sets a directory in which to look for DTDs when resolving external
* references . Can be used whjen DTDs have not been installed in the
* normal locatioons .
* /
+ ( void ) setDTDs : ( NSString * ) aPath
{
ASSIGNCOPY ( dtdPath , aPath ) ;
}
2002-03-06 15:50:14 +00:00
/ * *
* Return the name of the string encoding ( for XML ) to use for the
* specified OpenStep encoding .
* /
+ ( NSString * ) xmlEncodingStringForStringEncoding : ( NSStringEncoding ) encoding
{
NSString * xmlEncodingString = nil ;
switch ( encoding )
{
case NSUnicodeStringEncoding :
NSLog ( @ "NSUnicodeStringEncoding not supported for XML" ) ; // ? ?
break ;
case NSNEXTSTEPStringEncoding :
NSLog ( @ "NSNEXTSTEPStringEncoding not supported for XML" ) ; // ? ?
break ;
case NSJapaneseEUCStringEncoding :
xmlEncodingString = @ "EUC-JP" ;
break ;
case NSShiftJISStringEncoding :
xmlEncodingString = @ "Shift-JIS" ;
break ;
case NSISO2022JPStringEncoding :
xmlEncodingString = @ "ISO-2022-JP" ;
break ;
case NSUTF8StringEncoding :
xmlEncodingString = @ "UTF-8" ;
break ;
case NSWindowsCP1251StringEncoding :
NSLog ( @ "NSWindowsCP1251StringEncoding not supported for XML" ) ; // ? ?
break ;
case NSWindowsCP1252StringEncoding :
NSLog ( @ "NSWindowsCP1252StringEncoding not supported for XML" ) ; // ? ?
break ;
case NSWindowsCP1253StringEncoding :
NSLog ( @ "NSWindowsCP1253StringEncoding not supported for XML" ) ; // ? ?
break ;
case NSWindowsCP1254StringEncoding :
NSLog ( @ "NSWindowsCP1254StringEncoding not supported for XML" ) ; // ? ?
break ;
case NSWindowsCP1250StringEncoding :
NSLog ( @ "NSWindowsCP1250StringEncoding not supported for XML" ) ; // ? ?
break ;
case NSISOLatin1StringEncoding :
xmlEncodingString = @ "ISO-8859-1" ;
break ;
case NSISOLatin2StringEncoding :
xmlEncodingString = @ "ISO-8859-2" ;
break ;
case NSSymbolStringEncoding :
NSLog ( @ "NSSymbolStringEncoding not supported for XML" ) ; // ? ?
break ;
default :
2010-02-26 09:03:46 +00:00
NSLog ( @ "Encoding not supported for XML" ) ; // ? ?
2002-03-06 15:50:14 +00:00
xmlEncodingString = nil ;
break ;
}
return xmlEncodingString ;
}
2004-10-24 12:29:31 +00:00
/ * *
* If called by a SAX callback routine , this method will terminate
* the parsiong process .
* /
- ( void ) abortParsing
{
if ( lib ! = NULL )
{
xmlParserCtxtPtr ctxt = ( xmlParserCtxtPtr ) lib ;
// Stop SAX callbacks
ctxt -> disableSAX = 1 ;
// Stop incoming data being parsed .
ctxt -> instate = XML_PARSER _EOF ;
// Pretend we are at end of file ( nul byte ) .
2005-07-08 11:48:37 +00:00
if ( ctxt -> input ! = NULL ) ctxt -> input -> cur = ( const unsigned char * ) "" ;
2004-10-24 12:29:31 +00:00
}
}
2004-05-18 09:55:33 +00:00
/ * *
* If executed during a parse operation , returns the current column number .
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) columnNumber
2004-05-18 09:55:33 +00:00
{
return xmlSAX2GetColumnNumber ( lib ) ;
}
2002-03-06 15:50:14 +00:00
- ( void ) dealloc
{
2003-05-22 17:00:03 +00:00
RELEASE ( messages ) ;
2002-03-06 15:50:14 +00:00
RELEASE ( src ) ;
RELEASE ( saxHandler ) ;
if ( lib ! = NULL )
{
xmlFreeDoc ( ( ( xmlParserCtxtPtr ) lib ) -> myDoc ) ;
xmlFreeParserCtxt ( lib ) ;
}
[ super dealloc ] ;
}
/ * *
* Sets whether the document needs to be validated .
* /
- ( BOOL ) doValidityChecking : ( BOOL ) yesno
{
2004-05-18 09:55:33 +00:00
BOOL old ;
2002-03-06 15:50:14 +00:00
2004-05-18 09:55:33 +00:00
old = ( ( ( xmlParserCtxtPtr ) lib ) -> validate ) ? YES : NO ;
( ( xmlParserCtxtPtr ) lib ) -> validate = ( yesno ? 1 : 0 ) ;
return old ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Return the document produced as a result of parsing data .
* /
2002-05-22 14:23:17 +00:00
- ( GSXMLDocument * ) document
2002-03-06 15:50:14 +00:00
{
2002-05-22 16:26:42 +00:00
GSXMLDocument * d = [ GSXMLDocument alloc ] ;
d = [ d _initFrom : ( ( xmlParserCtxtPtr ) lib ) -> myDoc parent : self ownsLib : NO ] ;
return AUTORELEASE ( d ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Return error code for last parse operation .
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) errNo
2002-03-06 15:50:14 +00:00
{
return ( ( xmlParserCtxtPtr ) lib ) -> errNo ;
}
/ * *
* Sets whether warnings are generated .
* /
- ( BOOL ) getWarnings : ( BOOL ) yesno
{
2006-02-27 16:54:36 +00:00
BOOL old = ( ( ( xmlParserCtxtPtr ) lib ) -> vctxt . warning ) ? YES : NO ;
2003-08-08 14:55:23 +00:00
2006-02-27 16:54:36 +00:00
if ( yesno = = YES )
2003-08-08 14:55:23 +00:00
{
2006-02-27 16:54:36 +00:00
( ( xmlParserCtxtPtr ) lib ) -> vctxt . warning = xmlParserValidityWarning ;
2003-08-08 14:55:23 +00:00
}
2006-02-27 16:54:36 +00:00
else
2003-08-08 14:55:23 +00:00
{
2006-02-27 16:54:36 +00:00
( ( xmlParserCtxtPtr ) lib ) -> vctxt . warning = 0 ;
2003-08-08 14:55:23 +00:00
}
2006-02-27 16:54:36 +00:00
2003-08-08 14:55:23 +00:00
return old ;
2002-03-06 15:50:14 +00:00
}
2002-09-25 15:52:01 +00:00
/ * *
* Initialises by calling - initWithSAXHandler : with a nil argument .
* /
- ( id ) init
{
return [ self initWithSAXHandler : nil ] ;
}
2003-05-22 17:00:03 +00:00
/ * * < init / >
2002-03-06 15:50:14 +00:00
* < p >
2003-05-22 17:00:03 +00:00
* Initialisation of a new Parser with SAX handler .
2002-03-06 15:50:14 +00:00
* < / p >
* < p >
2003-05-22 17:00:03 +00:00
* If the handler object supplied is nil , the parser will use
* an instance of [ GSTreeSAXHandler ] to build a tree representing
* the parsed file . This tree will then be available ( via the - document
* method ) as a [ GSXMLDocument ] on completion of parsing .
2002-03-06 15:50:14 +00:00
* < / p >
* < p >
* The source for the parsing process is not specified - so
* parsing must be done incrementally by feeding data to the
* parser .
* < / p >
* /
- ( id ) initWithSAXHandler : ( GSSAXHandler * ) handler
{
2003-05-22 17:00:03 +00:00
if ( handler = = nil )
{
saxHandler = [ GSTreeSAXHandler new ] ;
}
else if ( [ handler isKindOfClass : [ GSSAXHandler class ] ] = = YES )
{
saxHandler = RETAIN ( handler ) ;
}
else
2002-03-06 15:50:14 +00:00
{
NSLog ( @ "Bad GSSAXHandler object passed to GSXMLParser initialiser" ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-03-06 15:50:14 +00:00
return nil ;
}
[ saxHandler _setParser : self ] ;
if ( [ self _initLibXML ] = = NO )
{
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-03-06 15:50:14 +00:00
return nil ;
}
return self ;
}
/ * *
* < p >
* Initialisation of a new Parser with SAX handler ( if not nil )
* by calling - initWithSAXHandler :
* < / p >
* < p >
* Sets the input source for the parser to be the specified file -
* so parsing of the entire file will be performed rather than
* incremental parsing .
* < / p >
* /
- ( id ) initWithSAXHandler : ( GSSAXHandler * ) handler
withContentsOfFile : ( NSString * ) path
{
2003-07-11 18:53:48 +00:00
if ( path = = nil || [ path isKindOfClass : NSString_class ] = = NO )
2002-03-06 15:50:14 +00:00
{
2002-08-29 09:18:18 +00:00
NSLog ( @ "Bad file path passed to initialize GSXMLParser" ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-08-29 09:18:18 +00:00
return nil ;
2002-03-06 15:50:14 +00:00
}
2002-08-29 09:18:18 +00:00
src = [ path copy ] ;
self = [ self initWithSAXHandler : handler ] ;
2002-03-06 15:50:14 +00:00
return self ;
}
/ * *
* < p >
* Initialisation of a new Parser with SAX handler ( if not nil )
* by calling - initWithSAXHandler :
* < / p >
* < p >
* Sets the input source for the parser to be the specified URL -
* so parsing of the entire document will be performed rather than
* incremental parsing .
* < / p >
* /
- ( id ) initWithSAXHandler : ( GSSAXHandler * ) handler
withContentsOfURL : ( NSURL * ) url
{
2002-08-29 09:18:18 +00:00
if ( url = = nil || [ url isKindOfClass : [ NSURL class ] ] = = NO )
2002-03-06 15:50:14 +00:00
{
2002-08-29 09:18:18 +00:00
NSLog ( @ "Bad NSURL passed to initialize GSXMLParser" ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-08-29 09:18:18 +00:00
return nil ;
2002-03-06 15:50:14 +00:00
}
2002-08-29 09:18:18 +00:00
src = [ url copy ] ;
self = [ self initWithSAXHandler : handler ] ;
2002-03-06 15:50:14 +00:00
return self ;
}
/ * *
* < p >
* Initialisation of a new Parser with SAX handler ( if not nil )
* by calling - initWithSAXHandler :
* < / p >
* < p >
* Sets the input source for the parser to be the specified data
* object ( which must contain an XML document ) , so parsing of the
* entire document will be performed rather than incremental parsing .
* < / p >
* /
- ( id ) initWithSAXHandler : ( GSSAXHandler * ) handler
withData : ( NSData * ) data
{
2002-08-29 09:18:18 +00:00
if ( data = = nil || [ data isKindOfClass : [ NSData class ] ] = = NO )
2002-03-06 15:50:14 +00:00
{
2002-08-29 09:18:18 +00:00
NSLog ( @ "Bad NSData passed to initialize GSXMLParser" ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-08-29 09:18:18 +00:00
return nil ;
2002-03-06 15:50:14 +00:00
}
2002-08-29 09:18:18 +00:00
src = [ data copy ] ;
self = [ self initWithSAXHandler : handler ] ;
2002-03-06 15:50:14 +00:00
return self ;
}
/ * *
* Set and return the previous value for blank text nodes support .
2002-11-04 15:39:43 +00:00
* ignorableWhitespace nodes are only generated when running
2002-03-06 15:50:14 +00:00
* the parser in validating mode and when the current element
* doesn ' t allow CDATA or mixed content .
* /
- ( BOOL ) keepBlanks : ( BOOL ) yesno
{
2004-05-18 09:55:33 +00:00
BOOL old ;
old = ( ( ( xmlParserCtxtPtr ) lib ) -> keepBlanks ) ? YES : NO ;
( ( xmlParserCtxtPtr ) lib ) -> keepBlanks = ( yesno ? 1 : 0 ) ;
return old ;
}
/ * *
* If executed during a parse operation , returns the current line number .
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) lineNumber
2004-05-18 09:55:33 +00:00
{
return xmlSAX2GetLineNumber ( lib ) ;
}
2002-03-06 15:50:14 +00:00
2004-05-18 09:55:33 +00:00
/ * *
* Returns the string into which warning and error messages are saved ,
* or nil if they are being written to stderr .
* /
- ( NSString * ) messages
{
return messages ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Parse source . Return YES if parsed , otherwise NO .
* This method should be called once to parse the entire document .
* < example >
* GSXMLParser * p = [ GSXMLParser parserWithContentsOfFile : @ "macos.xml" ] ;
*
* if ( [ p parse ] )
* {
* [ [ p doc ] dump ] ;
* }
* else
* {
* printf ( "error parse file\n" ) ;
* }
* < / example >
* /
- ( BOOL ) parse
{
id tmp ;
if ( src = = endMarker )
{
NSLog ( @ "GSXMLParser -parse called on object that is already parsed" ) ;
return NO ;
}
if ( src = = nil )
{
NSLog ( @ "GSXMLParser -parse called on object with no source" ) ;
return NO ;
}
if ( [ src isKindOfClass : [ NSData class ] ] )
{
}
else if ( [ src isKindOfClass : NSString_class ] )
{
NSData * data = [ NSData dataWithContentsOfFile : src ] ;
if ( data = = nil )
{
NSLog ( @ "File to parse (%@) is not readable" , src ) ;
return NO ;
}
ASSIGN ( src , data ) ;
}
else if ( [ src isKindOfClass : [ NSURL class ] ] )
{
NSData * data = [ src resourceDataUsingCache : YES ] ;
if ( data = = nil )
{
NSLog ( @ "URL to parse (%@) is not readable" , src ) ;
return NO ;
}
ASSIGN ( src , data ) ;
}
else
{
NSLog ( @ "source for [-parse] must be NSString, NSData or NSURL type" ) ;
return NO ;
}
tmp = RETAIN ( src ) ;
ASSIGN ( src , endMarker ) ;
[ self _parseChunk : tmp ] ;
[ self _parseChunk : nil ] ;
RELEASE ( tmp ) ;
if ( ( ( xmlParserCtxtPtr ) lib ) -> wellFormed )
return YES ;
else
return NO ;
}
/ * *
* < p >
* Pass data to the parser for incremental parsing . This method
* should be called many times , with each call passing another
* block of data from the same document . After the whole of the
* document has been parsed , the method should be called with
* an empty or nil data object to indicate end of parsing .
* On this final call , the return value indicates whether the
* document was valid or not .
* < / p >
* < example >
* GSXMLParser * p = [ GSXMLParser parserWithSAXHandler : nil source : nil ] ;
*
* while ( ( data = getMoreData ( ) ) ! = nil )
* {
* if ( [ p parse : data ] = = NO )
* {
* NSLog ( @ "parse error" ) ;
* }
* }
* // Do something with document parsed
* [ p parse : nil ] ; // Completed parsing of document .
* < / example >
* /
- ( BOOL ) parse : ( NSData * ) data
{
if ( src = = endMarker )
{
NSLog ( @ "GSXMLParser -parse: called on object that is fully parsed" ) ;
return NO ;
}
if ( src ! = nil )
{
NSLog ( @ "XMLParser -parse: called for parser not initialised with nil" ) ;
return NO ;
}
if ( data = = nil || [ data length ] = = 0 )
{
/ *
* At end of incremental parse .
* /
if ( lib ! = NULL )
{
2003-08-08 14:55:23 +00:00
[ self _parseChunk : nil ] ;
2002-03-06 15:50:14 +00:00
src = endMarker ;
if ( ( ( xmlParserCtxtPtr ) lib ) -> wellFormed )
return YES ;
else
return NO ;
}
else
{
NSLog ( @ "GSXMLParser -parse: terminated with no data" ) ;
return NO ;
}
}
else
{
[ self _parseChunk : data ] ;
return YES ;
}
}
2004-05-18 09:55:33 +00:00
/ * *
* Return the public ID of the document being parsed .
* /
- ( NSString * ) publicID
{
return UTF8Str ( xmlSAX2GetPublicId ( lib ) ) ;
}
2003-05-22 17:00:03 +00:00
/ * *
* Sets up ( or removes ) a mutable string to which error and warning
* messages are saved . Using an argument of NO will cause these messages
* to be written to stderr ( the default ) . < br / >
* NB . A SAX handler which overrides the error and warning logging
* messages may stop this mechanism operating .
* /
- ( void ) saveMessages : ( BOOL ) yesno
{
if ( yesno = = YES )
{
ASSIGN ( messages , [ NSMutableString stringWithCapacity : 256 ] ) ;
}
else
{
DESTROY ( messages ) ;
}
}
2002-03-06 15:50:14 +00:00
/ * *
* Set and return the previous value for entity support .
* Initially the parser always keeps entity references instead
* of substituting entity values in the output .
* /
- ( BOOL ) substituteEntities : ( BOOL ) yesno
{
2004-05-18 09:55:33 +00:00
BOOL old ;
2002-03-06 15:50:14 +00:00
2004-05-18 09:55:33 +00:00
old = ( ( ( xmlParserCtxtPtr ) lib ) -> replaceEntities ) ? YES : NO ;
( ( xmlParserCtxtPtr ) lib ) -> replaceEntities = ( yesno ? 1 : 0 ) ;
return old ;
}
2003-01-31 17:23:15 +00:00
2004-05-18 09:55:33 +00:00
/ * *
* Return the system ID of the document being parsed .
* /
- ( NSString * ) systemID
{
return UTF8Str ( xmlSAX2GetSystemId ( lib ) ) ;
2002-03-06 15:50:14 +00:00
}
/ *
* Private methods - internal use only .
* /
- ( BOOL ) _initLibXML
{
2005-07-08 11:48:37 +00:00
const char * file ;
2002-08-29 09:18:18 +00:00
2003-07-11 18:53:48 +00:00
if ( [ src isKindOfClass : NSString_class ] )
2002-08-29 09:18:18 +00:00
{
file = [ src lossyCString ] ;
}
else if ( [ src isKindOfClass : [ NSURL class ] ] )
{
file = [ [ src absoluteString ] lossyCString ] ;
}
else
{
file = "." ;
}
lib = ( void * ) xmlCreatePushParserCtxt ( [ saxHandler lib ] , NULL , 0 , 0 , file ) ;
2002-03-06 15:50:14 +00:00
if ( lib = = NULL )
{
NSLog ( @ "Failed to create libxml parser context" ) ;
return NO ;
}
else
{
/ *
* Put saxHandler address in _private member , so we can retrieve
2002-05-11 03:06:51 +00:00
* the GSSAXHandler to use in our SAX C Functions .
2002-03-06 15:50:14 +00:00
* /
2002-05-04 05:39:48 +00:00
( ( xmlParserCtxtPtr ) lib ) -> _private = saxHandler ;
2006-02-27 16:54:36 +00:00
/ *
* Set the entity loading function for this parser to be our one .
* /
( ( xmlParserCtxtPtr ) lib ) -> sax -> resolveEntity = loadEntityFunction ;
2002-03-06 15:50:14 +00:00
}
return YES ;
}
2003-05-22 19:02:38 +00:00
- ( NSMutableString * ) _messages
{
return messages ;
}
2003-08-08 14:55:23 +00:00
// nil data allowed
2002-03-06 15:50:14 +00:00
- ( void ) _parseChunk : ( NSData * ) data
{
2004-10-24 12:29:31 +00:00
if ( lib = = NULL || ( ( xmlParserCtxtPtr ) lib ) -> disableSAX ! = 0 )
{
return ; // Parsing impossible or disabled .
}
2006-02-27 16:54:36 +00:00
xmlParseChunk ( lib , [ data bytes ] , [ data length ] , data = = nil ) ;
2002-03-06 15:50:14 +00:00
}
@ end
/ * *
* The GSHTMLParser class is a simple subclass of GSXMLParser which should
* parse reasonably well formed HTML documents . If you wish to parse XHTML
* documents , you should use GSXMLParser . . . the GSHTMLParser class is for
* older ' legacy ' documents .
* /
@ implementation GSHTMLParser
- ( BOOL ) _initLibXML
{
lib = ( void * ) htmlCreatePushParserCtxt ( [ saxHandler lib ] , NULL , 0 , 0 , "." ,
XML_CHAR _ENCODING _NONE ) ;
if ( lib = = NULL )
{
NSLog ( @ "Failed to create libxml parser context" ) ;
return NO ;
}
else
{
/ *
* Put saxHandler address in _private member , so we can retrieve
2002-05-11 03:06:51 +00:00
* the GSSAXHandler to use in our SAX C Functions .
2002-03-06 15:50:14 +00:00
* /
( ( htmlParserCtxtPtr ) lib ) -> _private = saxHandler ;
}
return YES ;
}
- ( void ) _parseChunk : ( NSData * ) data
{
2002-05-04 05:39:48 +00:00
htmlParseChunk ( lib , [ data bytes ] , [ data length ] , data = = nil ) ;
2002-03-06 15:50:14 +00:00
}
@ end
/ * *
* < p > XML SAX Handler . < / p >
* < p >
2002-11-22 10:47:48 +00:00
* GSSAXHandler is a callback - based interface to the [ GSXMLParser ]
* which operates in a similar ( though not identical ) manner to
2002-03-06 15:50:14 +00:00
* SAX .
* < / p >
* < p >
2002-11-22 10:47:48 +00:00
* Each GSSAXHandler object is associated with a GSXMLParser
* object . As parsing progresses , the methods of the GSSAXHandler
* are invoked by the parser , so the handler is able to deal
* with the elements and entities being parsed .
* < / p >
* < p >
* The callback methods in the GSSAXHandler class do nothing - it
* is intended that you subclass GSSAXHandler and override them .
* < / p >
* < p >
* If you create a GSXMLParser passing nil as the GSSAXHandler ,
2005-02-22 11:22:44 +00:00
* the parser will parse data to create a [ GSXMLDocument ] instance
2002-11-22 10:47:48 +00:00
* which you can then examine as a whole . . . this is generally the
* preferred mechanism for parsing as it permits the parser to
* validate the parsed document againts a DTD , and your software
* can then examine the document secure in the knowledge that it
* contains the expected structure . Use of a GSSAXHandler is
* preferred for very large documents with simple structure . . .
* in which case incremental parsing is more efficient .
* < / p >
2002-03-06 15:50:14 +00:00
* /
2002-05-26 17:05:46 +00:00
@ implementation GSSAXHandler
2002-03-06 15:50:14 +00:00
+ ( void ) initialize
{
if ( cacheDone = = NO )
2004-05-30 09:05:10 +00:00
{
setupCache ( ) ;
}
2002-03-06 15:50:14 +00:00
}
/ *
* The context is a xmlParserCtxtPtr or htmlParserCtxtPtr .
* Its _private member contains the address of our Sax Handler Object .
* We can use a ( xmlParserCtxtPtr ) cast because xmlParserCtxt and
* htmlParserCtxt are the same structure ( and will remain , cf libxml author ) .
* /
2003-05-23 08:58:52 +00:00
# define HANDLER ( ( GSSAXHandler * ) ( ( ( xmlParserCtxtPtr ) ctx ) -> _private ) )
2002-03-06 15:50:14 +00:00
static xmlParserInputPtr
2006-02-27 16:54:36 +00:00
loadEntityFunction ( void * ctx ,
const unsigned char * eid , const unsigned char * url )
2002-03-06 15:50:14 +00:00
{
2006-09-13 15:53:58 +00:00
NSString * file = nil ;
2002-03-06 15:50:14 +00:00
NSString * entityId ;
NSString * location ;
NSArray * components ;
NSMutableString * local ;
unsigned count ;
unsigned index ;
NSCAssert ( ctx , @ "No Context" ) ;
2010-02-16 17:34:05 +00:00
if ( url = = NULL )
return NULL ;
2002-03-06 15:50:14 +00:00
2010-02-16 17:34:05 +00:00
entityId = ( eid ! = NULL ) ? ( id ) UTF8Str ( eid ) : nil ;
2002-03-06 15:50:14 +00:00
location = UTF8Str ( url ) ;
components = [ location pathComponents ] ;
2008-11-17 13:45:32 +00:00
local = ( NSMutableString * ) [ NSMutableString string ] ;
2002-03-06 15:50:14 +00:00
/ *
* Build a local filename by replacing path separator characters with
* something else .
* /
count = [ components count ] ;
if ( count > 0 )
{
count - - ;
for ( index = 0 ; index < count ; index + + )
{
[ local appendString : [ components objectAtIndex : index ] ] ;
[ local appendString : @ "_" ] ;
}
[ local appendString : [ components objectAtIndex : index ] ] ;
}
2006-02-23 03:02:55 +00:00
/ * Also replace ' : ' which isn ' t legal on some file systems * /
[ local replaceOccurrencesOfString : @ ":" withString : @ "+"
options : NSLiteralSearch
range : NSMakeRange ( 0 , [ local length ] ) ] ;
2002-03-06 15:50:14 +00:00
2006-09-13 15:53:58 +00:00
# ifdef GNUSTEP
2007-11-26 09:14:52 +00:00
if ( [ location rangeOfString : @ "/DTDs/PropertyList" ] . length > 0 )
2006-09-13 15:53:58 +00:00
{
file = [ location substringFromIndex : 6 ] ;
if ( [ [ NSFileManager defaultManager ] fileExistsAtPath : file ] = = NO )
{
location = [ NSBundle pathForLibraryResource : @ "plist-0_9"
ofType : @ "dtd"
inDirectory : @ "DTDs" ] ;
entityId = @ "-//GNUstep//DTD plist 0.9//EN" ;
file = nil ;
}
}
# endif
2002-03-06 15:50:14 +00:00
if ( file = = nil )
{
2006-09-13 15:53:58 +00:00
/ *
* Now ask the SAXHandler callback for the name of a local file
* /
file = [ HANDLER loadEntity : entityId at : location ] ;
if ( file = = nil )
{
file = [ GSXMLParser loadEntity : entityId at : location ] ;
}
2002-03-06 15:50:14 +00:00
}
if ( file = = nil )
{
/ *
* Special case - GNUstep DTDs - should be installed in the GNUstep
* system bundle - so we look for them there .
* /
if ( [ entityId hasPrefix : @ "-//GNUstep//DTD " ] = = YES )
{
NSCharacterSet * ws = [ NSCharacterSet whitespaceCharacterSet ] ;
2010-02-17 14:23:25 +00:00
NSString * found = nil ;
2002-03-06 15:50:14 +00:00
NSMutableString * name ;
unsigned len ;
NSRange r ;
/ *
* Extract the relevent DTD name
* /
name = AUTORELEASE ( [ entityId mutableCopy ] ) ;
r = NSMakeRange ( 0 , 16 ) ;
[ name deleteCharactersInRange : r ] ;
len = [ name length ] ;
r = [ name rangeOfString : @ "/" options : NSLiteralSearch ] ;
if ( r . length > 0 )
{
r . length = len - r . location ;
[ name deleteCharactersInRange : r ] ;
len = [ name length ] ;
}
/ *
* Convert dots to underscores .
* /
r = [ name rangeOfString : @ "." options : NSLiteralSearch ] ;
while ( r . length > 0 )
{
[ name replaceCharactersInRange : r withString : @ "_" ] ;
r . location + + ;
r . length = len - r . location ;
r = [ name rangeOfString : @ "."
options : NSLiteralSearch
range : r ] ;
}
/ *
* Convert whitespace to hyphens .
* /
r = [ name rangeOfCharacterFromSet : ws options : NSLiteralSearch ] ;
while ( r . length > 0 )
{
[ name replaceCharactersInRange : r withString : @ "-" ] ;
r . location + + ;
r . length = len - r . location ;
r = [ name rangeOfCharacterFromSet : ws
options : NSLiteralSearch
range : r ] ;
}
2010-02-16 19:51:52 +00:00
if ( dtdPath ! = nil )
{
found = [ dtdPath stringByAppendingPathComponent : name ] ;
found = [ found stringByAppendingPathExtension : @ "dtd" ] ;
if ( ! [ [ NSFileManager defaultManager ] fileExistsAtPath : found ] )
{
found = nil ;
}
}
if ( found = = nil )
{
2010-02-26 08:56:26 +00:00
# ifndef NeXT_Foundation _LIBRARY
2010-02-16 19:51:52 +00:00
found = [ NSBundle pathForLibraryResource : name
ofType : @ "dtd"
inDirectory : @ "DTDs" ] ;
2005-03-12 17:38:18 +00:00
# else
2010-02-26 09:03:46 +00:00
found = [ [ NSBundle bundleForClass : [ GSXMLNode class ] ]
pathForResource : name
ofType : @ "dtd"
inDirectory : @ "DTDs" ] ;
2005-03-12 17:38:18 +00:00
# endif
2010-02-16 19:51:52 +00:00
}
2002-03-06 15:50:14 +00:00
if ( found = = nil )
{
NSLog ( @ "unable to find GNUstep DTD - '%@' for '%s'" , name , eid ) ;
}
else
{
file = found ;
}
}
/ *
* DTD not found - so we look for it in standard locations .
* /
if ( file = = nil )
{
2010-02-16 19:51:52 +00:00
if ( dtdPath ! = nil )
{
file = [ dtdPath stringByAppendingPathComponent : local ] ;
if ( ! [ [ NSFileManager defaultManager ] fileExistsAtPath : local ] )
{
file = nil ;
}
}
if ( file = = nil )
{
file = [ [ NSBundle mainBundle ] pathForResource : local
ofType : @ ""
inDirectory : @ "DTDs" ] ;
}
2002-03-06 15:50:14 +00:00
if ( file = = nil )
{
2010-02-26 08:56:26 +00:00
# ifndef NeXT_Foundation _LIBRARY
2003-04-28 02:29:49 +00:00
file = [ NSBundle pathForLibraryResource : local
2002-03-06 15:50:14 +00:00
ofType : @ ""
inDirectory : @ "DTDs" ] ;
2010-02-26 08:56:26 +00:00
# else
2010-02-26 09:03:46 +00:00
file = [ [ NSBundle bundleForClass : [ GSXMLNode class ] ]
pathForResource : local
ofType : @ ""
inDirectory : @ "DTDs" ] ;
2010-02-26 08:56:26 +00:00
# endif
2002-03-06 15:50:14 +00:00
}
}
}
2010-02-16 17:34:05 +00:00
/ *
* If we found the DTD somewhere , add it to the catalog .
* /
2002-03-06 15:50:14 +00:00
if ( [ file length ] > 0 )
{
2010-02-16 17:34:05 +00:00
NSURL * theURL = [ NSURL fileURLWithPath : file ] ;
xmlCatalogAdd ( ( const unsigned char * ) "public" , eid ,
UTF8STRING ( [ theURL absoluteString ] ) ) ;
2002-03-06 15:50:14 +00:00
}
2010-02-16 17:34:05 +00:00
/ *
* A local DTD will now be in the catalog : The builtin entity resolver can
* take over .
* /
return xmlSAX2ResolveEntity ( ctx , eid , url ) ;
2002-03-06 15:50:14 +00:00
}
2006-02-27 16:54:36 +00:00
2003-05-23 08:58:52 +00:00
# define TREEFUN ( NAME , ARGS ) ( ( HANDLER -> isHtmlHandler = = YES ) ? ( * ( htmlDefaultSAXHandler . NAME ) ) ARGS : ( * ( xmlDefaultSAXHandler . NAME ) ) ARGS )
# define START ( SELNAME , RET , ARGS ) \
static SEL sel ; \
static RET ( * treeImp ) ARGS = 0 ; \
RET ( * imp ) ARGS ; \
\
NSCAssert ( ctx , @ "No Context" ) ; \
\
if ( treeImp = = 0 ) \
{ \
sel = @ selector ( SELNAME ) ; \
treeImp = ( RET ( * ) ARGS ) [ treeClass instanceMethodForSelector : sel ] ; \
} \
imp = ( RET ( * ) ARGS ) [ HANDLER methodForSelector : sel ]
2002-03-06 15:50:14 +00:00
static void
startDocumentFunction ( void * ctx )
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER startDocument ] ;
2002-03-06 15:50:14 +00:00
}
static void
endDocumentFunction ( void * ctx )
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER endDocument ] ;
2002-03-06 15:50:14 +00:00
}
static int
isStandaloneFunction ( void * ctx )
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
return [ HANDLER isStandalone ] ;
2002-03-06 15:50:14 +00:00
}
static int
hasInternalSubsetFunction ( void * ctx )
{
2004-06-24 09:26:01 +00:00
int has ;
2002-03-06 15:50:14 +00:00
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
has = [ HANDLER hasInternalSubset ] ;
2002-03-06 15:50:14 +00:00
if ( has < 0 )
2003-05-23 08:58:52 +00:00
{
has = TREEFUN ( hasInternalSubset , ( ctx ) ) ;
}
2002-03-06 15:50:14 +00:00
return has ;
}
static int
hasExternalSubsetFunction ( void * ctx )
{
2004-06-24 09:26:01 +00:00
int has ;
2002-03-06 15:50:14 +00:00
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
has = [ HANDLER hasExternalSubset ] ;
2002-03-06 15:50:14 +00:00
if ( has < 0 )
2003-05-23 08:58:52 +00:00
{
has = TREEFUN ( hasExternalSubset , ( ctx ) ) ;
}
2002-03-06 15:50:14 +00:00
return has ;
}
static void
2003-05-23 08:58:52 +00:00
internalSubsetFunction ( void * ctx , const unsigned char * name ,
2002-03-06 15:50:14 +00:00
const xmlChar * ExternalID , const xmlChar * SystemID )
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER internalSubset : UTF8Str ( name )
externalID : UTF8Str ( ExternalID )
systemID : UTF8Str ( SystemID ) ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
externalSubsetFunction ( void * ctx , const unsigned char * name ,
2002-03-06 15:50:14 +00:00
const xmlChar * ExternalID , const xmlChar * SystemID )
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER externalSubset : UTF8Str ( name )
externalID : UTF8Str ( ExternalID )
systemID : UTF8Str ( SystemID ) ] ;
2002-03-06 15:50:14 +00:00
}
static xmlEntityPtr
2003-05-23 08:58:52 +00:00
getEntityFunction ( void * ctx , const unsigned char * name )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
return [ HANDLER getEntity : UTF8Str ( name ) ] ;
2002-03-06 15:50:14 +00:00
}
static xmlEntityPtr
2003-05-23 08:58:52 +00:00
getParameterEntityFunction ( void * ctx , const unsigned char * name )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
return [ HANDLER getParameterEntity : UTF8Str ( name ) ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
entityDeclFunction ( void * ctx , const unsigned char * name , int type ,
const unsigned char * publicId , const unsigned char * systemId ,
unsigned char * content )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER entityDecl : UTF8Str ( name )
type : type
public : UTF8Str ( publicId )
system : UTF8Str ( systemId )
content : UTF8Str ( content ) ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
attributeDeclFunction ( void * ctx , const unsigned char * elem ,
const unsigned char * name , int type , int def ,
const unsigned char * defaultValue , xmlEnumerationPtr tree )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER attributeDecl : UTF8Str ( elem )
name : UTF8Str ( name )
type : type
typeDefValue : def
defaultValue : UTF8Str ( defaultValue ) ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
elementDeclFunction ( void * ctx , const unsigned char * name , int type ,
2002-03-06 15:50:14 +00:00
xmlElementContentPtr content )
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER elementDecl : UTF8Str ( name ) type : type ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
notationDeclFunction ( void * ctx , const unsigned char * name ,
const unsigned char * publicId , const unsigned char * systemId )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER notationDecl : UTF8Str ( name )
public : UTF8Str ( publicId )
system : UTF8Str ( systemId ) ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
unparsedEntityDeclFunction ( void * ctx , const unsigned char * name ,
const unsigned char * publicId , const unsigned char * systemId ,
const unsigned char * notationName )
2002-03-06 15:50:14 +00:00
{
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER unparsedEntityDecl : UTF8Str ( name )
public : UTF8Str ( publicId )
system : UTF8Str ( systemId )
notationName : UTF8Str ( notationName ) ] ;
}
static void
2003-05-23 08:58:52 +00:00
startElementFunction ( void * ctx , const unsigned char * name ,
const unsigned char * * atts )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSMutableDictionary * dict ;
2002-03-06 15:50:14 +00:00
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
dict = [ NSMutableDictionary dictionary ] ;
if ( atts ! = NULL )
2002-03-06 15:50:14 +00:00
{
2009-09-17 08:52:03 +00:00
int i = 0 ;
2003-05-23 08:58:52 +00:00
2004-06-24 09:26:01 +00:00
while ( atts [ i ] ! = NULL )
2002-03-06 15:50:14 +00:00
{
2010-10-12 19:19:02 +00:00
NSString * key = UTF8Str ( atts [ i + + ] ) ;
NSString * obj ;
const unsigned char * val = atts [ i + + ] ;
2004-06-24 09:26:01 +00:00
2010-10-12 19:19:02 +00:00
if ( 0 = = val )
{
/ * No value . . . assume tis is a minimised attribute in html .
* /
obj = key ;
}
else
{
obj = UTF8Str ( val ) ;
}
2004-06-24 09:26:01 +00:00
[ dict setObject : obj forKey : key ] ;
2002-03-06 15:50:14 +00:00
}
}
2004-06-24 09:26:01 +00:00
[ HANDLER startElement : UTF8Str ( name )
attributes : dict ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
endElementFunction ( void * ctx , const unsigned char * name )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
[ HANDLER endElement : UTF8Str ( name ) ] ;
2002-03-06 15:50:14 +00:00
}
2004-05-18 09:55:33 +00:00
# if HAVE_LIBXML _SAX2 _H
static void
startElementNsFunction ( void * ctx , const unsigned char * name ,
const unsigned char * prefix , const unsigned char * href ,
int nb_namespaces , const unsigned char * * namespaces ,
int nb_attributes , int nb_defaulted ,
const unsigned char * * atts )
{
2008-01-26 08:34:58 +00:00
NSMutableDictionary * adict = nil ;
NSMutableDictionary * ndict = nil ;
2004-06-24 09:26:01 +00:00
NSString * elem ;
2004-05-18 09:55:33 +00:00
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
elem = UTF8Str ( name ) ;
if ( atts ! = NULL )
2004-05-18 09:55:33 +00:00
{
2004-06-24 09:26:01 +00:00
int i ;
int j ;
2004-05-18 09:55:33 +00:00
2008-01-26 08:34:58 +00:00
adict = [ NSMutableDictionary dictionaryWithCapacity : nb_attributes ] ;
2004-06-24 09:26:01 +00:00
for ( i = j = 0 ; i < nb_attributes ; i + + , j + = 5 )
2004-05-18 09:55:33 +00:00
{
2004-06-24 09:26:01 +00:00
NSString * key = UTF8Str ( atts [ j ] ) ;
NSString * obj = UTF8StrLen ( atts [ j + 3 ] , atts [ j + 4 ] - atts [ j + 3 ] ) ;
2008-01-26 08:34:58 +00:00
[ adict setObject : obj forKey : key ] ;
2004-05-18 09:55:33 +00:00
}
}
2008-01-25 16:27:34 +00:00
if ( nb_namespaces > 0 )
{
int i ;
int pos = 0 ;
2008-01-26 08:34:58 +00:00
ndict = [ NSMutableDictionary dictionaryWithCapacity : nb_namespaces ] ;
2008-01-25 16:27:34 +00:00
for ( i = 0 ; i < nb_namespaces ; i + + )
{
NSString * key ;
NSString * obj ;
if ( namespaces [ pos ] = = 0 )
{
2008-01-26 09:23:49 +00:00
key = @ "" ;
2008-01-25 16:27:34 +00:00
}
else
{
2008-01-26 09:23:49 +00:00
key = UTF8Str ( namespaces [ pos ] ) ;
2008-01-25 16:27:34 +00:00
}
pos + + ;
if ( namespaces [ pos ] = = 0 )
{
obj = @ "" ;
}
else
{
obj = UTF8Str ( namespaces [ pos ] ) ;
}
pos + + ;
2008-01-26 08:34:58 +00:00
[ ndict setObject : obj forKey : key ] ;
2008-01-25 16:27:34 +00:00
}
}
2004-06-24 09:26:01 +00:00
[ HANDLER startElement : elem
prefix : UTF8Str ( prefix )
href : UTF8Str ( href )
2008-01-26 08:34:58 +00:00
attributes : adict
namespaces : ndict ] ;
2004-05-18 09:55:33 +00:00
}
static void
endElementNsFunction ( void * ctx , const unsigned char * name ,
const unsigned char * prefix , const unsigned char * href )
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER endElement : UTF8Str ( name )
prefix : UTF8Str ( prefix )
href : UTF8Str ( href ) ] ;
2004-05-18 09:55:33 +00:00
}
# endif
2002-03-06 15:50:14 +00:00
static void
2003-05-23 08:58:52 +00:00
charactersFunction ( void * ctx , const unsigned char * ch , int len )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER characters : UTF8StrLen ( ch , len ) ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
referenceFunction ( void * ctx , const unsigned char * name )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER reference : UTF8Str ( name ) ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
ignorableWhitespaceFunction ( void * ctx , const unsigned char * ch , int len )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER ignoreWhitespace : UTF8StrLen ( ch , len ) ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
processingInstructionFunction ( void * ctx , const unsigned char * target ,
const char * data )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER processInstruction : UTF8Str ( target )
2005-07-08 11:48:37 +00:00
data : UTF8Str ( ( const unsigned char * ) data ) ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
cdataBlockFunction ( void * ctx , const unsigned char * value , int len )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER cdataBlock : [ NSData dataWithBytes : value length : len ] ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
commentFunction ( void * ctx , const unsigned char * value )
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
NSCAssert ( ctx , @ "No Context" ) ;
[ HANDLER comment : UTF8Str ( value ) ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
warningFunction ( void * ctx , const unsigned char * msg , . . . )
2002-03-06 15:50:14 +00:00
{
2004-04-06 19:17:52 +00:00
NSString * estr ;
va_list args ;
int lineNumber = -1 ;
int colNumber = -1 ;
2002-03-06 15:50:14 +00:00
va_start ( args , msg ) ;
2010-06-15 13:02:36 +00:00
estr = [ [ [ NSString alloc ]
initWithFormat : UTF8Str ( msg ) arguments : args ] autorelease ] ;
2002-03-06 15:50:14 +00:00
va_end ( args ) ;
NSCAssert ( ctx , @ "No Context" ) ;
2002-06-18 15:26:48 +00:00
lineNumber = getLineNumber ( ctx ) ;
2004-05-18 09:55:33 +00:00
colNumber = xmlSAX2GetColumnNumber ( ctx ) ;
2004-04-06 19:17:52 +00:00
[ HANDLER warning : estr
2002-06-18 15:26:48 +00:00
colNumber : colNumber
lineNumber : lineNumber ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
errorFunction ( void * ctx , const unsigned char * msg , . . . )
2002-03-06 15:50:14 +00:00
{
2004-04-06 19:14:33 +00:00
NSString * estr ;
va_list args ;
int lineNumber = -1 ;
int colNumber = -1 ;
2002-03-06 15:50:14 +00:00
va_start ( args , msg ) ;
2010-06-15 13:02:36 +00:00
estr = [ [ [ NSString alloc ]
initWithFormat : UTF8Str ( msg ) arguments : args ] autorelease ] ;
2002-03-06 15:50:14 +00:00
va_end ( args ) ;
NSCAssert ( ctx , @ "No Context" ) ;
2004-05-18 09:55:33 +00:00
lineNumber = xmlSAX2GetLineNumber ( ctx ) ;
colNumber = xmlSAX2GetColumnNumber ( ctx ) ;
2004-04-06 19:14:33 +00:00
[ HANDLER error : estr
2002-06-18 15:26:48 +00:00
colNumber : colNumber
lineNumber : lineNumber ] ;
2002-03-06 15:50:14 +00:00
}
static void
2003-05-23 08:58:52 +00:00
fatalErrorFunction ( void * ctx , const unsigned char * msg , . . . )
2002-03-06 15:50:14 +00:00
{
2004-04-06 19:17:52 +00:00
NSString * estr ;
va_list args ;
int lineNumber = -1 ;
int colNumber = -1 ;
2002-03-06 15:50:14 +00:00
va_start ( args , msg ) ;
2010-06-15 13:02:36 +00:00
estr = [ [ [ NSString alloc ]
initWithFormat : UTF8Str ( msg ) arguments : args ] autorelease ] ;
2002-03-06 15:50:14 +00:00
va_end ( args ) ;
NSCAssert ( ctx , @ "No Context" ) ;
2004-05-18 09:55:33 +00:00
lineNumber = xmlSAX2GetLineNumber ( ctx ) ;
colNumber = xmlSAX2GetColumnNumber ( ctx ) ;
2004-04-06 19:17:52 +00:00
[ HANDLER fatalError : estr
2002-06-18 15:26:48 +00:00
colNumber : colNumber
lineNumber : lineNumber ] ;
2002-03-06 15:50:14 +00:00
}
# undef HANDLER
/ * *
* Create a new SAX handler .
* /
+ ( GSSAXHandler * ) handler
{
return AUTORELEASE ( [ [ self alloc ] init ] ) ;
}
- ( id ) init
{
NSAssert ( lib = = 0 , @ "Already created lib" ) ;
self = [ super init ] ;
if ( self ! = nil )
{
if ( [ self _initLibXML ] = = NO )
{
NSLog ( @ "GSSAXHandler: out of memory\n" ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-03-06 15:50:14 +00:00
return nil ;
}
}
return self ;
}
/ * *
2002-05-22 14:23:17 +00:00
* Returns a pointer to the raw libxml data used by this document . < br / >
* Only for use by libxml experts !
2002-03-06 15:50:14 +00:00
* /
- ( void * ) lib
{
return lib ;
}
/ * *
* Return the parser object with which this handler is
* associated . This may occasionally be useful .
* /
- ( GSXMLParser * ) parser
{
return parser ;
}
- ( void ) dealloc
{
2006-04-04 17:21:18 +00:00
if ( lib ! = NULL )
2002-03-06 15:50:14 +00:00
{
2010-02-26 09:03:46 +00:00
free ( lib ) ;
2002-03-06 15:50:14 +00:00
}
[ super dealloc ] ;
}
/ * *
* Called when the document starts being processed .
* /
- ( void ) startDocument
{
}
/ * *
* Called when the document end has been detected .
* /
- ( void ) endDocument
{
}
/ * *
* Called to detemrine if the document is standalone .
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) isStandalone
2002-03-06 15:50:14 +00:00
{
return 1 ;
}
/ * *
* Called when an opening tag has been processed .
* /
- ( void ) startElement : ( NSString * ) elementName
attributes : ( NSMutableDictionary * ) elementAttributes
{
}
2004-05-18 09:55:33 +00:00
- ( void ) startElement : ( NSString * ) elementName
prefix : ( NSString * ) prefix
href : ( NSString * ) href
attributes : ( NSMutableDictionary * ) elementAttributes
{
2004-06-24 09:26:01 +00:00
[ self startElement : elementName attributes : elementAttributes ] ;
2004-05-18 09:55:33 +00:00
}
2008-01-26 08:34:58 +00:00
- ( void ) startElement : ( NSString * ) elementName
prefix : ( NSString * ) prefix
href : ( NSString * ) href
attributes : ( NSMutableDictionary * ) elementAttributes
namespaces : ( NSMutableDictionary * ) elementNamespaces
{
[ self startElement : elementName
prefix : prefix
href : href
attributes : elementAttributes ] ;
}
2004-05-18 09:55:33 +00:00
/ * *
* Called when a closing tag has been processed .
* /
- ( void ) endElement : ( NSString * ) elementName
{
}
2002-03-06 15:50:14 +00:00
/ * *
* Called when a closing tag has been processed .
* /
2004-05-18 09:55:33 +00:00
- ( void ) endElement : ( NSString * ) elementName
prefix : ( NSString * ) prefix
href : ( NSString * ) href
2002-03-06 15:50:14 +00:00
{
2004-06-24 09:26:01 +00:00
[ self endElement : elementName ] ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Handle an attribute that has been read by the parser .
* /
- ( void ) attribute : ( NSString * ) name value : ( NSString * ) value
{
}
/ * *
* Receiving some chars from the parser .
* /
- ( void ) characters : ( NSString * ) name
{
}
/ * *
* Receiving some ignorable whitespaces from the parser .
* /
- ( void ) ignoreWhitespace : ( NSString * ) ch
{
}
/ * *
* A processing instruction has been parsed .
* /
- ( void ) processInstruction : ( NSString * ) targetName data : ( NSString * ) PIdata
{
}
/ * *
* A comment has been parsed .
* /
- ( void ) comment : ( NSString * ) value
{
}
/ * *
2004-05-16 13:26:32 +00:00
* Called when a cdata block has been parsed .
2002-03-06 15:50:14 +00:00
* /
2004-05-16 13:26:32 +00:00
- ( void ) cdataBlock : ( NSData * ) value
2002-03-06 15:50:14 +00:00
{
}
/ * *
2002-11-22 10:47:48 +00:00
* Called to return the filename from which an entity should be loaded .
2002-03-06 15:50:14 +00:00
* /
- ( NSString * ) loadEntity : ( NSString * ) publicId
at : ( NSString * ) location
{
return nil ;
}
/ * *
* An old global namespace has been parsed .
* /
- ( void ) namespaceDecl : ( NSString * ) name
href : ( NSString * ) href
prefix : ( NSString * ) prefix
{
}
/ * *
* What to do when a notation declaration has been parsed .
* /
- ( void ) notationDecl : ( NSString * ) name
public : ( NSString * ) publicId
system : ( NSString * ) systemId
{
}
/ * *
* An entity definition has been parsed .
* /
- ( void ) entityDecl : ( NSString * ) name
2009-02-23 20:42:32 +00:00
type : ( NSInteger ) type
2002-03-06 15:50:14 +00:00
public : ( NSString * ) publicId
system : ( NSString * ) systemId
content : ( NSString * ) content
{
}
/ * *
* An attribute definition has been parsed .
* /
- ( void ) attributeDecl : ( NSString * ) nameElement
2002-06-06 14:02:59 +00:00
name : ( NSString * ) name
2009-02-23 20:42:32 +00:00
type : ( NSInteger ) type
typeDefValue : ( NSInteger ) defType
2002-03-06 15:50:14 +00:00
defaultValue : ( NSString * ) value
{
}
/ * *
* An element definition has been parsed .
* /
- ( void ) elementDecl : ( NSString * ) name
2009-02-23 20:42:32 +00:00
type : ( NSInteger ) type
2002-03-06 15:50:14 +00:00
{
}
/ * *
* What to do when an unparsed entity declaration is parsed .
* /
- ( void ) unparsedEntityDecl : ( NSString * ) name
2002-06-06 14:02:59 +00:00
public : ( NSString * ) publicId
system : ( NSString * ) systemId
2002-03-06 15:50:14 +00:00
notationName : ( NSString * ) notation
{
}
/ * *
* Called when an entity reference is detected .
* /
- ( void ) reference : ( NSString * ) name
{
}
/ * *
* An old global namespace has been parsed .
* /
- ( void ) globalNamespace : ( NSString * ) name
href : ( NSString * ) href
prefix : ( NSString * ) prefix
{
}
/ * *
* Called when a warning message needs to be output .
* /
- ( void ) warning : ( NSString * ) e
{
2003-05-22 17:00:03 +00:00
GSPrintf ( stderr , @ "%@" , e ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Called when an error message needs to be output .
* /
- ( void ) error : ( NSString * ) e
{
2003-05-22 17:00:03 +00:00
GSPrintf ( stderr , @ "%@" , e ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Called when a fatal error message needs to be output .
* /
- ( void ) fatalError : ( NSString * ) e
{
2003-05-22 17:00:03 +00:00
GSPrintf ( stderr , @ "%@" , e ) ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Called when a warning message needs to be output .
* /
- ( void ) warning : ( NSString * ) e
2009-02-23 20:42:32 +00:00
colNumber : ( NSInteger ) colNumber
lineNumber : ( NSInteger ) lineNumber
2002-03-06 15:50:14 +00:00
{
2004-04-06 19:17:52 +00:00
e = [ NSString stringWithFormat : @ "at line: %d column: %d ... %@" ,
lineNumber , colNumber , e ] ;
2002-06-18 15:26:48 +00:00
[ self warning : e ] ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Called when an error message needs to be output .
* /
- ( void ) error : ( NSString * ) e
2009-02-23 20:42:32 +00:00
colNumber : ( NSInteger ) colNumber
lineNumber : ( NSInteger ) lineNumber
2002-03-06 15:50:14 +00:00
{
2004-04-06 19:14:33 +00:00
e = [ NSString stringWithFormat : @ "at line: %d column: %d ... %@" ,
lineNumber , colNumber , e ] ;
2002-06-18 15:26:48 +00:00
[ self error : e ] ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Called when a fatal error message needs to be output .
* /
- ( void ) fatalError : ( NSString * ) e
2010-06-16 10:45:58 +00:00
colNumber : ( NSInteger ) colNumber
lineNumber : ( NSInteger ) lineNumber
2002-03-06 15:50:14 +00:00
{
2004-04-06 19:14:33 +00:00
e = [ NSString stringWithFormat : @ "at line: %d column: %d ... %@" ,
lineNumber , colNumber , e ] ;
2002-06-18 15:26:48 +00:00
[ self fatalError : e ] ;
2002-03-06 15:50:14 +00:00
}
/ * *
* Called to find out whether there is an internal subset .
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) hasInternalSubset
2002-03-06 15:50:14 +00:00
{
return 0 ;
}
/ * *
* Called to find out whether there is an internal subset .
* /
- ( BOOL ) internalSubset : ( NSString * ) name
externalID : ( NSString * ) externalID
systemID : ( NSString * ) systemID
{
return NO ;
}
/ * *
* Called to find out whether there is an external subset .
* /
2009-02-23 20:42:32 +00:00
- ( NSInteger ) hasExternalSubset
2002-03-06 15:50:14 +00:00
{
return 0 ;
}
/ * *
* Called to find out whether there is an external subset .
* /
- ( BOOL ) externalSubset : ( NSString * ) name
externalID : ( NSString * ) externalID
2002-03-13 19:01:55 +00:00
systemID : ( NSString * ) systemID
2002-03-06 15:50:14 +00:00
{
return NO ;
}
/ * *
* get an entity by name
* /
- ( void * ) getEntity : ( NSString * ) name
{
return 0 ;
}
/ * *
2002-06-18 15:26:48 +00:00
* get a parameter entity by name
2002-03-06 15:50:14 +00:00
* /
- ( void * ) getParameterEntity : ( NSString * ) name
{
return 0 ;
}
/ *
* Private methods - internal use only .
* /
- ( BOOL ) _initLibXML
{
2010-02-26 09:03:46 +00:00
lib = ( xmlSAXHandler * ) malloc ( sizeof ( xmlSAXHandler ) ) ;
2002-03-06 15:50:14 +00:00
if ( lib = = NULL )
2002-06-18 15:26:48 +00:00
{
return NO ;
}
2002-03-06 15:50:14 +00:00
else
{
2003-05-22 17:00:03 +00:00
memcpy ( lib , & xmlDefaultSAXHandler , sizeof ( xmlSAXHandler ) ) ;
2002-03-06 15:50:14 +00:00
# define LIB ( ( xmlSAXHandlerPtr ) lib )
2004-06-24 09:26:01 +00:00
# if HAVE_LIBXML _SAX2 _H
/ *
* We must call xmlSAXVersion ( ) BEFORE setting any functions as it
* sets up default values and would trash our settings .
* /
xmlSAXVersion ( LIB , 2 ) ; // Set SAX2
LIB -> startElementNs = ( void * ) startElementNsFunction ;
LIB -> endElementNs = ( void * ) endElementNsFunction ;
2006-11-07 18:37:36 +00:00
# endif
2004-06-24 09:26:01 +00:00
LIB -> startElement = ( void * ) startElementFunction ;
LIB -> endElement = ( void * ) endElementFunction ;
2002-03-06 15:50:14 +00:00
LIB -> internalSubset = ( void * ) internalSubsetFunction ;
LIB -> externalSubset = ( void * ) externalSubsetFunction ;
LIB -> isStandalone = ( void * ) isStandaloneFunction ;
LIB -> hasInternalSubset = ( void * ) hasInternalSubsetFunction ;
LIB -> hasExternalSubset = ( void * ) hasExternalSubsetFunction ;
LIB -> getEntity = ( void * ) getEntityFunction ;
LIB -> entityDecl = ( void * ) entityDeclFunction ;
LIB -> notationDecl = ( void * ) notationDeclFunction ;
LIB -> attributeDecl = ( void * ) attributeDeclFunction ;
LIB -> elementDecl = ( void * ) elementDeclFunction ;
LIB -> unparsedEntityDecl = ( void * ) unparsedEntityDeclFunction ;
LIB -> startDocument = ( void * ) startDocumentFunction ;
LIB -> endDocument = ( void * ) endDocumentFunction ;
LIB -> reference = ( void * ) referenceFunction ;
LIB -> characters = ( void * ) charactersFunction ;
LIB -> ignorableWhitespace = ( void * ) ignorableWhitespaceFunction ;
2003-05-23 08:58:52 +00:00
LIB -> processingInstruction = ( void * ) processingInstructionFunction ;
2002-03-06 15:50:14 +00:00
LIB -> comment = ( void * ) commentFunction ;
LIB -> warning = ( void * ) warningFunction ;
LIB -> error = ( void * ) errorFunction ;
LIB -> fatalError = ( void * ) fatalErrorFunction ;
LIB -> getParameterEntity = ( void * ) getParameterEntityFunction ;
LIB -> cdataBlock = ( void * ) cdataBlockFunction ;
# undef LIB
return YES ;
}
}
- ( void ) _setParser : ( GSXMLParser * ) value
{
parser = value ;
}
@ end
2003-05-22 17:00:03 +00:00
/ * *
* The default handler for parsing documents . . . this will build a
* GSXMLDocument for you . This handler may not currently be subclassed ,
* though that capability may be added at a later date .
* /
@ implementation GSTreeSAXHandler
/ * *
2004-05-18 11:18:37 +00:00
* Called when a warning message needs to be output . < br / >
2003-05-22 17:00:03 +00:00
* See [ GSXMLParser - setErrors : ] for the mechanism implemented by this .
* /
- ( void ) warning : ( NSString * ) e
{
2003-05-22 19:02:38 +00:00
NSMutableString * m = [ parser _messages ] ;
2003-05-22 17:00:03 +00:00
if ( m = = nil )
{
GSPrintf ( stderr , @ "%@" , e ) ;
}
else
{
[ m appendString : e ] ;
}
}
/ * *
* Called when an error message needs to be output . < br / >
* See [ GSXMLParser - setErrors : ] for the mechanism implemented by this .
* /
- ( void ) error : ( NSString * ) e
{
2003-05-22 19:02:38 +00:00
NSMutableString * m = [ parser _messages ] ;
2003-05-22 17:00:03 +00:00
if ( m = = nil )
{
GSPrintf ( stderr , @ "%@" , e ) ;
}
else
{
[ m appendString : e ] ;
}
}
/ * *
* Called when a fatal error message needs to be output . < br / >
* See [ GSXMLParser - setErrors : ] for the mechanism implemented by this .
* /
- ( void ) fatalError : ( NSString * ) e
{
2003-05-22 19:02:38 +00:00
NSMutableString * m = [ parser _messages ] ;
2003-05-22 17:00:03 +00:00
if ( m = = nil )
{
GSPrintf ( stderr , @ "%@" , e ) ;
}
else
{
[ m appendString : e ] ;
}
}
2004-06-24 09:26:01 +00:00
2003-05-22 17:00:03 +00:00
- ( BOOL ) _initLibXML
{
2010-02-26 09:03:46 +00:00
lib = ( xmlSAXHandler * ) malloc ( sizeof ( xmlSAXHandler ) ) ;
2003-05-22 17:00:03 +00:00
if ( lib = = NULL )
{
return NO ;
}
else
{
memcpy ( lib , & xmlDefaultSAXHandler , sizeof ( xmlSAXHandler ) ) ;
# define LIB ( ( xmlSAXHandlerPtr ) lib )
2004-06-24 09:26:01 +00:00
# define SETCB ( NAME , SEL ) if ( [ self methodForSelector : @ selector ( SEL ) ] ! = [ treeClass instanceMethodForSelector : @ selector ( SEL ) ] ) LIB -> NAME = ( void * ) NAME # # Function
# if HAVE_LIBXML _SAX2 _H
/ *
* We must call xmlSAXVersion ( ) BEFORE setting any functions as it
* sets up default values and would trash our settings .
* /
xmlSAXVersion ( LIB , 2 ) ; // Set SAX2
SETCB ( startElementNs , startElement : prefix : href : attributes : ) ;
SETCB ( endElementNs , endElement : prefix : href : ) ;
2006-11-07 18:37:36 +00:00
# endif
2004-06-24 09:26:01 +00:00
SETCB ( startElement , startElement : attributes : ) ;
SETCB ( endElement , endElement : ) ;
SETCB ( internalSubset , internalSubset : externalID : systemID : ) ;
SETCB ( externalSubset , externalSubset : externalID : systemID : ) ;
SETCB ( isStandalone , isStandalone ) ;
SETCB ( hasInternalSubset , hasInternalSubset ) ;
SETCB ( hasExternalSubset , hasExternalSubset ) ;
SETCB ( getEntity , getEntity : ) ;
SETCB ( entityDecl , entityDecl : type : public : system : content : ) ;
2009-11-27 10:42:33 +00:00
SETCB ( notationDecl , notationDecl : public : system : ) ;
2004-06-24 09:26:01 +00:00
SETCB ( attributeDecl , attributeDecl : name : type : typeDefValue : defaultValue : ) ;
SETCB ( elementDecl , elementDecl : type : ) ;
SETCB ( unparsedEntityDecl , unparsedEntityDecl : public : system : notationName : ) ;
SETCB ( startDocument , startDocument ) ;
2005-02-22 11:22:44 +00:00
SETCB ( endDocument , endDocument ) ;
2004-06-24 09:26:01 +00:00
SETCB ( reference , reference : ) ;
SETCB ( characters , characters : ) ;
SETCB ( ignorableWhitespace , ignoreWhitespace : ) ;
SETCB ( processingInstruction , processInstruction : data : ) ;
SETCB ( comment , comment : ) ;
SETCB ( getParameterEntity , getParameterEntity : ) ;
SETCB ( cdataBlock , cdataBlock : ) ;
LIB -> warning = ( void * ) warningFunction ;
LIB -> error = ( void * ) errorFunction ;
LIB -> fatalError = ( void * ) fatalErrorFunction ;
2003-05-22 17:00:03 +00:00
# undef LIB
return YES ;
}
}
@ end
2002-11-22 10:47:48 +00:00
/ * *
* You may create a subclass of this class to handle incremental parsing
* of html documents . . . this is provided for handling legacy documents ,
* as modern html documents should use xhtml , and for those you should
* simply subclass [ GSSAXHandler ]
* /
2002-03-06 15:50:14 +00:00
@ implementation GSHTMLSAXHandler
- ( BOOL ) _initLibXML
{
2003-05-23 08:58:52 +00:00
isHtmlHandler = YES ;
2010-02-26 09:03:46 +00:00
lib = ( xmlSAXHandler * ) malloc ( sizeof ( htmlSAXHandler ) ) ;
2002-03-06 15:50:14 +00:00
if ( lib = = NULL )
2002-06-18 15:26:48 +00:00
{
return NO ;
}
2002-03-06 15:50:14 +00:00
else
{
2003-05-23 08:58:52 +00:00
memcpy ( lib , & htmlDefaultSAXHandler , sizeof ( htmlSAXHandler ) ) ;
2002-03-06 15:50:14 +00:00
# define LIB ( ( htmlSAXHandlerPtr ) lib )
2004-06-24 09:26:01 +00:00
LIB -> internalSubset = ( void * ) internalSubsetFunction ;
LIB -> externalSubset = ( void * ) externalSubsetFunction ;
LIB -> isStandalone = ( void * ) isStandaloneFunction ;
LIB -> hasInternalSubset = ( void * ) hasInternalSubsetFunction ;
LIB -> hasExternalSubset = ( void * ) hasExternalSubsetFunction ;
LIB -> getEntity = ( void * ) getEntityFunction ;
LIB -> entityDecl = ( void * ) entityDeclFunction ;
LIB -> notationDecl = ( void * ) notationDeclFunction ;
LIB -> attributeDecl = ( void * ) attributeDeclFunction ;
LIB -> elementDecl = ( void * ) elementDeclFunction ;
LIB -> unparsedEntityDecl = ( void * ) unparsedEntityDeclFunction ;
LIB -> startDocument = ( void * ) startDocumentFunction ;
LIB -> endDocument = ( void * ) endDocumentFunction ;
LIB -> startElement = ( void * ) startElementFunction ;
LIB -> endElement = ( void * ) endElementFunction ;
LIB -> reference = ( void * ) referenceFunction ;
LIB -> characters = ( void * ) charactersFunction ;
LIB -> ignorableWhitespace = ( void * ) ignorableWhitespaceFunction ;
LIB -> processingInstruction = ( void * ) processingInstructionFunction ;
LIB -> comment = ( void * ) commentFunction ;
LIB -> warning = ( void * ) warningFunction ;
LIB -> error = ( void * ) errorFunction ;
LIB -> fatalError = ( void * ) fatalErrorFunction ;
LIB -> getParameterEntity = ( void * ) getParameterEntityFunction ;
LIB -> cdataBlock = ( void * ) cdataBlockFunction ;
2002-03-06 15:50:14 +00:00
# undef LIB
return YES ;
}
}
@ end
2002-08-27 15:46:15 +00:00
2002-11-22 10:47:48 +00:00
/ * *
* < p > You don ' t create GSXPathObject instances , instead the XPATH system
* creates them and returns them as the result of the
* [ GSXPathContext - evaluateExpression : ] method .
* < / p >
* /
2002-08-27 15:46:15 +00:00
@ implementation GSXPathObject
- ( id ) init
{
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-08-27 15:46:15 +00:00
return nil ;
}
/ * Internal method . * /
- ( id ) _initWithNativePointer : ( xmlXPathObject * ) lib
context : ( GSXPathContext * ) context
{
_lib = lib ;
/ * We RETAIN our context because we might be holding references to nodes
* which belong to the document , and we must make sure the document is
* not freed before we are . * /
ASSIGN ( _context , context ) ;
return self ;
}
/ * This method is called by GSXPathContext when creating a
* GSXPathObject to wrap the results of a query . It assumes that lib
* is a pointer created by xmlXPathEval ( ) , and that we are now taking
* on responsibility for freeing it . It then examines lib , and
* replaces itself with an object of the appropriate subclass . * /
+ ( id ) _newWithNativePointer : ( xmlXPathObject * ) lib
context : ( GSXPathContext * ) context
{
switch ( lib -> type )
{
case XPATH_NODESET :
return [ [ GSXPathNodeSet alloc ] _initWithNativePointer : lib
context : context ] ;
break ;
case XPATH_BOOLEAN :
return [ [ GSXPathBoolean alloc ] _initWithNativePointer : lib
context : context ] ;
break ;
case XPATH_NUMBER :
return [ [ GSXPathNumber alloc ] _initWithNativePointer : lib
context : context ] ;
break ;
case XPATH_STRING :
return [ [ GSXPathString alloc ] _initWithNativePointer : lib
context : context ] ;
break ;
default :
2005-02-22 11:22:44 +00:00
/ * This includes :
2002-08-27 15:46:15 +00:00
case XPATH_UNDEFINED :
case XPATH_POINT :
case XPATH_RANGE :
case XPATH_LOCATIONSET :
case XPATH_USERS :
case XPATH_XSLT _TREE :
* /
return [ [ self alloc ] _initWithNativePointer : lib context : context ] ;
}
}
- ( void ) dealloc
{
xmlXPathFreeObject ( _lib ) ;
RELEASE ( _context ) ;
[ super dealloc ] ;
}
@ end
@ implementation GSXPathBoolean
2002-11-22 10:47:48 +00:00
/ * *
* Returns the the value of the receiver . . . YES / NO , true / false .
* /
2002-08-27 15:46:15 +00:00
- ( BOOL ) booleanValue
{
return ( ( xmlXPathObject * ) _lib ) -> boolval ;
}
- ( NSString * ) description
{
return ( [ self booleanValue ] ? @ "true" : @ "false" ) ;
}
@ end
@ implementation GSXPathNumber
2002-11-22 10:47:48 +00:00
/ * *
* Returns the floating point ( double ) value of the receiver .
* /
2002-08-27 15:46:15 +00:00
- ( double ) doubleValue
{
return ( ( xmlXPathObject * ) _lib ) -> floatval ;
}
- ( NSString * ) description
{
2003-07-11 18:53:48 +00:00
return [ NSString_class stringWithFormat : @ "%f" , [ self doubleValue ] ] ;
2002-08-27 15:46:15 +00:00
}
@ end
@ implementation GSXPathString
2002-11-22 10:47:48 +00:00
/ * *
* Returns the string value of the receiver .
* /
2002-08-27 15:46:15 +00:00
- ( NSString * ) stringValue
{
xmlChar * string = ( ( xmlXPathObject * ) _lib ) -> stringval ;
2005-07-08 11:48:37 +00:00
return [ NSString_class stringWithUTF8String : ( const char * ) string ] ;
2002-08-27 15:46:15 +00:00
}
- ( NSString * ) description
{
2003-07-11 18:53:48 +00:00
return [ NSString_class stringWithFormat : @ "%@" , [ self stringValue ] ] ;
2002-08-27 15:46:15 +00:00
}
@ end
2002-11-22 10:47:48 +00:00
/ * *
* An XPATH node set is an ordered set of nodes returned as a result of
* an expression . The order of the nodes in the set is the same as the
* order in the xml document from which they were extracted .
* /
2002-08-27 15:46:15 +00:00
@ implementation GSXPathNodeSet
2002-11-22 10:47:48 +00:00
/ * *
* Returns the number of nodes in the receiver .
* /
2009-02-23 20:42:32 +00:00
- ( NSUInteger ) count
2002-11-22 10:47:48 +00:00
{
if ( xmlXPathNodeSetIsEmpty ( ( ( xmlXPathObject * ) _lib ) -> nodesetval ) )
{
return 0 ;
}
return xmlXPathNodeSetGetLength ( ( ( xmlXPathObject * ) _lib ) -> nodesetval ) ;
}
/ * *
* Deprecated
* /
2009-02-23 20:42:32 +00:00
- ( NSUInteger ) length
2002-08-27 15:46:15 +00:00
{
if ( xmlXPathNodeSetIsEmpty ( ( ( xmlXPathObject * ) _lib ) -> nodesetval ) )
{
return 0 ;
}
return xmlXPathNodeSetGetLength ( ( ( xmlXPathObject * ) _lib ) -> nodesetval ) ;
}
2002-11-22 10:47:48 +00:00
/ * *
* Returns the node from the receiver at the specified index , or nil
* if no such node exists .
* /
2009-02-23 20:42:32 +00:00
- ( GSXMLNode * ) nodeAtIndex : ( NSUInteger ) index
2002-08-27 15:46:15 +00:00
{
if ( xmlXPathNodeSetIsEmpty ( ( ( xmlXPathObject * ) _lib ) -> nodesetval ) )
{
return nil ;
}
else
{
xmlNode * node ;
GSXMLNode * n ;
2003-01-03 20:14:47 +00:00
node = xmlXPathNodeSetItem ( ( ( xmlXPathObject * ) _lib ) -> nodesetval ,
2009-02-23 20:42:32 +00:00
( NSInteger ) index ) ;
2002-08-27 15:46:15 +00:00
n = [ GSXMLNode alloc ] ;
2004-09-24 19:14:26 +00:00
n = [ n _initFrom : node parent : self ] ;
2004-09-24 19:16:22 +00:00
return AUTORELEASE ( n ) ;
2002-08-27 15:46:15 +00:00
}
}
- ( NSString * ) description
{
2008-01-21 10:46:41 +00:00
return [ NSString_class stringWithFormat : @ "NodeSet (count %u)" , [ self count ] ] ;
2002-08-27 15:46:15 +00:00
}
@ end
2002-11-22 10:47:48 +00:00
/ * *
2008-01-05 18:49:18 +00:00
* < p > Use of the GSXPathContext class is simple . . . you just need to
* look up xpath to learn the syntax of xpath expressions , then you
* can apply those expressions to a context to retrieve data from a
* document .
2002-11-22 10:47:48 +00:00
* < / p >
* < example >
* GSXMLParser * p = [ GSXMLParser parserWithContentsOfFile : @ "xp.xml" ] ;
*
* if ( [ p parse ] )
* {
* GSXMLDocument * d = [ p document ] ;
* GSXPathContext * c = [ [ GSXPathContext alloc ] initWithDocument : document ] ;
* GSXPathString * result = [ c evaluateExpression : @ "string(/body/text())" ] ;
*
* GSPrintf ( stdout , @ "Got %@" , [ result stringValue ] ) ;
* }
* else
* {
* GSPrintf ( stderr , "error parsing file\n" ) ;
* }
* < / example >
* /
2002-08-27 15:46:15 +00:00
@ implementation GSXPathContext
2002-11-22 10:47:48 +00:00
/ * *
* Initialises the receiver as an xpath parser for the supplied document .
* /
2002-08-27 15:46:15 +00:00
- ( id ) initWithDocument : ( GSXMLDocument * ) d
{
ASSIGN ( _document , d ) ;
2004-02-04 00:14:00 +00:00
_lib = xmlXPathNewContext ( [ _document lib ] ) ;
2002-08-27 15:46:15 +00:00
( ( xmlXPathContext * ) _lib ) -> node = xmlDocGetRootElement ( [ _document lib ] ) ;
2005-02-22 11:22:44 +00:00
2002-08-27 15:46:15 +00:00
return self ;
}
2002-11-22 10:47:48 +00:00
/ * *
* Evaluates the supplied expression and returns the resulting node or
* node set . If the expression is invalid , returns nil .
* /
2002-08-27 15:46:15 +00:00
- ( GSXPathObject * ) evaluateExpression : ( NSString * ) XPathExpression
{
xmlXPathCompExpr * comp ;
xmlXPathObject * res ;
GSXPathObject * result ;
2005-02-22 11:22:44 +00:00
2005-07-08 11:48:37 +00:00
comp = xmlXPathCompile ( UTF8STRING ( XPathExpression ) ) ;
2005-02-22 11:22:44 +00:00
if ( comp = = NULL )
2002-08-27 15:46:15 +00:00
{
/ * Maybe an exception would be better ? * /
return nil ;
}
res = xmlXPathCompiledEval ( comp , ( ( xmlXPathContext * ) _lib ) ) ;
2003-05-22 13:22:42 +00:00
if ( res = = NULL )
{
result = nil ;
}
else
{
result = [ GSXPathObject _newWithNativePointer : res context : self ] ;
2009-01-12 12:48:46 +00:00
IF_NO _GC ( [ result autorelease ] ; )
2003-05-22 13:22:42 +00:00
}
2002-08-27 15:46:15 +00:00
xmlXPathFreeCompExpr ( comp ) ;
return result ;
}
2008-01-05 21:01:40 +00:00
- ( BOOL ) registerNamespaceWithPrefix : ( NSString * ) prefix
href : ( NSString * ) href
{
if ( xmlXPathRegisterNs ( _lib , UTF8STRING ( prefix ) , UTF8STRING ( href ) ) ! = 0 )
{
return NO ;
}
else
{
return YES ;
}
}
2002-08-27 15:46:15 +00:00
- ( void ) dealloc
{
2005-02-22 11:22:44 +00:00
xmlXPathFreeContext ( _lib ) ;
2002-08-27 15:46:15 +00:00
RELEASE ( _document ) ;
[ super dealloc ] ;
}
@ end
2002-05-11 03:06:51 +00:00
/ *
* need this to make the linker happy on Windows
* /
@ interface GSXMLDummy : NSObject
@ end
@ implementation GSXMLDummy
@ end
2002-05-22 14:23:17 +00:00
@ implementation GSXMLNode ( Deprecated )
- ( GSXMLNode * ) childElement { static BOOL warned = NO ; if ( warned = = NO ) { warned = YES ; NSLog ( @ "WARNING, use of deprecated method ... [%@ -%@]" , NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ; } return [ self firstChildElement ] ; }
- ( GSXMLNode * ) children { static BOOL warned = NO ; if ( warned = = NO ) { warned = YES ; NSLog ( @ "WARNING, use of deprecated method ... [%@ -%@]" , NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ; } return [ self firstChild ] ; }
- ( GSXMLDocument * ) doc { static BOOL warned = NO ; if ( warned = = NO ) { warned = YES ; NSLog ( @ "WARNING, use of deprecated method ... [%@ -%@]" , NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ; } return [ self document ] ; }
- ( GSXMLNamespace * ) ns { static BOOL warned = NO ; if ( warned = = NO ) { warned = YES ; NSLog ( @ "WARNING, use of deprecated method ... [%@ -%@]" , NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ; } return [ self namespace ] ; }
- ( GSXMLNamespace * ) nsDefs { static BOOL warned = NO ; if ( warned = = NO ) { warned = YES ; NSLog ( @ "WARNING, use of deprecated method ... [%@ -%@]" , NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ; } return [ self namespaceDefinitions ] ; }
- ( GSXMLNode * ) prev { static BOOL warned = NO ; if ( warned = = NO ) { warned = YES ; NSLog ( @ "WARNING, use of deprecated method ... [%@ -%@]" , NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ; } return [ self previous ] ; }
- ( NSMutableDictionary * ) propertiesAsDictionary
{
static BOOL warned = NO ; if ( warned = = NO ) { warned = YES ; NSLog ( @ "WARNING, use of deprecated method ... [%@ -%@]" , NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ; }
return [ self propertiesAsDictionaryWithKeyTransformationSel : NULL ] ;
}
@ end
@ implementation GSXMLParser ( Deprecated )
- ( GSXMLDocument * ) doc { static BOOL warned = NO ; if ( warned = = NO ) { warned = YES ; NSLog ( @ "WARNING, use of deprecated method ... [%@ -%@]" , NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ; } return [ self document ] ; }
@ end
2004-03-28 04:42:11 +00:00
@ implementation GSXMLDocument ( XSLT )
# ifdef HAVE_LIBXSLT
/ * *
* Performs an XSLT transformation on the specified file using the
2004-04-06 06:27:32 +00:00
* stylesheet provided . < br / >
2004-03-28 04:42:11 +00:00
*
* Returns an autoreleased GSXMLDocument containing the transformed
* XML , or nil on failure .
* /
+ ( GSXMLDocument * ) xsltTransformFile : ( NSString * ) xmlFile
stylesheet : ( NSString * ) xsltStylesheet
{
return [ GSXMLDocument xsltTransformFile : xmlFile
stylesheet : xsltStylesheet
params : nil ] ;
}
/ * *
* Performs an XSLT transformation on the specified file using the
2004-04-06 06:27:32 +00:00
* stylesheet and parameters provided . See the libxslt documentation
2004-03-28 04:42:11 +00:00
* for details of the supported parameters . < br / >
*
* Returns an autoreleased GSXMLDocument containing the transformed
* XML , or nil on failure .
* /
+ ( GSXMLDocument * ) xsltTransformFile : ( NSString * ) xmlFile
stylesheet : ( NSString * ) xsltStylesheet
params : ( NSDictionary * ) params
{
GSXMLDocument * newdoc ;
2005-02-22 11:22:44 +00:00
2004-03-28 04:42:11 +00:00
NS_DURING
{
NSData * xml ;
NSData * ss ;
xml = [ NSData dataWithContentsOfFile : xmlFile ] ;
ss = [ NSData dataWithContentsOfFile : xsltStylesheet ] ;
if ( xml = = nil || ss = = nil )
{
newdoc = nil ;
}
else
{
2005-02-22 11:22:44 +00:00
newdoc = [ GSXMLDocument xsltTransformXml : xml
2004-03-28 04:42:11 +00:00
stylesheet : ss
params : params ] ;
}
}
NS_HANDLER
{
newdoc = nil ;
}
NS_ENDHANDLER
2005-02-22 11:22:44 +00:00
2004-03-28 04:42:11 +00:00
return newdoc ;
}
/ * *
* Performs an XSLT transformation on the specified file using the
2004-04-06 06:27:32 +00:00
* stylesheet provided . < br / >
2004-03-28 04:42:11 +00:00
*
* Returns an autoreleased GSXMLDocument containing the transformed
* XML , or nil on failure .
* /
+ ( GSXMLDocument * ) xsltTransformXml : ( NSData * ) xmlData
stylesheet : ( NSData * ) xsltStylesheet
{
return [ GSXMLDocument xsltTransformXml : xmlData
stylesheet : xsltStylesheet
params : nil ] ;
}
2005-02-22 11:22:44 +00:00
2004-03-28 04:42:11 +00:00
/ * *
* Performs an XSLT transformation on the specified file using the
2004-04-06 06:27:32 +00:00
* stylesheet and parameters provided . See the libxslt documentation
2004-03-28 04:42:11 +00:00
* for details of the supported parameters . < br / >
*
* Returns an autoreleased GSXMLDocument containing the transformed
* XML , or nil on failure .
* /
+ ( GSXMLDocument * ) xsltTransformXml : ( NSData * ) xmlData
stylesheet : ( NSData * ) xsltStylesheet
params : ( NSDictionary * ) params
{
GSXMLDocument * newdoc ;
2005-02-22 11:22:44 +00:00
2004-03-28 04:42:11 +00:00
NS_DURING
{
GSXMLParser * xmlParser ;
GSXMLDocument * xml ;
GSXMLParser * ssParser ;
GSXMLDocument * ss ;
2006-04-28 10:57:47 +00:00
newdoc = nil ;
2004-03-28 04:42:11 +00:00
xmlParser = [ GSXMLParser parserWithData : xmlData ] ;
2006-04-28 10:57:47 +00:00
if ( [ xmlParser parse ] = = YES )
{
xml = [ xmlParser document ] ;
ssParser = [ GSXMLParser parserWithData : xsltStylesheet ] ;
if ( [ ssParser parse ] = = YES )
{
ss = [ ssParser document ] ;
newdoc = [ xml xsltTransform : ss params : params ] ;
}
}
2004-03-28 04:42:11 +00:00
}
NS_HANDLER
{
newdoc = nil ;
}
NS_ENDHANDLER
2005-02-22 11:22:44 +00:00
2004-03-28 04:42:11 +00:00
return newdoc ;
}
/ * *
* Performs an XSLT transformation on the current document using the
* supplied stylesheet . < br / >
*
* Returns an autoreleased GSXMLDocument containing the transformed
* XML , or nil on failure .
* /
- ( GSXMLDocument * ) xsltTransform : ( GSXMLDocument * ) xsltStylesheet
{
return [ self xsltTransform : xsltStylesheet params : nil ] ;
}
/ * *
* Performs an XSLT transformation on the current document using the
2004-03-28 11:13:36 +00:00
* supplied stylesheet and paramaters ( params may be nil ) .
2004-03-28 04:42:11 +00:00
* See the libxslt documentation for details of the supported parameters . < br / >
*
* Returns an autoreleased GSXMLDocument containing the transformed
* XML , or nil on failure .
* /
- ( GSXMLDocument * ) xsltTransform : ( GSXMLDocument * ) xsltStylesheet
params : ( NSDictionary * ) params
{
2005-02-22 11:22:44 +00:00
GSXMLDocument * newdoc = nil ;
2004-03-28 04:42:11 +00:00
NS_DURING
{
xsltStylesheetPtr ss = NULL ;
xmlDocPtr ssXml = ( xmlDocPtr ) [ xsltStylesheet lib ] ;
int pSize = params = = nil ? 1 : ( [ params count ] * 2 ) + 1 ;
int pNum = 0 ;
const char * parameters [ pSize ] ;
if ( params ! = nil )
{
NSEnumerator * keys = [ params keyEnumerator ] ;
if ( keys ! = nil )
{
NSString * key = [ keys nextObject ] ;
while ( key ! = nil )
{
NSString * value = [ params objectForKey : key ] ;
parameters [ pNum + + ] = [ key cString ] ;
parameters [ pNum + + ] = [ value cString ] ;
key = [ keys nextObject ] ;
}
}
}
parameters [ pNum ] = NULL ;
2005-02-22 11:22:44 +00:00
2004-03-28 04:42:11 +00:00
ss = xsltParseStylesheetDoc ( ssXml ) ;
if ( xsltStylesheet ! = NULL )
{
xmlDocPtr res = NULL ;
res = xsltApplyStylesheet ( ss , lib , parameters ) ;
if ( res ! = NULL )
{
newdoc = [ GSXMLDocument alloc ] ;
newdoc = [ newdoc _initFrom : res
2005-02-22 11:22:44 +00:00
parent : self
2004-03-28 04:42:11 +00:00
ownsLib : YES ] ;
2009-01-12 12:48:46 +00:00
IF_NO _GC ( [ newdoc autorelease ] ; )
2004-03-28 04:42:11 +00:00
}
}
/ *
2005-02-22 11:22:44 +00:00
* N . B . We don ' t want to call xsltFreeStylesheet ( ) to free the
* stylesheet xmlDocPtr because that will destroy the lib which
2004-03-28 04:42:11 +00:00
* is owned by the xsltStylesheet object .
* /
xsltCleanupGlobals ( ) ;
}
NS_HANDLER
{
newdoc = nil ;
}
NS_ENDHANDLER
return newdoc ;
}
# else / * HAVE_LIBXSLT * /
+ ( GSXMLDocument * ) xsltTransformFile : ( NSString * ) xmlFile
stylesheet : ( NSString * ) xsltStylesheet
params : ( NSDictionary * ) params
{
NSLog ( @ "libxslt is not available" ) ;
return nil ;
}
2005-02-22 11:22:44 +00:00
2004-03-28 04:42:11 +00:00
+ ( GSXMLDocument * ) xsltTransformFile : ( NSString * ) xmlFile
stylesheet : ( NSString * ) xsltStylesheet
{
NSLog ( @ "libxslt is not available" ) ;
return nil ;
}
2005-02-22 11:22:44 +00:00
2004-03-28 04:42:11 +00:00
+ ( GSXMLDocument * ) xsltTransformXml : ( NSData * ) xmlData
stylesheet : ( NSData * ) xsltStylesheet
params : ( NSDictionary * ) params
{
NSLog ( @ "libxslt is not available" ) ;
return nil ;
}
+ ( GSXMLDocument * ) xsltTransformXml : ( NSData * ) xmlData
stylesheet : ( NSData * ) xsltStylesheet
{
NSLog ( @ "libxslt is not available" ) ;
return nil ;
}
2005-02-22 11:22:44 +00:00
2004-03-28 04:42:11 +00:00
- ( GSXMLDocument * ) xsltTransform : ( GSXMLDocument * ) xsltStylesheet
2004-03-28 11:13:36 +00:00
params : ( NSDictionary * ) params
2004-03-28 04:42:11 +00:00
{
NSLog ( @ "libxslt is not available" ) ;
return nil ;
}
- ( GSXMLDocument * ) xsltTransform : ( GSXMLDocument * ) xsltStylesheet
{
NSLog ( @ "libxslt is not available" ) ;
return nil ;
}
# endif / * HAVE_LIBXSLT * /
@ end
2002-03-06 15:50:14 +00:00
# else
2003-02-03 04:15:27 +00:00
# ifndef NeXT_Foundation _LIBRARY
2010-02-14 10:48:10 +00:00
# import "Foundation/NSCoder.h"
# import "Foundation/NSInvocation.h"
2003-02-03 04:15:27 +00:00
# endif
2002-03-06 15:50:14 +00:00
/ *
* Build dummy implementations of the classes if libxml is not available
* /
@ interface GSXMLDummy : NSObject
@ end
@ interface GSXMLDocument : GSXMLDummy
@ end
@ interface GSXMLNamespace : GSXMLDummy
@ end
@ interface GSXMLNode : GSXMLDummy
@ end
@ interface GSSAXHandler : GSXMLDummy
@ end
@ interface GSXMLParser : GSXMLDummy
@ end
2002-05-26 17:05:46 +00:00
@ interface GSXMLAttribute : GSXMLNode
@ end
2002-03-06 15:50:14 +00:00
@ implementation GSXMLDummy
+ ( id ) allocWithZone : ( NSZone * ) z
{
NSLog ( @ "Not built with libxml ... %@ unusable in %@" ,
NSStringFromClass ( self ) , NSStringFromSelector ( _cmd ) ) ;
return nil ;
}
+ ( void ) forwardInvocation : ( NSInvocation * ) anInvocation
{
NSLog ( @ "Not built with libxml ... %@ unusable in %@" ,
2005-02-22 11:22:44 +00:00
NSStringFromClass ( [ self class ] ) ,
2002-06-13 16:02:02 +00:00
NSStringFromSelector ( [ anInvocation selector ] ) ) ;
2002-03-06 15:50:14 +00:00
return ;
}
- ( id ) init
{
NSLog ( @ "Not built with libxml ... %@ unusable in %@" ,
NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-03-06 15:50:14 +00:00
return nil ;
}
- ( id ) initWithCoder : ( NSCoder * ) aCoder
{
NSLog ( @ "Not built with libxml ... %@ unusable in %@" ,
NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ;
2010-02-25 18:49:31 +00:00
DESTROY ( self ) ;
2002-03-06 15:50:14 +00:00
return nil ;
}
@ end
@ implementation GSXMLDocument
@ end
@ implementation GSXMLNamespace
@ end
@ implementation GSXMLNode
@ end
@ implementation GSSAXHandler
@ end
@ implementation GSXMLParser
@ end
2002-05-26 17:05:46 +00:00
@ implementation GSXMLAttribute
@ end
2004-03-28 04:42:11 +00:00
2002-03-06 15:50:14 +00:00
# endif
2004-10-03 09:11:15 +00:00
@ implementation NSString ( GSXML )
- ( NSString * ) stringByEscapingXML
{
unsigned length = [ self length ] ;
2004-10-13 16:46:09 +00:00
unsigned output = 0 ;
2004-10-03 09:11:15 +00:00
unichar * from ;
unsigned i = 0 ;
2004-10-13 16:46:09 +00:00
BOOL escape = NO ;
2004-10-03 09:11:15 +00:00
from = NSZoneMalloc ( NSDefaultMallocZone ( ) , sizeof ( unichar ) * length ) ;
[ self getCharacters : from ] ;
for ( i = 0 ; i < length ; i + + )
{
unichar c = from [ i ] ;
2005-12-13 20:56:36 +00:00
if ( ( c >= 0 x20 && c <= 0 xd7ff )
2006-11-08 08:22:04 +00:00
|| c = = 0 x9 || c = = 0 xd || c = = 0 xa
2005-12-13 20:56:36 +00:00
|| ( c >= 0 xe000 && c <= 0 xfffd ) )
2004-10-03 09:11:15 +00:00
{
switch ( c )
{
case ' " ' :
case ' \ ' ' :
output + = 6 ;
2004-10-13 16:46:09 +00:00
escape = YES ;
2004-10-03 09:11:15 +00:00
break ;
case ' & ' :
output + = 5 ;
2004-10-13 16:46:09 +00:00
escape = YES ;
2004-10-03 09:11:15 +00:00
break ;
case ' < ' :
case ' > ' :
output + = 4 ;
2004-10-13 16:46:09 +00:00
escape = YES ;
2004-10-03 09:11:15 +00:00
break ;
default :
/ *
* For non - ascii characters , we can use & # nnnn ; escapes
* /
if ( c > 127 )
{
output + = 5 ;
while ( c >= 1000 )
{
output + + ;
c / = 10 ;
}
2004-10-13 16:46:09 +00:00
escape = YES ;
2004-10-03 09:11:15 +00:00
}
2004-10-13 16:46:09 +00:00
output + + ;
2004-10-03 09:11:15 +00:00
break ;
}
}
2005-12-13 20:56:36 +00:00
else
{
escape = YES ; // Need to remove bad characters
}
2004-10-03 09:11:15 +00:00
}
2004-10-13 16:46:09 +00:00
if ( escape = = YES )
2004-10-03 09:11:15 +00:00
{
unichar * to ;
unsigned j = 0 ;
to = NSZoneMalloc ( NSDefaultMallocZone ( ) , sizeof ( unichar ) * output ) ;
for ( i = 0 ; i < length ; i + + )
{
unichar c = from [ i ] ;
2005-12-13 20:56:36 +00:00
if ( ( c >= 0 x20 && c <= 0 xd7ff )
2006-11-08 08:22:04 +00:00
|| c = = 0 x9 || c = = 0 xd || c = = 0 xa
2005-12-13 20:56:36 +00:00
|| ( c >= 0 xe000 && c <= 0 xfffd ) )
2004-10-03 09:11:15 +00:00
{
switch ( c )
{
case ' " ' :
to [ j + + ] = ' & ' ;
to [ j + + ] = ' q ' ;
to [ j + + ] = ' u ' ;
to [ j + + ] = ' o ' ;
to [ j + + ] = ' t ' ;
to [ j + + ] = ' ; ' ;
break ;
case ' \ ' ' :
to [ j + + ] = ' & ' ;
to [ j + + ] = ' a ' ;
to [ j + + ] = ' p ' ;
to [ j + + ] = ' o ' ;
to [ j + + ] = ' s ' ;
to [ j + + ] = ' ; ' ;
break ;
case ' & ' :
to [ j + + ] = ' & ' ;
to [ j + + ] = ' a ' ;
to [ j + + ] = ' m ' ;
to [ j + + ] = ' p ' ;
to [ j + + ] = ' ; ' ;
break ;
case ' < ' :
to [ j + + ] = ' & ' ;
to [ j + + ] = ' l ' ;
to [ j + + ] = ' t ' ;
to [ j + + ] = ' ; ' ;
break ;
case ' > ' :
to [ j + + ] = ' & ' ;
to [ j + + ] = ' g ' ;
to [ j + + ] = ' t ' ;
to [ j + + ] = ' ; ' ;
break ;
2002-05-22 14:23:17 +00:00
2004-10-03 09:11:15 +00:00
default :
if ( c > 127 )
{
char buf [ 12 ] ;
char * ptr = buf ;
to [ j + + ] = ' & ' ;
to [ j + + ] = ' # ' ;
sprintf ( buf , "%u" , c ) ;
while ( * ptr ! = ' \ 0 ' )
{
to [ j + + ] = * ptr + + ;
}
to [ j + + ] = ' ; ' ;
}
else
{
to [ j + + ] = c ;
}
break ;
}
}
}
self = [ [ NSString alloc ] initWithCharacters : to length : output ] ;
NSZoneFree ( NSDefaultMallocZone ( ) , to ) ;
2009-01-12 12:48:46 +00:00
IF_NO _GC ( [ self autorelease ] ; )
2004-10-03 09:11:15 +00:00
}
else
{
self = AUTORELEASE ( [ self copyWithZone : NSDefaultMallocZone ( ) ] ) ;
}
NSZoneFree ( NSDefaultMallocZone ( ) , from ) ;
return self ;
}
- ( NSString * ) stringByUnescapingXML
{
unsigned length = [ self length ] ;
NSRange r = NSMakeRange ( 0 , length ) ;
r = [ self rangeOfString : @ "&" options : NSLiteralSearch range : r ] ;
if ( r . length > 0 )
{
NSMutableString * m = [ self mutableCopy ] ;
while ( r . length > 0 )
{
NSRange e ;
unsigned s0 = NSMaxRange ( r ) ;
e = [ m rangeOfString : @ ";"
options : NSLiteralSearch
range : NSMakeRange ( s0 , length - s0 ) ] ;
if ( e . length > 0 )
{
unsigned s1 = NSMaxRange ( e ) ;
NSString * s = [ m substringWithRange : NSMakeRange ( s0 , s1 - s0 ) ] ;
if ( [ s hasPrefix : @ "&#" ] = = YES )
{
unichar u ;
2006-03-08 18:14:42 +00:00
if ( [ s hasPrefix : @ "&#x" ] || [ s hasPrefix : @ "&#X" ] )
{
unsigned val = 0 ;
s = [ s substringFromIndex : 3 ] ;
sscanf ( [ s UTF8String ] , "%x" , & val ) ;
u = val ;
}
else if ( [ s hasPrefix : @ "�x" ] || [ s hasPrefix : @ "�X" ] )
2004-10-03 09:11:15 +00:00
{
unsigned val = 0 ;
s = [ s substringFromIndex : 4 ] ;
sscanf ( [ s UTF8String ] , "%x" , & val ) ;
u = val ;
}
else
{
s = [ s substringFromIndex : 2 ] ;
u = [ s intValue ] ;
}
if ( u = = 0 )
{
u = ' ' ;
}
s = [ [ NSString alloc ] initWithCharacters : & u length : 1 ] ;
s = AUTORELEASE ( s ) ;
}
else if ( [ s isEqualToString : @ "amp" ] )
{
s = @ "&" ;
}
else if ( [ s isEqualToString : @ "apos" ] )
{
s = @ "'" ;
}
else if ( [ s isEqualToString : @ "quot" ] )
{
s = @ "\" " ;
}
else if ( [ s isEqualToString : @ "lt" ] )
{
s = @ "<" ;
}
else if ( [ s isEqualToString : @ "gt" ] )
{
s = @ ">" ;
}
else
{
// Unknown escape . . . don ' t change .
s = [ NSString stringWithFormat : @ "&%@;" , s ] ;
}
[ m replaceCharactersInRange : NSMakeRange ( s0 , s1 - s0 )
withString : s ] ;
r . length = [ s length ] ;
length + = r . length - ( s1 - s0 ) ;
r . location = NSMaxRange ( r ) ;
r . length = length - r . location ;
r = [ m rangeOfString : @ "&" options : NSLiteralSearch range : r ] ;
}
else
{
r . length = 0 ;
}
}
self = AUTORELEASE ( m ) ;
}
else
{
self = AUTORELEASE ( [ self copyWithZone : NSDefaultMallocZone ( ) ] ) ;
}
return self ;
}
@ end
2002-05-22 14:23:17 +00:00
2005-03-04 15:50:06 +00:00
2005-03-05 06:03:03 +00:00
# ifdef HAVE_LIBXML
2005-03-04 15:50:06 +00:00
/ *
* Categories on other classes which are required for XMLRPC
* /
@ interface NSArray ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc ;
2005-03-04 15:50:06 +00:00
@ end
@ interface NSData ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc ;
2005-03-04 15:50:06 +00:00
@ end
@ interface NSDate ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc ;
2005-03-04 15:50:06 +00:00
@ end
@ interface NSDictionary ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc ;
2005-03-04 15:50:06 +00:00
@ end
@ interface NSObject ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc ;
2005-03-04 15:50:06 +00:00
@ end
@ interface NSNumber ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc ;
2005-03-04 15:50:06 +00:00
@ end
@ interface NSString ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc ;
2005-03-04 15:50:06 +00:00
@ end
/ *
* A little code to handle indentation .
* /
static NSString * indentations [ ] = {
@ " " ,
@ " " ,
@ " " ,
@ "\t" ,
@ "\t " ,
@ "\t " ,
@ "\t " ,
@ "\t\t" ,
@ "\t\t " ,
@ "\t\t " ,
@ "\t\t " ,
@ "\t\t\t" ,
@ "\t\t\t " ,
@ "\t\t\t " ,
@ "\t\t\t " ,
@ "\t\t\t\t"
} ;
static void indentation ( unsigned level , NSMutableString * str )
{
if ( level > 0 )
{
if ( level >= sizeof ( indentations ) / sizeof ( * indentations ) )
{
level = sizeof ( indentations ) / sizeof ( * indentations ) - 1 ;
}
[ str appendString : indentations [ level ] ] ;
}
}
2006-06-15 08:23:49 +00:00
# define INDENT ( I ) if ( compact = = NO ) indentation ( I , str )
# define NL if ( compact = = NO ) [ str appendString : @ "\n" ]
2005-03-04 15:50:06 +00:00
/ *
* Implementation of categories to output objects for XMLRPC
* /
@ implementation NSArray ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc
2005-03-04 15:50:06 +00:00
{
unsigned i ;
unsigned c = [ self count ] ;
2006-06-15 08:23:49 +00:00
BOOL compact = [ rpc compact ] ;
2005-03-04 15:50:06 +00:00
2006-06-15 08:23:49 +00:00
INDENT ( indent + + ) ;
[ str appendString : @ "<array>" ] ;
NL ;
INDENT ( indent + + ) ;
[ str appendString : @ "<data>" ] ;
NL ;
2005-03-04 15:50:06 +00:00
for ( i = 0 ; i < c ; i + + )
{
id value = [ self objectAtIndex : i ] ;
2006-06-15 08:23:49 +00:00
INDENT ( indent + + ) ;
[ str appendString : @ "<value>" ] ;
NL ;
[ value appendToXMLRPC : str indent : indent for : rpc ] ;
NL ;
INDENT ( - - indent ) ;
[ str appendString : @ "</value>" ] ;
NL ;
}
INDENT ( - - indent ) ;
[ str appendString : @ "</data>" ] ;
NL ;
INDENT ( - - indent ) ;
2005-03-04 15:50:06 +00:00
[ str appendString : @ "</array>" ] ;
}
@ end
@ implementation NSData ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc
2005-03-04 15:50:06 +00:00
{
NSData * d ;
NSString * s ;
d = [ GSMimeDocument encodeBase64 : self ] ;
s = [ [ NSString alloc ] initWithData : d encoding : NSASCIIStringEncoding ] ;
[ str appendString : @ "<base64>" ] ;
[ str appendString : s ] ;
[ str appendString : @ "</base64>" ] ;
RELEASE ( s ) ;
}
@ end
@ implementation NSDate ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc
2005-03-04 15:50:06 +00:00
{
NSString * s ;
s = [ self descriptionWithCalendarFormat : @ "%Y%m%dT%H:%M:%S"
2006-06-15 08:23:49 +00:00
timeZone : [ rpc timeZone ]
2005-03-04 15:50:06 +00:00
locale : nil ] ;
[ str appendString : @ "<dateTime.iso8601>" ] ;
[ str appendString : s ] ;
[ str appendString : @ "</dateTime.iso8601>" ] ;
}
@ end
@ implementation NSDictionary ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc
2005-03-04 15:50:06 +00:00
{
NSEnumerator * kEnum = [ self keyEnumerator ] ;
NSString * key ;
2006-06-15 08:23:49 +00:00
BOOL compact = [ rpc compact ] ;
2005-03-04 15:50:06 +00:00
2006-06-15 08:23:49 +00:00
INDENT ( indent + + ) ;
[ str appendString : @ "<struct>" ] ;
NL ;
2005-03-04 15:50:06 +00:00
while ( ( key = [ kEnum nextObject ] ) )
{
id value = [ self objectForKey : key ] ;
2006-06-15 08:23:49 +00:00
INDENT ( indent + + ) ;
[ str appendString : @ "<member>" ] ;
NL ;
INDENT ( indent ) ;
2005-03-04 15:50:06 +00:00
[ str appendString : @ "<name>" ] ;
[ str appendString : [ [ key description ] stringByEscapingXML ] ] ;
2006-06-15 08:23:49 +00:00
[ str appendString : @ "</name>" ] ;
NL ;
INDENT ( indent + + ) ;
[ str appendString : @ "<value>" ] ;
NL ;
[ value appendToXMLRPC : str indent : indent - - for : rpc ] ;
NL ;
INDENT ( indent - - ) ;
[ str appendString : @ "</value>" ] ;
NL ;
INDENT ( indent ) ;
[ str appendString : @ "</member>" ] ;
NL ;
}
INDENT ( - - indent ) ;
2005-03-04 15:50:06 +00:00
[ str appendString : @ "</struct>" ] ;
}
@ end
@ implementation NSNumber ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc
2005-03-04 15:50:06 +00:00
{
const char * t = [ self objCType ] ;
2006-06-15 08:23:49 +00:00
BOOL compact = [ rpc compact ] ;
2005-03-04 15:50:06 +00:00
2006-06-15 08:23:49 +00:00
INDENT ( indent ) ;
2005-03-04 15:50:06 +00:00
if ( strchr ( "cCsSiIlL" , * t ) ! = 0 )
{
long i = [ self longValue ] ;
if ( ( i = = 0 || i = = 1 ) && ( * t = = ' c ' || * t = = ' C ' ) )
{
if ( i = = 0 )
{
[ str appendString : @ "<boolean>0</boolean>" ] ;
}
else
{
[ str appendString : @ "<boolean>1</boolean>" ] ;
}
}
else
{
2008-01-21 10:46:41 +00:00
[ str appendFormat : @ "<i4>%ld</i4>" , i ] ;
2005-03-04 15:50:06 +00:00
}
}
else
{
[ str appendFormat : @ "<double>%f</double>" , [ self doubleValue ] ] ;
}
}
@ end
@ implementation NSObject ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc
2005-03-04 15:50:06 +00:00
{
2006-06-15 08:23:49 +00:00
[ [ self description ] appendToXMLRPC : str indent : indent for : rpc ] ;
2005-03-04 15:50:06 +00:00
}
@ end
@ implementation NSString ( GSXMLRPC )
2006-06-15 08:23:49 +00:00
- ( void ) appendToXMLRPC : ( NSMutableString * ) str
2009-02-23 20:42:32 +00:00
indent : ( NSUInteger ) indent
2006-06-15 08:23:49 +00:00
for : ( GSXMLRPC * ) rpc
2005-03-04 15:50:06 +00:00
{
2006-06-15 08:23:49 +00:00
BOOL compact = [ rpc compact ] ;
if ( compact = = YES )
{
[ str appendString : [ self stringByEscapingXML ] ] ;
}
else
{
INDENT ( indent ) ;
[ str appendFormat : @ "<string>%@</string>" , [ self stringByEscapingXML ] ] ;
}
2005-03-04 15:50:06 +00:00
}
@ end
/ *
* Convert incoming XMLRPC value to a normal Objective - C object .
* /
@ interface GSXMLRPC ( Private )
- ( id ) _parseValue : ( GSXMLNode * ) node ;
@ end
@ implementation GSXMLRPC ( Private )
- ( id ) _parseValue : ( GSXMLNode * ) node
{
NSString * name = [ node name ] ;
NSString * str ;
if ( [ name isEqualToString : @ "value" ] )
{
GSXMLNode * type = [ node firstChildElement ] ;
/ *
* A value with no type element is just a string .
* /
if ( type = = nil )
{
name = @ "string" ;
}
else
{
node = type ;
name = [ node name ] ;
}
}
if ( [ name length ] = = 0 )
{
return nil ;
}
if ( [ name isEqualToString : @ "i4" ] || [ name isEqualToString : @ "int" ] )
{
str = [ node content ] ;
if ( str = = nil )
{
[ NSException raise : NSInvalidArgumentException
format : @ "missing %@ value" , name ] ;
}
return [ NSNumber numberWithInt : [ str intValue ] ] ;
}
if ( [ name isEqualToString : @ "string" ] )
{
str = [ node content ] ;
if ( str = = nil )
{
str = @ "" ;
}
return str ;
}
if ( [ name isEqualToString : @ "boolean" ] )
{
char c ;
str = [ node content ] ;
if ( str = = nil )
{
[ NSException raise : NSInvalidArgumentException
format : @ "missing %@ value" , name ] ;
}
c = [ str intValue ] ;
return [ NSNumber numberWithBool : c = = 0 ? NO : YES ] ;
}
if ( [ name isEqualToString : @ "double" ] )
{
str = [ node content ] ;
if ( str = = nil )
{
[ NSException raise : NSInvalidArgumentException
format : @ "missing %@ value" , name ] ;
}
return [ NSNumber numberWithDouble : [ str doubleValue ] ] ;
}
2006-02-22 06:11:25 +00:00
if ( [ name isEqualToString : @ "base64" ] )
2005-03-04 15:50:06 +00:00
{
NSData * d ;
str = [ node content ] ;
if ( str = = nil )
{
[ NSException raise : NSInvalidArgumentException
format : @ "missing %@ value" , name ] ;
}
d = [ str dataUsingEncoding : NSASCIIStringEncoding ] ;
return [ GSMimeDocument decodeBase64 : d ] ;
}
2005-12-13 06:46:42 +00:00
if ( [ name isEqualToString : @ "dateTime.iso8601" ] )
2005-03-04 15:50:06 +00:00
{
2006-06-15 08:23:49 +00:00
NSCalendarDate * d ;
const char * s ;
int year ;
int month ;
int day ;
int hour ;
int minute ;
int second ;
2005-03-04 15:50:06 +00:00
str = [ node content ] ;
if ( str = = nil )
{
[ NSException raise : NSInvalidArgumentException
format : @ "missing %@ value" , name ] ;
}
2006-06-15 08:23:49 +00:00
s = [ str UTF8String ] ;
if ( sscanf ( s , "%04d%02d%02dT%02d:%02d:%02d" ,
& year , & month , & day , & hour , & minute , & second ) ! = 6 )
{
[ NSException raise : NSInvalidArgumentException
format : @ "bad date/time format '%@'" , str ] ;
}
d = [ [ NSCalendarDate alloc ] initWithYear : year
month : month
day : day
hour : hour
minute : minute
second : second
timeZone : tz ] ;
return AUTORELEASE ( d ) ;
2005-03-04 15:50:06 +00:00
}
if ( [ name isEqualToString : @ "array" ] )
{
NSMutableArray * arr = [ NSMutableArray array ] ;
node = [ node firstChildElement ] ;
while ( node ! = nil && [ [ node name ] isEqualToString : @ "data" ] = = NO )
{
node = [ node nextElement ] ;
}
if ( [ [ node name ] isEqualToString : @ "data" ] = = YES )
{
node = [ node firstChildElement ] ;
while ( node ! = nil )
{
if ( [ [ node name ] isEqualToString : @ "value" ] = = YES )
{
id v ;
v = [ self _parseValue : node ] ;
if ( v ! = nil )
{
[ arr addObject : v ] ;
}
}
node = [ node nextElement ] ;
}
}
return arr ;
}
if ( [ name isEqualToString : @ "struct" ] )
{
NSMutableDictionary * dict = [ NSMutableDictionary dictionary ] ;
node = [ node firstChildElement ] ;
while ( node ! = nil )
{
if ( [ [ node name ] isEqualToString : @ "member" ] = = YES )
{
GSXMLNode * member = [ node firstChildElement ] ;
NSString * key = nil ;
id val = nil ;
while ( member ! = nil )
{
if ( [ [ member name ] isEqualToString : @ "name" ] = = YES )
{
key = [ member content ] ;
}
else if ( [ [ member name ] isEqualToString : @ "value" ] = = YES )
{
val = [ self _parseValue : member ] ;
}
if ( key ! = nil && val ! = nil )
{
[ dict setObject : val forKey : key ] ;
break ;
}
member = [ member nextElement ] ;
}
}
node = [ node nextElement ] ;
}
return dict ;
}
[ NSException raise : NSInvalidArgumentException
format : @ "Unknown value type: %@" , name ] ;
return nil ;
}
@ end
/ *
* And now , the actual GSXMLRPC class .
* /
@ implementation GSXMLRPC
2006-06-15 08:23:49 +00:00
- ( NSData * ) buildMethod : ( NSString * ) method
params : ( NSArray * ) params
{
return [ [ self buildMethodCall : method params : params ] dataUsingEncoding :
NSUTF8StringEncoding ] ;
}
2005-03-04 15:50:06 +00:00
- ( NSString * ) buildMethodCall : ( NSString * ) method
params : ( NSArray * ) params
{
NSMutableString * str = [ NSMutableString stringWithCapacity : 1024 ] ;
unsigned c = [ params count ] ;
unsigned i ;
if ( [ method length ] = = 0 )
{
return nil ;
}
else
{
static NSCharacterSet * illegal = nil ;
NSRange r ;
if ( illegal = = nil )
{
NSMutableCharacterSet * tmp = [ NSMutableCharacterSet new ] ;
[ tmp addCharactersInRange : NSMakeRange ( ' 0 ' , 10 ) ] ;
[ tmp addCharactersInRange : NSMakeRange ( ' a ' , 26 ) ] ;
[ tmp addCharactersInRange : NSMakeRange ( ' A ' , 26 ) ] ;
[ tmp addCharactersInString : @ "_.:/" ] ;
[ tmp invert ] ;
illegal = [ tmp copy ] ;
RELEASE ( tmp ) ;
}
r = [ method rangeOfCharacterFromSet : illegal ] ;
if ( r . length > 0 )
{
return nil ; // Bad method name .
}
}
[ str appendString : @ "<?xml version=\" 1.0 \ "?>\n" ] ;
2006-06-15 08:23:49 +00:00
[ str appendString : @ "<methodCall>" ] ;
NL ;
INDENT ( 1 ) ;
[ str appendFormat : @ "<methodName>%@</methodName>" ,
2005-03-04 15:50:06 +00:00
[ method stringByEscapingXML ] ] ;
2006-06-15 08:23:49 +00:00
NL ;
2005-03-04 15:50:06 +00:00
if ( c > 0 )
{
2006-06-15 08:23:49 +00:00
INDENT ( 1 ) ;
[ str appendString : @ "<params>" ] ;
NL ;
2005-03-04 15:50:06 +00:00
for ( i = 0 ; i < c ; i + + )
{
2006-06-15 08:23:49 +00:00
INDENT ( 2 ) ;
[ str appendString : @ "<param>" ] ;
NL ;
INDENT ( 3 ) ;
[ str appendString : @ "<value>" ] ;
NL ;
[ [ params objectAtIndex : i ] appendToXMLRPC : str indent : 3 for : self ] ;
NL ;
INDENT ( 3 ) ;
[ str appendString : @ "</value>" ] ;
2007-02-15 14:21:59 +00:00
NL ;
2006-06-15 08:23:49 +00:00
INDENT ( 2 ) ;
[ str appendString : @ "</param>" ] ;
NL ;
2005-03-04 15:50:06 +00:00
}
2006-06-15 08:23:49 +00:00
INDENT ( 1 ) ;
[ str appendString : @ "</params>" ] ;
NL ;
2005-03-04 15:50:06 +00:00
}
2006-06-15 08:23:49 +00:00
[ str appendString : @ "</methodCall>" ] ;
NL ;
2005-03-04 15:50:06 +00:00
return str ;
}
2009-02-23 20:42:32 +00:00
- ( NSString * ) buildResponseWithFaultCode : ( NSInteger ) code andString : ( NSString * ) s
2005-03-04 15:50:06 +00:00
{
NSMutableString * str = [ NSMutableString stringWithCapacity : 1024 ] ;
NSDictionary * fault ;
fault = [ NSDictionary dictionaryWithObjectsAndKeys :
[ NSNumber numberWithInt : code ] , @ "faultCode" ,
2005-07-14 20:20:31 +00:00
s , @ "faultString" ,
2005-03-04 15:50:06 +00:00
nil ] ;
[ str appendString : @ "<?xml version=\" 1.0 \ "?>\n" ] ;
2006-06-15 08:23:49 +00:00
[ str appendString : @ "<methodResponse>" ] ;
NL ;
INDENT ( 1 ) ;
[ str appendString : @ "<fault>" ] ;
NL ;
INDENT ( 2 ) ;
[ str appendString : @ "<value>" ] ;
NL ;
[ fault appendToXMLRPC : str indent : 3 for : self ] ;
NL ;
INDENT ( 2 ) ;
[ str appendString : @ "</value>" ] ;
NL ;
INDENT ( 1 ) ;
[ str appendString : @ "</fault>" ] ;
NL ;
[ str appendString : @ "</methodResponse>" ] ;
NL ;
2005-03-04 15:50:06 +00:00
return str ;
}
- ( NSString * ) buildResponseWithParams : ( NSArray * ) params
{
NSMutableString * str = [ NSMutableString stringWithCapacity : 1024 ] ;
unsigned c = [ params count ] ;
unsigned i ;
[ str appendString : @ "<?xml version=\" 1.0 \ "?>\n" ] ;
2006-06-15 08:23:49 +00:00
[ str appendString : @ "<methodResponse>" ] ;
NL ;
INDENT ( 1 ) ;
[ str appendString : @ "<params>" ] ;
NL ;
2005-03-04 15:50:06 +00:00
for ( i = 0 ; i < c ; i + + )
{
2006-06-15 08:23:49 +00:00
INDENT ( 2 ) ;
[ str appendString : @ "<param>" ] ;
NL ;
INDENT ( 3 ) ;
[ str appendString : @ "<value>" ] ;
NL ;
[ [ params objectAtIndex : i ] appendToXMLRPC : str indent : 3 for : self ] ;
NL ;
INDENT ( 3 ) ;
[ str appendString : @ "</value>" ] ;
NL ;
INDENT ( 2 ) ;
[ str appendString : @ "</param>" ] ;
NL ;
}
INDENT ( 1 ) ;
[ str appendString : @ "</params>" ] ;
NL ;
[ str appendString : @ "</methodResponse>" ] ;
NL ;
2005-03-04 15:50:06 +00:00
return str ;
}
2006-06-15 08:23:49 +00:00
- ( BOOL ) compact
{
return compact ;
}
2005-03-04 15:50:06 +00:00
- ( void ) dealloc
{
2006-06-15 08:23:49 +00:00
RELEASE ( tz ) ;
2005-03-04 15:50:06 +00:00
if ( timer ! = nil )
{
[ self timeout : nil ] ; // Treat as immediate timeout .
}
2005-03-12 17:38:18 +00:00
# ifdef GNUSTEP
2005-03-04 15:50:06 +00:00
[ handle removeClient : self ] ;
2005-03-12 17:38:18 +00:00
# endif
2005-03-04 15:50:06 +00:00
DESTROY ( result ) ;
2005-03-12 17:38:18 +00:00
# ifdef GNUSTEP
2005-03-04 15:50:06 +00:00
DESTROY ( handle ) ;
2005-03-12 17:38:18 +00:00
# else
if ( connection )
{
[ connection release ] ;
}
[ response release ] ;
[ connectionURL release ] ;
# endif
2005-03-04 15:50:06 +00:00
[ super dealloc ] ;
}
- ( id ) delegate
{
return delegate ;
}
- ( id ) initWithURL : ( NSString * ) url
{
return [ self initWithURL : url certificate : nil privateKey : nil password : nil ] ;
}
- ( id ) initWithURL : ( NSString * ) url
certificate : ( NSString * ) cert
privateKey : ( NSString * ) pKey
password : ( NSString * ) pwd
{
if ( url ! = nil )
{
NS_DURING
{
2005-03-12 17:38:18 +00:00
# ifdef GNUSTEP
2005-03-04 15:50:06 +00:00
NSURL * u = [ NSURL URLWithString : url ] ;
2005-03-12 17:38:18 +00:00
2005-03-04 15:50:06 +00:00
handle = RETAIN ( [ u URLHandleUsingCache : NO ] ) ;
if ( cert ! = nil && pKey ! = nil && pwd ! = nil )
{
[ handle writeProperty : cert
forKey : GSHTTPPropertyCertificateFileKey ] ;
[ handle writeProperty : pKey forKey : GSHTTPPropertyKeyFileKey ] ;
[ handle writeProperty : pwd forKey : GSHTTPPropertyPasswordKey ] ;
}
2005-03-12 17:38:18 +00:00
# else
connectionURL = [ url copy ] ;
connection = nil ;
response = [ [ NSMutableData alloc ] init ] ;
# endif
2005-03-04 15:50:06 +00:00
}
NS_HANDLER
{
DESTROY ( self ) ;
}
NS_ENDHANDLER
}
return self ;
}
- ( id ) init
{
return [ self initWithURL : nil certificate : nil privateKey : nil password : nil ] ;
}
- ( id ) makeMethodCall : ( NSString * ) method
params : ( NSArray * ) params
2009-02-23 20:42:32 +00:00
timeout : ( NSInteger ) seconds
2005-03-04 15:50:06 +00:00
{
NS_DURING
{
if ( [ self sendMethodCall : method params : params timeout : seconds ] = = YES )
{
NSDate * when = AUTORELEASE ( RETAIN ( [ timer fireDate ] ) ) ;
while ( timer ! = nil )
{
[ [ NSRunLoop currentRunLoop ] runMode : NSDefaultRunLoopMode
beforeDate : when ] ;
}
}
}
NS_HANDLER
{
ASSIGN ( result , [ localException description ] ) ;
}
NS_ENDHANDLER
return result ;
}
- ( NSString * ) parseMethod : ( NSData * ) request
params : ( NSMutableArray * ) params
{
GSXPathContext * ctx = nil ;
GSXPathNodeSet * ns = nil ;
2006-04-28 11:06:16 +00:00
GSXMLParser * parser = nil ;
2005-03-04 15:50:06 +00:00
NSString * method ;
[ params removeAllObjects ] ;
NS_DURING
{
GSXMLDocument * doc = nil ;
2006-04-28 11:06:16 +00:00
parser = [ GSXMLParser parserWithData : request ] ;
2005-03-04 15:50:06 +00:00
[ parser substituteEntities : YES ] ;
2006-04-28 11:06:16 +00:00
[ parser saveMessages : YES ] ;
2006-04-28 10:57:47 +00:00
if ( [ parser parse ] = = YES )
{
doc = [ parser document ] ;
ctx = AUTORELEASE ( [ [ GSXPathContext alloc ] initWithDocument : doc ] ) ;
}
2005-03-04 15:50:06 +00:00
}
NS_HANDLER
{
ctx = nil ;
}
NS_ENDHANDLER
if ( ctx = = nil )
{
[ NSException raise : NSInvalidArgumentException
2006-04-28 11:06:16 +00:00
format : @ "Bad Request: parse failed (%@)" , [ parser messages ] ] ;
2005-03-04 15:50:06 +00:00
}
ns = ( GSXPathNodeSet * ) [ ctx evaluateExpression : @ "//methodCall/methodName" ] ;
if ( [ ns count ] ! = 1 )
{
[ NSException raise : NSInvalidArgumentException
format : @ "Badly formatted methodCall" ] ;
}
method = [ [ ns nodeAtIndex : 0 ] content ] ;
ns = ( GSXPathNodeSet * ) [ ctx evaluateExpression :
@ "//methodCall/params/param/value" ] ;
NS_DURING
{
int i ;
for ( i = 0 ; i < [ ns count ] ; i + + )
{
GSXMLNode * node = [ ns nodeAtIndex : i ] ;
2006-06-15 08:23:49 +00:00
id value = [ self _parseValue : node ] ;
2005-03-04 15:50:06 +00:00
2006-06-15 08:23:49 +00:00
if ( value ! = nil )
2005-03-04 15:50:06 +00:00
{
2006-06-15 08:23:49 +00:00
[ params addObject : value ] ;
2005-03-04 15:50:06 +00:00
}
}
}
NS_HANDLER
{
[ params removeAllObjects ] ;
[ localException raise ] ;
}
NS_ENDHANDLER
return method ;
}
2007-10-03 08:54:07 +00:00
- ( NSDictionary * ) parseResponse : ( NSData * ) resp
2005-03-04 15:50:06 +00:00
params : ( NSMutableArray * ) params
{
GSXPathContext * ctx = nil ;
GSXPathNodeSet * ns = nil ;
2006-04-28 11:06:16 +00:00
GSXMLParser * parser = nil ;
2005-03-04 15:50:06 +00:00
id fault = nil ;
[ params removeAllObjects ] ;
NS_DURING
{
GSXMLDocument * doc = nil ;
2007-10-03 08:54:07 +00:00
parser = [ GSXMLParser parserWithData : resp ] ;
2005-03-04 15:50:06 +00:00
[ parser substituteEntities : YES ] ;
2006-04-28 11:06:16 +00:00
[ parser saveMessages : YES ] ;
2006-04-28 10:57:47 +00:00
if ( [ parser parse ] = = YES )
{
doc = [ parser document ] ;
ctx = AUTORELEASE ( [ [ GSXPathContext alloc ] initWithDocument : doc ] ) ;
}
2005-03-04 15:50:06 +00:00
}
NS_HANDLER
{
ctx = nil ;
}
NS_ENDHANDLER
if ( ctx = = nil )
{
[ NSException raise : NSInvalidArgumentException
2006-04-28 11:06:16 +00:00
format : @ "Bad Request: parse failed (%@)" , [ parser messages ] ] ;
2005-03-04 15:50:06 +00:00
}
ns = ( GSXPathNodeSet * ) [ ctx evaluateExpression :
@ "//methodResponse/params/param/value" ] ;
NS_DURING
{
2005-03-12 17:38:18 +00:00
int i ;
2005-03-04 15:50:06 +00:00
if ( [ ns count ] > 0 )
{
for ( i = 0 ; i < [ ns count ] ; i + + )
{
GSXMLNode * node = [ ns nodeAtIndex : i ] ;
2006-06-15 08:23:49 +00:00
id value = [ self _parseValue : node ] ;
2005-03-04 15:50:06 +00:00
2006-06-15 08:23:49 +00:00
if ( value ! = nil )
2005-03-04 15:50:06 +00:00
{
2006-06-15 08:23:49 +00:00
[ params addObject : value ] ;
2005-03-04 15:50:06 +00:00
}
}
}
else
{
ns = ( GSXPathNodeSet * ) [ ctx evaluateExpression :
@ "//methodResponse/fault/value/struct" ] ;
if ( [ ns count ] > 0 )
{
fault = [ self _parseValue : [ ns nodeAtIndex : 0 ] ] ;
}
}
}
NS_HANDLER
{
[ params removeAllObjects ] ;
[ localException raise ] ;
}
NS_ENDHANDLER
return fault ;
}
- ( id ) result
{
if ( timer = = nil )
{
return result ;
}
else
{
return nil ;
}
}
- ( BOOL ) sendMethodCall : ( NSString * ) method
params : ( NSArray * ) params
2009-02-23 20:42:32 +00:00
timeout : ( NSInteger ) seconds
2005-03-04 15:50:06 +00:00
{
NSData * data ;
ASSIGN ( result , @ "unable to send" ) ;
2005-03-12 17:38:18 +00:00
# ifdef GNUSTEP
2005-03-04 15:50:06 +00:00
if ( handle = = nil )
{
return NO ; // Not initialised to send .
}
2005-03-12 17:38:18 +00:00
# endif
2005-03-04 15:50:06 +00:00
if ( timer ! = nil )
{
return NO ; // Send already in progress .
}
2006-06-15 08:23:49 +00:00
data = [ self buildMethod : method params : params ] ;
if ( data = = nil )
2005-03-04 15:50:06 +00:00
{
return NO ;
}
timer = [ NSTimer scheduledTimerWithTimeInterval : seconds
target : self
selector : @ selector ( timeout : )
userInfo : nil
repeats : NO ] ;
2005-03-12 17:38:18 +00:00
# ifdef GNUSTEP
2007-03-14 08:57:20 +00:00
[ handle addClient : self ] ;
2005-03-04 15:50:06 +00:00
[ handle writeProperty : @ "POST" forKey : GSHTTPPropertyMethodKey ] ;
[ handle writeProperty : @ "GSXMLRPC/1.0.0" forKey : @ "User-Agent" ] ;
[ handle writeProperty : @ "text/xml" forKey : @ "Content-Type" ] ;
[ handle writeData : data ] ;
[ handle loadInBackground ] ;
2005-03-12 17:38:18 +00:00
# else
{
NSMutableURLRequest * request ;
request = [ NSMutableURLRequest alloc ] ;
2005-07-23 12:30:21 +00:00
request = [ request initWithURL : [ NSURL URLWithString : connectionURL ] ] ;
2005-03-12 17:38:18 +00:00
[ request setCachePolicy : NSURLRequestReloadIgnoringCacheData ] ;
[ request setHTTPMethod : @ "POST" ] ;
[ request setValue : @ "GSXMLRPC/1.0.0" forHTTPHeaderField : @ "User-Agent" ] ;
[ request setValue : @ "text/xml" forHTTPHeaderField : @ "Content-Type" ] ;
[ request setHTTPBody : data ] ;
connection = [ NSURLConnection alloc ] ;
connection = [ connection initWithRequest : request delegate : self ] ;
[ request release ] ;
}
# endif
2005-03-04 15:50:06 +00:00
return YES ;
}
- ( void ) setDebug : ( BOOL ) flag
{
2005-03-12 17:38:18 +00:00
# ifdef GNUSTEP
2005-03-04 15:50:06 +00:00
if ( [ handle respondsToSelector : _cmd ] = = YES )
{
[ ( id ) handle setDebug : flag ] ;
}
2005-03-12 17:38:18 +00:00
# endif
2005-03-04 15:50:06 +00:00
}
2006-06-15 08:23:49 +00:00
- ( void ) setCompact : ( BOOL ) flag
{
compact = flag ;
}
2005-03-04 15:50:06 +00:00
- ( void ) setDelegate : ( id ) aDelegate
{
delegate = aDelegate ;
}
2006-06-15 08:23:49 +00:00
- ( void ) setTimeZone : ( NSTimeZone * ) timeZone
{
ASSIGN ( tz , timeZone ) ;
}
2005-03-04 15:50:06 +00:00
- ( void ) timeout : ( NSTimer * ) t
{
[ timer invalidate ] ;
timer = nil ;
2005-03-12 17:38:18 +00:00
# ifdef GNUSTEP
2005-03-04 15:50:06 +00:00
[ handle cancelLoadInBackground ] ;
2005-03-12 17:38:18 +00:00
# else
[ connection cancel ] ;
# endif
2005-03-04 15:50:06 +00:00
}
2006-06-15 08:23:49 +00:00
- ( NSTimeZone * ) timeZone
{
if ( tz = = nil )
{
tz = RETAIN ( [ NSTimeZone timeZoneForSecondsFromGMT : 0 ] ) ;
}
return tz ;
}
2005-03-12 17:38:18 +00:00
# ifdef GNUSTEP
2005-03-04 15:50:06 +00:00
- ( void ) URLHandle : ( NSURLHandle * ) sender
resourceDataDidBecomeAvailable : ( NSData * ) newData
{
// Not interesting
}
- ( void ) URLHandle : ( NSURLHandle * ) sender
resourceDidFailLoadingWithReason : ( NSString * ) reason
{
ASSIGN ( result , reason ) ;
[ timer invalidate ] ;
timer = nil ;
2007-03-14 08:57:20 +00:00
# ifdef GNUSTEP
[ handle removeClient : self ] ;
# endif
2005-03-04 15:50:06 +00:00
if ( [ delegate respondsToSelector : @ selector ( completedXMLRPC : ) ] )
{
[ delegate completedXMLRPC : self ] ;
}
}
- ( void ) URLHandleResourceDidBeginLoading : ( NSURLHandle * ) sender
{
// Not interesting
}
- ( void ) URLHandleResourceDidCancelLoading : ( NSURLHandle * ) sender
{
2007-03-08 08:57:58 +00:00
NSString * str ;
2005-03-04 15:50:06 +00:00
[ timer invalidate ] ;
timer = nil ;
2007-03-14 08:57:20 +00:00
# ifdef GNUSTEP
[ handle removeClient : self ] ;
# endif
2007-03-08 08:57:58 +00:00
str = [ handle propertyForKeyIfAvailable : NSHTTPPropertyStatusCodeKey ] ;
if ( str = = nil )
{
str = @ "timeout" ;
}
else
{
str = [ NSString stringWithFormat : @ "HTTP status %@" , str ] ;
}
ASSIGN ( result , str ) ;
2005-03-04 15:50:06 +00:00
if ( [ delegate respondsToSelector : @ selector ( completedXMLRPC : ) ] )
{
[ delegate completedXMLRPC : self ] ;
}
}
- ( void ) URLHandleResourceDidFinishLoading : ( NSURLHandle * ) sender
{
NSMutableArray * params = [ NSMutableArray array ] ;
id fault = nil ;
int code ;
code = [ [ handle propertyForKey : NSHTTPPropertyStatusCodeKey ] intValue ] ;
if ( code = = 200 )
{
2007-10-03 08:54:07 +00:00
NSData * resp = [ handle availableResourceData ] ;
2005-03-04 15:50:06 +00:00
NS_DURING
{
2007-10-03 08:54:07 +00:00
fault = [ self parseResponse : resp params : params ] ;
2005-03-04 15:50:06 +00:00
}
NS_HANDLER
{
fault = [ localException reason ] ;
}
NS_ENDHANDLER
}
else
{
fault = [ NSString stringWithFormat : @ "HTTP status %03d" , code ] ;
}
if ( fault = = nil )
{
ASSIGN ( result , params ) ;
}
else
{
ASSIGN ( result , fault ) ;
}
[ timer invalidate ] ;
timer = nil ;
2007-03-14 08:57:20 +00:00
# ifdef GNUSTEP
[ handle removeClient : self ] ;
# endif
2005-03-04 15:50:06 +00:00
if ( [ delegate respondsToSelector : @ selector ( completedXMLRPC : ) ] )
{
[ delegate completedXMLRPC : self ] ;
}
}
2005-03-12 17:38:18 +00:00
# else / * ! GNUSTEP * /
- ( void ) connection : ( NSURLConnection * ) connection
didCancelAuthenticationChallenge : ( NSURLAuthenticationChallenge * ) challenge
{
/ * DO NOTHING * /
}
- ( void ) connection : ( NSURLConnection * ) connection
didFailWithError : ( NSError * ) error
{
ASSIGN ( result , [ error localizedDescription ] ) ;
[ timer invalidate ] ;
timer = nil ;
if ( [ delegate respondsToSelector : @ selector ( completedXMLRPC : ) ] )
{
[ delegate completedXMLRPC : self ] ;
}
}
- ( void ) connection : ( NSURLConnection * ) connection
didReceiveAuthenticationChallenge : ( NSURLAuthenticationChallenge * ) challenge
{
}
- ( void ) connection : ( NSURLConnection * ) connection didReceiveData : ( NSData * ) data
{
[ response appendData : data ] ;
}
- ( void ) connection : ( NSURLConnection * ) connection
didReceiveResponse : ( NSURLResponse * ) response
{
/ * DO NOTHING * /
}
- ( NSCachedURLResponse * ) connection : ( NSURLConnection * ) connection
willCacheResponse : ( NSCachedURLResponse * ) cachedResponse
{
return nil ;
}
- ( NSURLRequest * ) connection : ( NSURLConnection * ) connection
willSendRequest : ( NSURLRequest * ) request
redirectResponse : ( NSURLResponse * ) redirectResponse
{
return nil ;
}
- ( void ) connectionDidFinishLoading : ( NSURLConnection * ) connection
{
NSMutableArray * params = [ NSMutableArray array ] ;
id fault = nil ;
NS_DURING
{
fault = [ self parseResponse : response params : params ] ;
}
NS_HANDLER
{
fault = [ localException reason ] ;
}
NS_ENDHANDLER
if ( fault = = nil )
{
ASSIGNCOPY ( result , params ) ;
}
else
{
ASSIGNCOPY ( result , fault ) ;
}
[ timer invalidate ] ;
timer = nil ;
if ( [ delegate respondsToSelector : @ selector ( completedXMLRPC : ) ] )
{
[ delegate completedXMLRPC : self ] ;
}
}
# endif
2005-03-04 15:50:06 +00:00
@ end
@ implementation GSXMLRPC ( Delegate )
- ( void ) completedXMLRPC : ( GSXMLRPC * ) sender
{
}
@ end
2005-03-04 16:01:49 +00:00
# endif / * HAVE_LIBXML * /