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