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
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation ; either
version 2 of the License , or ( at your option ) any later version .
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 .
You should have received a copy of the GNU Library General Public
License along with this library ; if not , write to the Free
Software Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 USA .
< 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 >
* /
2003-01-26 19:38:42 +00:00
# include "config.h"
2005-02-23 16:05:09 +00:00
# include "GNUstepBase/preface.h"
2003-09-13 22:42:50 +00:00
# include "GNUstepBase/GSCategories.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
2005-03-05 06:03:03 +00:00
# include "GNUstepBase/GSMime.h"
2003-07-31 23:49:32 +00:00
# include "GNUstepBase/GSXML.h"
2003-02-03 04:15:27 +00:00
# ifndef NeXT_Foundation _LIBRARY
2005-03-05 06:03:03 +00:00
# include < Foundation / NSArray . h >
2002-03-06 15:50:14 +00:00
# include < Foundation / NSBundle . h >
2005-03-05 06:03:03 +00:00
# include < Foundation / NSCalendarDate . h >
2002-03-06 15:50:14 +00:00
# include < Foundation / NSCharacterSet . h >
2005-03-05 06:03:03 +00:00
# include < Foundation / NSData . h >
# include < Foundation / NSDate . h >
# include < Foundation / NSDictionary . h >
# include < Foundation / NSException . h >
2002-03-06 15:50:14 +00:00
# include < Foundation / NSFileManager . h >
2005-03-05 06:03:03 +00:00
# include < Foundation / NSHashTable . h >
2002-06-13 16:02:02 +00:00
# include < Foundation / NSInvocation . h >
2005-03-05 06:03:03 +00:00
# include < Foundation / NSMapTable . h >
# include < Foundation / NSRunLoop . h >
# include < Foundation / NSString . h >
# include < Foundation / NSTimeZone . h >
# include < Foundation / NSTimer . h >
# include < Foundation / NSURL . h >
# include < Foundation / NSURLHandle . h >
# include < Foundation / NSValue . h >
2003-02-03 04:15:27 +00:00
# else
# include < Foundation / Foundation . h >
# endif
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 >
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
# 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 >
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 * /
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 ;
inline static NSString *
2003-05-23 08:58:52 +00:00
UTF8Str ( const unsigned char * bytes )
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
{
2003-05-23 08:58:52 +00:00
unsigned char * buf = NSZoneMalloc ( NSDefaultMallocZone ( ) , length + 1 ) ;
2002-03-06 15:50:14 +00:00
NSString * str ;
memcpy ( buf , bytes , length ) ;
buf [ length ] = ' \ 0 ' ;
str = UTF8Str ( buf ) ;
NSZoneFree ( NSDefaultMallocZone ( ) , buf ) ;
return str ;
}
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
2005-02-16 17:40:48 +00:00
static char * objc_strdup ( const char * from )
{
unsigned len = ( from = = 0 ) ? 1 : ( strlen ( from ) + 1 ) ;
char * to = objc_malloc ( len ) ;
strcpy ( to , from ) ;
return to ;
}
2002-03-06 15:50:14 +00:00
static void
setupCache ( )
{
if ( cacheDone = = NO )
{
cacheDone = YES ;
2005-02-16 17:40:48 +00:00
xmlMemSetup ( objc_free , objc_malloc , objc_realloc , objc_strdup ) ;
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
2003-05-23 08:58:52 +00:00
loadEntityFunction ( const unsigned char * url , const unsigned char * eid ,
xmlParserCtxtPtr ctxt ) ;
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" ) ;
}
}
+ ( int ) 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 )
{
2004-10-31 13:02:58 +00:00
return ( int ) key ;
2002-05-22 14:23:17 +00:00
}
}
return -1 ;
2002-03-06 15:50:14 +00:00
}
2002-05-22 14:23:17 +00:00
+ ( NSString * ) descriptionFromType : ( int ) type
{
2002-05-23 15:58:15 +00:00
NSString * desc = ( NSString * ) NSMapGet ( attrNames , ( void * ) type ) ;
2002-05-22 14:23:17 +00:00
return desc ;
}
- ( int ) type
{
return ( int ) ( ( xmlAttrPtr ) ( lib ) ) -> atype ;
}
- ( NSString * ) typeDescription
{
NSString * desc = ( NSString * ) NSMapGet ( attrNames , ( void * ) [ self type ] ) ;
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
{
2002-05-23 15:58:15 +00:00
void * data = xmlNewDoc ( [ version UTF8String ] ) ;
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 ) ;
2005-02-16 17:40:48 +00:00
objc_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
}
- ( unsigned ) hash
{
2004-10-31 13:02:58 +00:00
return ( ( ( unsigned ) lib ) > > 3 ) ;
2002-03-06 15:50:14 +00:00
}
- ( id ) init
{
NSLog ( @ "GSXMLDocument: calling -init is not legal" ) ;
RELEASE ( self ) ;
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 :
xmlNewDocNode ( lib , [ ns lib ] , [ name UTF8String ] , [ content UTF8String ] )
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
}
/ * *
2002-05-22 16:26:42 +00:00
* Sets the root node of the document .
2002-03-06 15:50:14 +00:00
* /
- ( GSXMLNode * ) setRoot : ( GSXMLNode * ) node
{
void * nodeLib = [ node lib ] ;
void * oldRoot = xmlDocSetRootElement ( lib , nodeLib ) ;
2002-05-22 16:26:42 +00:00
GSXMLNode * n ;
if ( oldRoot = = NULL )
return nil ;
2002-03-06 15:50:14 +00:00
2002-05-22 16:26:42 +00:00
n = [ GSXMLNode alloc ] ;
n = [ n _initFrom : nodeLib parent : self ] ;
return AUTORELEASE ( n ) ;
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 .
* /
+ ( NSString * ) descriptionFromType : ( int ) type
{
2002-05-23 15:58:15 +00:00
NSString * desc = ( NSString * ) NSMapGet ( nsNames , ( void * ) 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 >
* /
+ ( int ) typeFromDescription : ( NSString * ) desc
{
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 )
{
2004-10-31 13:02:58 +00:00
return ( int ) 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 ] ;
}
2002-03-06 15:50:14 +00:00
- ( unsigned ) hash
{
2004-10-31 13:02:58 +00:00
return ( ( ( unsigned ) 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" ) ;
RELEASE ( self ) ;
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
* /
- ( int ) type
{
return ( int ) ( ( xmlNsPtr ) ( lib ) ) -> type ;
}
/ * *
* Return string representation of the type of the namespace .
* /
- ( NSString * ) typeDescription
{
NSString * desc = ( NSString * ) NSMapGet ( nsNames , ( void * ) [ self type ] ) ;
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 .
* /
+ ( NSString * ) descriptionFromType : ( int ) type
{
2002-05-23 15:58:15 +00:00
NSString * desc = ( NSString * ) NSMapGet ( nodeNames , ( void * ) 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 >
* /
2002-03-06 15:50:14 +00:00
+ ( int ) typeFromDescription : ( NSString * ) desc
{
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 )
{
2004-10-31 13:02:58 +00:00
return ( int ) 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 ) ;
}
if ( ( int ) ptr -> type = = XML_TEXT _NODE )
{
return @ "" ;
2002-03-06 15:50:14 +00:00
}
2003-04-02 04:51:54 +00:00
else if ( ( int ) ptr -> type = = XML_ELEMENT _NODE )
{
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
2004-10-03 09:11:15 +00:00
* escaped character information ( like the standard five entities & amp ; lt ; ,
* & 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 ;
}
}
- ( unsigned ) hash
{
2004-10-31 13:02:58 +00:00
return ( ( ( unsigned ) 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" ) ;
RELEASE ( self ) ;
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
{
if ( ( int ) ( ( xmlNodePtr ) ( lib ) ) -> type = = XML_ELEMENT _NODE )
{
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
{
if ( ( int ) ( ( xmlNodePtr ) ( lib ) ) -> type = = XML_TEXT _NODE )
{
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 ;
l = xmlNewProp ( ( xmlNodePtr ) [ self lib ] , [ name cString ] , [ value cString ] ) ;
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 :
xmlNewTextChild ( lib , [ ns lib ] , [ name UTF8String ] , [ content UTF8String ] )
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 :
xmlAddChild ( ( xmlNodePtr ) lib , xmlNewText ( [ content UTF8String ] ) )
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 :
xmlAddChild ( ( xmlNodePtr ) lib , xmlNewComment ( [ content UTF8String ] ) )
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 ;
data = xmlNewNs ( ( xmlNodePtr ) lib , [ href UTF8String ] , [ prefix UTF8String ] ) ;
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 :
2002-05-11 03:06:51 +00:00
xmlAddChild ( ( xmlNodePtr ) lib , xmlNewPI ( [ name UTF8String ] ,
2002-05-22 16:26:42 +00:00
[ content UTF8String ] ) ) parent : self ] ;
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
/ * *
* Returns the next element node , skipping past any oyther node types
* ( 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
{
2002-05-22 14:23:17 +00:00
xmlSetProp ( lib , [ key UTF8String ] , [ value UTF8String ] ) ;
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
* /
- ( int ) type
{
return ( int ) ( ( xmlNodePtr ) ( lib ) ) -> type ;
}
/ * *
* Return node type as a string .
* /
- ( NSString * ) typeDescription
{
NSString * desc = ( NSString * ) NSMapGet ( nodeNames , ( void * ) [ self type ] ) ;
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
2004-01-12 19:42:18 +00:00
static NSHashTable * warnings = 0 ;
2003-08-08 14:55:23 +00:00
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 ( ) ;
warnings = NSCreateHashTable ( NSNonRetainedObjectHashCallBacks , 0 ) ;
}
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 ] ) ;
}
/ * *
* 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 ;
case NSISOCyrillicStringEncoding :
NSLog ( @ "NSISOCyrillicStringEncoding not supported for XML" ) ; // ? ?
break ;
case NSNonLossyASCIIStringEncoding :
case NSASCIIStringEncoding :
case GSUndefinedEncoding :
default :
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 ) .
if ( ctxt -> input ! = NULL ) ctxt -> input -> cur = "" ;
}
}
2004-05-18 09:55:33 +00:00
/ * *
* If executed during a parse operation , returns the current column number .
* /
- ( int ) columnNumber
{
return xmlSAX2GetColumnNumber ( lib ) ;
}
2002-03-06 15:50:14 +00:00
- ( void ) dealloc
{
2003-08-08 14:55:23 +00:00
NSHashRemove ( warnings , self ) ;
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 .
* /
- ( int ) errNo
{
return ( ( xmlParserCtxtPtr ) lib ) -> errNo ;
}
/ * *
* Sets whether warnings are generated .
* /
- ( BOOL ) getWarnings : ( BOOL ) yesno
{
2003-08-08 14:55:23 +00:00
BOOL old = YES ;
if ( NSHashGet ( warnings , self ) = = nil )
{
old = NO ;
}
if ( yesno = = YES && old = = NO )
{
NSHashInsert ( warnings , self ) ;
}
else if ( yesno = = NO && old = = YES )
{
NSHashRemove ( warnings , self ) ;
}
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" ) ;
RELEASE ( self ) ;
return nil ;
}
[ saxHandler _setParser : self ] ;
if ( [ self _initLibXML ] = = NO )
{
RELEASE ( self ) ;
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" ) ;
RELEASE ( self ) ;
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" ) ;
RELEASE ( self ) ;
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" ) ;
RELEASE ( self ) ;
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 .
* /
- ( int ) lineNumber
{
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
{
2003-05-23 08:58:52 +00:00
const unsigned 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 ;
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
{
2003-08-08 14:55:23 +00:00
xmlExternalEntityLoader oldLoader ;
int oldWarnings ;
2004-10-24 12:29:31 +00:00
if ( lib = = NULL || ( ( xmlParserCtxtPtr ) lib ) -> disableSAX ! = 0 )
{
return ; // Parsing impossible or disabled .
}
2003-08-08 14:55:23 +00:00
oldLoader = xmlGetExternalEntityLoader ( ) ;
oldWarnings = xmlGetWarningsDefaultValue ;
NS_DURING
{
if ( NSHashGet ( warnings , self ) = = nil )
{
xmlGetWarningsDefaultValue = 0 ;
}
else
{
xmlGetWarningsDefaultValue = 1 ;
}
xmlSetExternalEntityLoader ( ( xmlExternalEntityLoader ) loadEntityFunction ) ;
xmlParseChunk ( lib , [ data bytes ] , [ data length ] , data = = nil ) ;
xmlSetExternalEntityLoader ( oldLoader ) ;
xmlGetWarningsDefaultValue = oldWarnings ;
}
NS_HANDLER
{
xmlSetExternalEntityLoader ( oldLoader ) ;
xmlGetWarningsDefaultValue = oldWarnings ;
[ localException raise ] ;
}
NS_ENDHANDLER
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
2003-05-23 08:58:52 +00:00
loadEntityFunction ( const unsigned char * url , const unsigned char * eid ,
xmlParserCtxtPtr ctx )
2002-03-06 15:50:14 +00:00
{
extern xmlParserInputPtr xmlNewInputFromFile ( ) ;
NSString * file ;
xmlParserInputPtr ret = 0 ;
NSString * entityId ;
NSString * location ;
NSArray * components ;
NSMutableString * local ;
unsigned count ;
unsigned index ;
NSCAssert ( ctx , @ "No Context" ) ;
if ( eid = = 0 || url = = 0 )
return 0 ;
entityId = UTF8Str ( eid ) ;
location = UTF8Str ( url ) ;
components = [ location pathComponents ] ;
local = [ NSMutableString string ] ;
/ *
* 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 ] ] ;
}
/ *
* 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 ] ;
}
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 ] ;
NSMutableString * name ;
NSString * found ;
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 ] ;
}
2003-04-28 02:29:49 +00:00
found = [ NSBundle pathForLibraryResource : name
2002-03-06 15:50:14 +00:00
ofType : @ "dtd"
inDirectory : @ "DTDs" ] ;
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 )
{
file = [ [ NSBundle mainBundle ] pathForResource : local
ofType : @ ""
inDirectory : @ "DTDs" ] ;
if ( file = = nil )
{
2003-04-28 02:29:49 +00:00
file = [ NSBundle pathForLibraryResource : local
2002-03-06 15:50:14 +00:00
ofType : @ ""
inDirectory : @ "DTDs" ] ;
}
}
}
if ( [ file length ] > 0 )
{
ret = xmlNewInputFromFile ( ctx , [ file fileSystemRepresentation ] ) ;
}
else
{
NSLog ( @ "don't know how to load entity '%s' id '%s'" , url , eid ) ;
}
return ret ;
}
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
{
2004-06-24 09:26:01 +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
{
2004-06-24 09:26:01 +00:00
NSString * key = UTF8Str ( atts [ i + + ] ) ;
NSString * obj = UTF8Str ( atts [ i + + ] ) ;
[ 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 )
{
2004-06-24 09:26:01 +00:00
NSMutableDictionary * dict ;
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 ) ;
dict = [ NSMutableDictionary dictionary ] ;
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
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 ] ) ;
[ dict setObject : obj forKey : key ] ;
2004-05-18 09:55:33 +00:00
}
}
2004-06-24 09:26:01 +00:00
[ HANDLER startElement : elem
prefix : UTF8Str ( prefix )
href : UTF8Str ( href )
attributes : dict ] ;
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 )
data : UTF8Str ( 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 ) ;
2004-04-06 19:17:52 +00:00
estr = [ [ NSString alloc ] initWithFormat : UTF8Str ( msg ) arguments : args ] ;
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 ) ;
2004-04-06 19:14:33 +00:00
estr = [ [ NSString alloc ] initWithFormat : UTF8Str ( msg ) arguments : args ] ;
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 ) ;
2004-04-06 19:17:52 +00:00
estr = [ [ NSString alloc ] initWithFormat : UTF8Str ( msg ) arguments : args ] ;
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" ) ;
RELEASE ( self ) ;
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
{
if ( parser = = nil && lib ! = NULL )
{
free ( lib ) ;
}
[ 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 .
* /
- ( int ) isStandalone
{
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
}
/ * *
* 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
type : ( int ) type
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
type : ( int ) type
2002-03-06 15:50:14 +00:00
typeDefValue : ( int ) defType
defaultValue : ( NSString * ) value
{
}
/ * *
* An element definition has been parsed .
* /
- ( void ) elementDecl : ( NSString * ) name
type : ( int ) type
{
}
/ * *
* 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
colNumber : ( int ) colNumber
lineNumber : ( int ) lineNumber
{
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
colNumber : ( int ) colNumber
lineNumber : ( int ) lineNumber
{
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
colNumber : ( int ) colNumber
lineNumber : ( int ) lineNumber
{
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 .
* /
- ( int ) hasInternalSubset
{
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 .
* /
- ( int ) hasExternalSubset
{
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
{
lib = ( xmlSAXHandler * ) malloc ( sizeof ( xmlSAXHandler ) ) ;
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 ;
# else
LIB -> startElement = ( void * ) startElementFunction ;
LIB -> endElement = ( void * ) endElementFunction ;
# endif
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
{
lib = ( xmlSAXHandler * ) malloc ( sizeof ( xmlSAXHandler ) ) ;
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 : ) ;
2005-02-22 11:22:44 +00:00
# else
2004-06-24 09:26:01 +00:00
SETCB ( startElement , startElement : attributes : ) ;
SETCB ( endElement , endElement : ) ;
2005-02-22 11:22:44 +00:00
# endif
2004-06-24 09:26:01 +00:00
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 : ) ;
SETCB ( notationDecl , notationDecl : public : ) ;
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 ;
2002-03-06 15:50:14 +00:00
lib = ( xmlSAXHandler * ) malloc ( sizeof ( htmlSAXHandler ) ) ;
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
{
RELEASE ( self ) ;
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 ;
2003-07-11 18:53:48 +00:00
return [ NSString_class stringWithUTF8String : 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 .
* /
- ( unsigned int ) count
{
if ( xmlXPathNodeSetIsEmpty ( ( ( xmlXPathObject * ) _lib ) -> nodesetval ) )
{
return 0 ;
}
return xmlXPathNodeSetGetLength ( ( ( xmlXPathObject * ) _lib ) -> nodesetval ) ;
}
/ * *
* Deprecated
* /
2002-08-27 15:46:15 +00:00
- ( unsigned int ) length
{
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 .
* /
2002-08-27 15:46:15 +00:00
- ( GSXMLNode * ) nodeAtIndex : ( unsigned ) index
{
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 ,
( int ) 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
{
2003-07-11 18:53:48 +00:00
return [ NSString_class stringWithFormat : @ "NodeSet (count %d)" , [ self count ] ] ;
2002-08-27 15:46:15 +00:00
}
@ end
2002-11-22 10:47:48 +00:00
/ * *
* < p > Use of the GSXPathContext claass 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 .
* < / 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
2002-08-27 15:46:15 +00:00
comp = xmlXPathCompile ( [ XPathExpression UTF8String ] ) ;
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 ] ;
AUTORELEASE ( result ) ;
}
2002-08-27 15:46:15 +00:00
xmlXPathFreeCompExpr ( comp ) ;
return result ;
}
- ( 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 ;
xmlParser = [ GSXMLParser parserWithData : xmlData ] ;
[ xmlParser parse ] ;
xml = [ xmlParser document ] ;
ssParser = [ GSXMLParser parserWithData : xsltStylesheet ] ;
[ ssParser parse ] ;
ss = [ ssParser document ] ;
newdoc = [ xml xsltTransform : 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 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 ] ;
AUTORELEASE ( newdoc ) ;
}
}
/ *
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
2002-03-06 15:50:14 +00:00
# include < Foundation / NSObjCRuntime . h >
# include < Foundation / NSCoder . h >
2002-12-03 02:50:07 +00:00
# include < Foundation / NSInvocation . h >
# include < Foundation / NSString . h >
2003-02-03 04:15:27 +00:00
# else
# include < Foundation / Foundation . h >
# 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 ) ) ;
RELEASE ( self ) ;
return nil ;
}
- ( id ) initWithCoder : ( NSCoder * ) aCoder
{
NSLog ( @ "Not built with libxml ... %@ unusable in %@" ,
NSStringFromClass ( [ self class ] ) , NSStringFromSelector ( _cmd ) ) ;
RELEASE ( self ) ;
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 ] ;
if ( c >= 0 x20 || c = = 0 x9 || c = = 0 xa || c = = 0 xd )
{
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 ;
}
}
}
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 ] ;
if ( c >= 0 x20 || c = = 0 x9 || c = = 0 xa || c = = 0 xd )
{
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 ) ;
AUTORELEASE ( self ) ;
}
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 ;
if ( [ s hasPrefix : @ "�x" ] || [ s hasPrefix : @ "�X" ] )
{
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 )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent ;
@ end
@ interface NSData ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent ;
@ end
@ interface NSDate ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent ;
@ end
@ interface NSDictionary ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent ;
@ end
@ interface NSObject ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent ;
@ end
@ interface NSNumber ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent ;
@ end
@ interface NSString ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent ;
@ 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 ] ] ;
}
}
/ *
* Implementation of categories to output objects for XMLRPC
* /
@ implementation NSArray ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent
{
unsigned i ;
unsigned c = [ self count ] ;
indentation ( indent + + , str ) ;
[ str appendString : @ "<array>\n" ] ;
indentation ( indent + + , str ) ;
[ str appendString : @ "<data>\n" ] ;
for ( i = 0 ; i < c ; i + + )
{
id value = [ self objectAtIndex : i ] ;
indentation ( indent + + , str ) ;
[ str appendString : @ "<value>\n" ] ;
[ value appendToXMLRPC : str indent : indent ] ;
[ str appendString : @ "\n" ] ;
indentation ( - - indent , str ) ;
[ str appendString : @ "</value>\n" ] ;
}
indentation ( - - indent , str ) ;
[ str appendString : @ "</data>\n" ] ;
indentation ( - - indent , str ) ;
[ str appendString : @ "</array>" ] ;
}
@ end
@ implementation NSData ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent
{
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 )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent
{
static NSTimeZone * z = nil ;
NSString * s ;
if ( z = = nil )
{
s = RETAIN ( [ NSTimeZone timeZoneForSecondsFromGMT : 0 ] ) ;
}
s = [ self descriptionWithCalendarFormat : @ "%Y%m%dT%H:%M:%S"
timeZone : z
locale : nil ] ;
[ str appendString : @ "<dateTime.iso8601>" ] ;
[ str appendString : s ] ;
[ str appendString : @ "</dateTime.iso8601>" ] ;
}
@ end
@ implementation NSDictionary ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent
{
NSEnumerator * kEnum = [ self keyEnumerator ] ;
NSString * key ;
indentation ( indent + + , str ) ;
[ str appendString : @ "<struct>\n" ] ;
while ( ( key = [ kEnum nextObject ] ) )
{
id value = [ self objectForKey : key ] ;
indentation ( indent + + , str ) ;
[ str appendString : @ "<member>\n" ] ;
indentation ( indent , str ) ;
[ str appendString : @ "<name>" ] ;
[ str appendString : [ [ key description ] stringByEscapingXML ] ] ;
[ str appendString : @ "</name>\n" ] ;
indentation ( indent + + , str ) ;
[ str appendString : @ "<value>\n" ] ;
[ value appendToXMLRPC : str indent : indent - - ] ;
[ str appendString : @ "\n" ] ;
indentation ( indent - - , str ) ;
[ str appendString : @ "</value>\n" ] ;
indentation ( indent , str ) ;
[ str appendString : @ "</member>\n" ] ;
}
indentation ( - - indent , str ) ;
[ str appendString : @ "</struct>" ] ;
}
@ end
@ implementation NSNumber ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent
{
const char * t = [ self objCType ] ;
indentation ( indent , str ) ;
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
{
[ str appendFormat : @ "<i4>%d</i4>" , i ] ;
}
}
else
{
[ str appendFormat : @ "<double>%f</double>" , [ self doubleValue ] ] ;
}
}
@ end
@ implementation NSObject ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent
{
[ [ self description ] appendToXMLRPC : str indent : indent ] ;
}
@ end
@ implementation NSString ( GSXMLRPC )
- ( void ) appendToXMLRPC : ( NSMutableString * ) str indent : ( unsigned ) indent
{
indentation ( indent , str ) ;
[ str appendFormat : @ "<string>%@</string>" , [ self stringByEscapingXML ] ] ;
}
@ 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 ] ] ;
}
if ( [ name isEqualToString : @ "data" ] )
{
NSData * d ;
str = [ node content ] ;
if ( str = = nil )
{
[ NSException raise : NSInvalidArgumentException
format : @ "missing %@ value" , name ] ;
}
d = [ str dataUsingEncoding : NSASCIIStringEncoding ] ;
return [ GSMimeDocument decodeBase64 : d ] ;
}
if ( [ name isEqualToString : @ "date" ] )
{
str = [ node content ] ;
if ( str = = nil )
{
[ NSException raise : NSInvalidArgumentException
format : @ "missing %@ value" , name ] ;
}
return [ NSCalendarDate dateWithString : str
calendarFormat : @ "%Y%m%dT%H:%M:%S"
locale : nil ] ;
}
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
- ( 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" ] ;
[ str appendString : @ "<methodCall>\n" ] ;
[ str appendFormat : @ " <methodName>%@</methodName>\n" ,
[ method stringByEscapingXML ] ] ;
if ( c > 0 )
{
[ str appendString : @ " <params>\n" ] ;
for ( i = 0 ; i < c ; i + + )
{
[ str appendString : @ " <param>\n" ] ;
[ str appendString : @ " <value>\n" ] ;
[ [ params objectAtIndex : i ] appendToXMLRPC : str indent : 3 ] ;
[ str appendString : @ "\n </value>\n" ] ;
[ str appendString : @ " </param>\n" ] ;
}
[ str appendString : @ " </params>\n" ] ;
}
[ str appendString : @ "</methodCall>\n" ] ;
return str ;
}
- ( NSString * ) buildResponseWithFaultCode : ( int ) code andString : ( NSString * ) s
{
NSMutableString * str = [ NSMutableString stringWithCapacity : 1024 ] ;
NSDictionary * fault ;
fault = [ NSDictionary dictionaryWithObjectsAndKeys :
[ NSNumber numberWithInt : code ] , @ "faultCode" ,
[ s stringByEscapingXML ] , @ "faultString" ,
nil ] ;
[ str appendString : @ "<?xml version=\" 1.0 \ "?>\n" ] ;
[ str appendString : @ "<methodResponse>\n" ] ;
[ str appendString : @ " <fault>\n" ] ;
[ str appendString : @ " <value>\n" ] ;
[ fault appendToXMLRPC : str indent : 3 ] ;
[ str appendString : @ "\n </value>\n" ] ;
[ str appendString : @ " </fault>\n" ] ;
[ str appendString : @ "</methodResponse>\n" ] ;
return str ;
}
- ( NSString * ) buildResponseWithParams : ( NSArray * ) params
{
NSMutableString * str = [ NSMutableString stringWithCapacity : 1024 ] ;
unsigned c = [ params count ] ;
unsigned i ;
[ str appendString : @ "<?xml version=\" 1.0 \ "?>\n" ] ;
[ str appendString : @ "<methodResponse>\n" ] ;
[ str appendString : @ " <params>\n" ] ;
for ( i = 0 ; i < c ; i + + )
{
[ str appendString : @ " <param>\n" ] ;
[ str appendString : @ " <value>\n" ] ;
[ [ params objectAtIndex : i ] appendToXMLRPC : str indent : 3 ] ;
[ str appendString : @ "\n </value>\n" ] ;
[ str appendString : @ " </param>\n" ] ;
}
[ str appendString : @ " </params>\n" ] ;
[ str appendString : @ "</methodResponse>\n" ] ;
return str ;
}
- ( void ) dealloc
{
if ( timer ! = nil )
{
[ self timeout : nil ] ; // Treat as immediate timeout .
}
[ handle removeClient : self ] ;
DESTROY ( result ) ;
DESTROY ( handle ) ;
[ 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
{
NSURL * u = [ NSURL URLWithString : url ] ;
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 ] ;
}
[ handle addClient : self ] ;
}
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
timeout : ( int ) seconds
{
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 ;
NSString * method ;
[ params removeAllObjects ] ;
NS_DURING
{
GSXMLParser * parser = [ GSXMLParser parserWithData : request ] ;
GSXMLDocument * doc = nil ;
[ parser substituteEntities : YES ] ;
[ parser parse ] ;
doc = [ parser document ] ;
ctx = AUTORELEASE ( [ [ GSXPathContext alloc ] initWithDocument : doc ] ) ;
}
NS_HANDLER
{
ctx = nil ;
}
NS_ENDHANDLER
if ( ctx = = nil )
{
[ NSException raise : NSInvalidArgumentException
format : @ "Bad Request: parse failed" ] ;
}
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 ] ;
if ( [ [ node name ] isEqualToString : @ "value" ]
&& [ node firstChildElement ] ! = nil )
{
id value = [ self _parseValue : [ node firstChildElement ] ] ;
if ( value ! = nil )
{
[ params addObject : value ] ;
}
}
}
}
NS_HANDLER
{
[ params removeAllObjects ] ;
[ localException raise ] ;
}
NS_ENDHANDLER
return method ;
}
- ( NSDictionary * ) parseResponse : ( NSData * ) response
params : ( NSMutableArray * ) params
{
GSXPathContext * ctx = nil ;
GSXPathNodeSet * ns = nil ;
id fault = nil ;
[ params removeAllObjects ] ;
NS_DURING
{
GSXMLParser * parser = [ GSXMLParser parserWithData : response ] ;
GSXMLDocument * doc = nil ;
[ parser substituteEntities : YES ] ;
[ parser parse ] ;
doc = [ parser document ] ;
ctx = AUTORELEASE ( [ [ GSXPathContext alloc ] initWithDocument : doc ] ) ;
}
NS_HANDLER
{
ctx = nil ;
}
NS_ENDHANDLER
if ( ctx = = nil )
{
[ NSException raise : NSInvalidArgumentException
format : @ "Bad Response: parse failed" ] ;
}
ns = ( GSXPathNodeSet * ) [ ctx evaluateExpression :
@ "//methodResponse/params/param/value" ] ;
NS_DURING
{
int i ;
if ( [ ns count ] > 0 )
{
for ( i = 0 ; i < [ ns count ] ; i + + )
{
GSXMLNode * node = [ ns nodeAtIndex : i ] ;
if ( [ [ node name ] isEqualToString : @ "value" ]
&& [ node firstChildElement ] ! = nil )
{
id value = [ self _parseValue : [ node firstChildElement ] ] ;
if ( value ! = nil )
{
[ params addObject : value ] ;
}
}
}
}
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
timeout : ( int ) seconds
{
NSString * xml ;
NSData * data ;
ASSIGN ( result , @ "unable to send" ) ;
if ( handle = = nil )
{
return NO ; // Not initialised to send .
}
if ( timer ! = nil )
{
return NO ; // Send already in progress .
}
xml = [ self buildMethodCall : method params : params ] ;
if ( xml = = nil )
{
return NO ;
}
data = [ xml dataUsingEncoding : NSUTF8StringEncoding ] ;
timer = [ NSTimer scheduledTimerWithTimeInterval : seconds
target : self
selector : @ selector ( timeout : )
userInfo : nil
repeats : NO ] ;
[ 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 ] ;
return YES ;
}
- ( void ) setDebug : ( BOOL ) flag
{
if ( [ handle respondsToSelector : _cmd ] = = YES )
{
[ ( id ) handle setDebug : flag ] ;
}
}
- ( void ) setDelegate : ( id ) aDelegate
{
delegate = aDelegate ;
}
- ( void ) timeout : ( NSTimer * ) t
{
[ timer invalidate ] ;
timer = nil ;
[ handle cancelLoadInBackground ] ;
}
- ( void ) URLHandle : ( NSURLHandle * ) sender
resourceDataDidBecomeAvailable : ( NSData * ) newData
{
// Not interesting
}
- ( void ) URLHandle : ( NSURLHandle * ) sender
resourceDidFailLoadingWithReason : ( NSString * ) reason
{
ASSIGN ( result , reason ) ;
[ timer invalidate ] ;
timer = nil ;
if ( [ delegate respondsToSelector : @ selector ( completedXMLRPC : ) ] )
{
[ delegate completedXMLRPC : self ] ;
}
}
- ( void ) URLHandleResourceDidBeginLoading : ( NSURLHandle * ) sender
{
// Not interesting
}
- ( void ) URLHandleResourceDidCancelLoading : ( NSURLHandle * ) sender
{
ASSIGN ( result , @ "timeout" ) ;
[ timer invalidate ] ;
timer = nil ;
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 )
{
NSData * response = [ handle availableResourceData ] ;
NS_DURING
{
fault = [ self parseResponse : response params : params ] ;
}
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 ;
if ( [ delegate respondsToSelector : @ selector ( completedXMLRPC : ) ] )
{
[ delegate completedXMLRPC : self ] ;
}
}
@ end
@ implementation GSXMLRPC ( Delegate )
- ( void ) completedXMLRPC : ( GSXMLRPC * ) sender
{
}
@ end
2005-03-04 16:01:49 +00:00
# endif / * HAVE_LIBXML * /