Preliminary XML support

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@7470 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 2000-09-11 11:59:33 +00:00
parent 30915f3915
commit 86678d57f8
13 changed files with 1803 additions and 17 deletions

View file

@ -1,6 +1,14 @@
2000-09-11 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/gnustep/base/GSXML.h: new classes for parsing XML
* Source/GSXML.m: new classes for parsing XML
* Source/Makefile.preamble: Define HAVE_LIBXML if appropriate.
* Source/GNUMakefile: Build new classes if appropriate.
* Tools/Makefile.preamble: Removed libxml stuff - now done globally.
2000-09-10 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSCalnedarDate: ([-initWithString:calendarFormat:locale:])
* Source/NSCalendarDate: ([-initWithString:calendarFormat:locale:])
modify parsing to be more tolerant of numeric fields that are smaller
than the expected size, but warn about unexpected format.

View file

@ -0,0 +1,261 @@
/* Implementation for GSPropertyList
Written by: Michael Pakhantsov <mishel@berest.dp.ua>
Date: Jule 2000
*/
#ifndef __GSXML_H__
#define __GSXML_H__
#define GSXML_DEBUG 1
//#undef GSXML_DEBUG
#include <libxml/tree.h>
#include <libxml/entities.h>
#include <Foundation/NSObject.h>
#include <Foundation/NSString.h>
#include <Foundation/NSDictionary.h>
@class GSXMLAttribute;
@class GSXMLDocument;
@class GSXMLHandler;
@class GSXMLNamespace;
@class GSXMLNode;
@class GSSAXHandler;
typedef xmlElementType GSXMLElementType;
typedef xmlEntityType GSXMLEntityType;
typedef xmlAttributeType GSXMLAttributeType;
typedef xmlElementTypeVal GSXMLElementTypeVal;
typedef xmlNsType GSXMLNamespaceType;
#ifdef GSXML_DEBUG
#define DP(message) printf("DEBUG: %s\n", message)
#define TEST_ALLOC_ALL printf("test allocation\n%s", GSDebugAllocationListAll())
#define TEST_ALLOC(msg) printf(" %s test allocation list\n%s", msg, GSDebugAllocationList(YES))
#endif
@interface GSXMLDocument : NSObject
{
void *lib; // pointer to xmllib pointer of xmlDoc struct
BOOL native;
}
+ (GSXMLDocument*) documentWithVersion: (NSString*)version;
+ (GSXMLDocument*) documentFrom: (void*)data;
- (id) initWithVersion: (NSString*)version;
- (id) initFrom: (void*)data;
- (void*) lib;
- (GSXMLNode*) root;
- (GSXMLNode*) setRoot: (GSXMLNode*)node;
- (GSXMLNode*) makeNode: (GSXMLNamespace*)ns
name: (NSString*)name
content: (NSString*)content;
- (NSString*) version;
- (NSString*) encoding;
- (void) save: (NSString*) filename;
@end
@interface GSXMLNamespace : NSObject
{
void *lib; /* pointer to struct xmlNs in the gnome xmllib */
BOOL native;
}
+ (GSXMLNamespace*) namespace: (GSXMLNode*)node
href: (NSString*)href
prefix: (NSString*)prefix;
+ (GSXMLNamespace*) namespaceFrom: (void*)data;
- (id) initWithNode: (GSXMLNode*)node
href: (NSString*)href
prefix: (NSString*)prefix;
- (id) initFrom: (void*)data;
- (NSString*) href;
- (void*) lib;
- (GSXMLNamespace*) next;
- (NSString*) prefix;
- (GSXMLNamespaceType) type;
@end
/* XML Node */
@interface GSXMLNode : NSObject
{
void *lib; /* pointer to struct xmlNode from libxml */
BOOL native;
}
+ (GSXMLNode*) nodeWithNamespace: (GSXMLNamespace*)ns name: (NSString*)name;
+ (GSXMLNode*) nodeFrom: (void*) data;
- (id) initWithNamespace: (GSXMLNamespace*)ns name: (NSString*)name;
- (id) initFrom: (void*) data;
- (GSXMLNode*) children;
- (NSString*) content;
- (GSXMLDocument*) doc;
- (void*) lib;
- (NSString*) name;
- (GSXMLNode*) next;
- (GSXMLNamespace*) ns;
- (GSXMLNamespace*) nsDef; /* namespace definitions on this node */
- (GSXMLNode*) parent;
- (GSXMLNode*) prev;
- (GSXMLAttribute*) properties;
- (NSMutableDictionary*) propertiesAsDictionary;
- (GSXMLElementType) type;
- (GSXMLNode*) makeChild: (GSXMLNamespace*)ns
name: (NSString*)name
content: (NSString*)content;
- (GSXMLNode*) makeComment: (NSString*)content;
- (GSXMLNode*) makePI: (NSString*)name
content: (NSString*)content;
- (GSXMLAttribute*) setProp: (NSString*)name
value: (NSString*)value;
@end
/* Attribute */
@interface GSXMLAttribute : GSXMLNode
{
}
+ (GSXMLAttribute*) attributeFromNode: (GSXMLNode*)node
name: (NSString*)name
value: (NSString*)value;
+ (GSXMLAttribute*) attributeFrom: (void*)data;
- (id) initFromNode: (GSXMLNode*)node
name: (NSString*)name
value: (NSString*)value;
- (id) initFrom: (void*)data;
- (NSString*) name;
- (GSXMLAttribute*) next;
- (GSXMLAttribute*) prev;
- (GSXMLAttributeType) type;
- (NSString*) value;
@end
@interface GSXMLParser : NSObject
{
id src; /* source for parsing */
void *lib; /* parser context */
GSSAXHandler *saxHandler;
}
+ (GSXMLParser*) parser: (id)source;
+ (GSXMLParser*) parserWithSAXHandler: (GSSAXHandler*)handler
source: (id) source;
- (id) initWithSAXHandler: (GSSAXHandler*)handler source: (id)source;
- (GSXMLDocument*) doc;
- (BOOL) parse;
- (BOOL) doValidityChecking: (BOOL)yesno;
- (int) errNo;
- (BOOL) getWarnings: (BOOL)yesno;
- (BOOL) keepBlanks: (BOOL)yesno;
- (void) setExternalEntityLoader: (void*)function;
- (BOOL) substituteEntities: (BOOL)yesno;
@end
@interface GSSAXHandler : NSObject
{
void *lib;
BOOL native;
}
+ (GSSAXHandler*) handler;
- (void*) lib;
@end
@interface GSSAXHandler (Callbacks)
- (void) startDocument;
- (void) endDocument;
- (void) isStandalone;
- (void) startElement: (NSString*)elementName
attributes: (NSMutableDictionary*)elementAttributes;
- (void) endElement: (NSString*)elementName;
- (void) attribute: (NSString*)name
value: (NSString*)value;
- (void) characters: (NSString*)name
length: (int)len;
- (void) ignoreWhitespace: (NSString*)ch
length: (int)len;
- (void) processInstruction: (NSString*)targetName
data: (NSString*)PIdata;
- (void) comment: (NSString*) value;
- (void) cdataBlock: (NSString*)value
length: (int)len;
- (void) hasInternalSubset;
- (void) internalSubset: (NSString*)name
externalID: (NSString*)externalID
systemID: (NSString*)systemID;
- (void) hasExternalSubset;
- (void) resolveEntity: (NSString*)publicId
systemID: (NSString*)systemID;
- (void) getEntity: (NSString*)name;
- (void) getParameterEntity: (NSString*)name;
- (void) namespaceDecl: (NSString*)name
href: (NSString*)href
prefix: (NSString*)prefix;
- (void) notationDecl: (NSString*)name
public: (NSString*)publicId
system: (NSString*)systemId;
- (void) entityDecl: (NSString*)name
type: (int)type
public: (NSString*)publicId
system: (NSString*)systemId
content: (NSString*)content;
- (void) attributeDecl: (NSString*)nameElement
name: (NSString*)name
type: (int)type
typeDefValue: (int)defType
defaultValue: (NSString*)value;
- (void) elementDecl: (NSString*)name
type: (int)type;
- (void) unparsedEntityDecl: (NSString*)name
public: (NSString*)publicId
system: (NSString*)systemId
notationName: (NSString*)notation;
- (void) reference: (NSString*)name;
- (void) globalNamespace: (NSString*)name
href: (NSString*)href
prefix: (NSString*)prefix;
- (void) warning: (NSString*)e;
- (void) error: (NSString*)e;
- (void) fatalError: (NSString*)e;
@end
#endif __GSXML_H__

View file

@ -95,8 +95,6 @@ preface.m \
mframe.m \
objc-gnu2next.m
GNU_EXTRAS_MFILES = \
GNU_CFILES = \
md5.c \
numbers.c \
@ -138,8 +136,6 @@ o_map_cbs.h \
objc-gnu2next.h \
preface.h
GNU_EXTRAS_HFILES = \
# GNUStep source files
BASE_MFILES = \
@ -226,6 +222,10 @@ objc-load.m \
NSURL.m \
NSURLHandle.m
ifeq ($(HAVE_LIBXML),1)
BASE_MFILES += GSXML.m
endif
NSVALUE_MFILES = \
NSValue0.m NSValue1.m NSValue2.m NSValue3.m \
NSValue4.m
@ -319,6 +319,10 @@ Foundation/objc-load.h \
Foundation/NSURL.h \
Foundation/NSURLHandle.h
ifeq ($(HAVE_LIBXML),1)
BASE_HEADERS += Foundation/GSXML.h
endif
UNICODE_HEADERS = \
unicode/caseconv.h \
unicode/cop.h \

1280
Source/GSXML.m Normal file

File diff suppressed because it is too large Load diff

View file

@ -39,7 +39,7 @@
#
# Additional flags to pass to the preprocessor
ADDITIONAL_CPPFLAGS = $(DEFS) -Wall
ADDITIONAL_CPPFLAGS = $(DEFS) -DHAVE_LIBXML=$(HAVE_LIBXML) -Wall
# Additional flags to pass to the Objective-C compiler
ADDITIONAL_OBJCFLAGS =

View file

@ -718,7 +718,7 @@ static IMP msInitImp; /* designated initialiser for mutable */
if (plInit == 0)
setupPl([NSGCString class]);
result = parsePlItem(&data);
result = parsePl(&data);
if (result == nil && data.err != nil)
{

View file

@ -402,7 +402,7 @@
if (plInit == 0)
setupPl([NSGString class]);
result = parsePlItem(&data);
result = parsePl(&data);
if (result == nil && data.err != nil)
{

View file

@ -2665,7 +2665,7 @@ handle_printf_atsign (FILE *stream,
if (plInit == 0)
setupPl([NSGString class]);
result = parsePlItem(&data);
result = parsePl(&data);
if (result == nil && data.err != nil)
{

View file

@ -21,6 +21,107 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#if HAVE_LIBXML
#include <Foundation/GSXML.h>
static char base64[]
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static void
decodeBase64Unit(const char* ptr, unsigned char *out)
{
out[0] = (ptr[0] << 2) | ((ptr[1] & 0x30) >> 4);
out[1] = ((ptr[1] & 0x0F) << 4) | ((ptr[2] & 0x3C) >> 2);
out[2] = ((ptr[2] & 0x03) << 6) | (ptr[3] & 0x3F);
out[3] = 0;
}
static NSData*
decodeBase64(const char *source)
{
int length = strlen(source);
char *sourceBuffer = objc_malloc(length+1);
NSMutableData *data = [NSMutableData dataWithCapacity:0];
int i, j;
unsigned char tmp[4];
strcpy(sourceBuffer, source);
j = 0;
for (i = 0; i < length; i++)
{
if (!isspace(source[i]))
{
sourceBuffer[j++] = source[i];
}
}
sourceBuffer[j] = '\0';
length = strlen(sourceBuffer);
while (length > 0 && sourceBuffer[length-1] == '=')
{
sourceBuffer[--length] = '\0';
}
for (i = 0; i < length; i += 4)
{
decodeBase64Unit(&sourceBuffer[i], tmp);
[data appendBytes: tmp length: strlen(tmp)];
}
objc_free(sourceBuffer);
return data;
}
static char*
encodeBase64(NSData *source)
{
int length = [source length];
int enclen = length / 3;
int remlen = length - 3 * enclen;
int destlen = 4 * ((length - 1) / 3) + 5;
unsigned char *sourceBuffer = malloc(length);
unsigned char *destBuffer = malloc(destlen);
int sourceIndex = 0, destIndex = 0;
[source getBytes:sourceBuffer];
destBuffer[destlen - 1] = '\0';
for (sourceIndex = 0; sourceIndex < length - 2; sourceIndex += 3, destIndex += 4)
{
destBuffer[destIndex] = base64[sourceBuffer[sourceIndex] >> 2];
destBuffer[destIndex + 1] = base64[((sourceBuffer[sourceIndex] << 4) | (sourceBuffer[sourceIndex + 1] >> 4)) & 0x3f];
destBuffer[destIndex + 2] = base64[((sourceBuffer[sourceIndex + 1] << 2) | (sourceBuffer[sourceIndex + 2] >> 6)) & 0x3f];
destBuffer[destIndex + 3] = base64[sourceBuffer[sourceIndex + 2] & 0x3f];
}
if (remlen == 1)
{
destBuffer[destIndex] = base64[sourceBuffer[sourceIndex] >> 2];
destBuffer[destIndex + 1] = (sourceBuffer[sourceIndex] << 4) & 0x30;
destBuffer[destIndex + 1] = base64[destBuffer[destIndex + 1]];
destBuffer[destIndex + 2] = '=';
destBuffer[destIndex + 3] = '=';
}
else if (remlen == 2)
{
destBuffer[destIndex] = base64[sourceBuffer[sourceIndex] >> 2];
destBuffer[destIndex + 1] = (sourceBuffer[sourceIndex] << 4) & 0x30;
destBuffer[destIndex + 1] |= sourceBuffer[sourceIndex + 1] >> 4;
destBuffer[destIndex + 1] = base64[destBuffer[destIndex + 1]];
destBuffer[destIndex + 2] = (sourceBuffer[sourceIndex + 1] << 2) & 0x3c;
destBuffer[destIndex + 2] = base64[destBuffer[destIndex + 2]];
destBuffer[destIndex + 3] = '=';
}
free(sourceBuffer);
return destBuffer;
}
#endif
/*
* Cache some commonly used character sets along with methods to
* check membership.
@ -555,6 +656,142 @@ static id parsePlItem(pldata* pld)
}
}
#if HAVE_LIBXML
static GSXMLNode*
elementNode(GSXMLNode* node)
{
while (node != nil)
{
if ([node type] == XML_ELEMENT_NODE)
{
break;
}
node = [node next];
}
return node;
}
static id
nodeToObject(GSXMLNode* node)
{
NSString *name;
NSString *content;
GSXMLNode *children;
node = elementNode(node);
if (node == nil)
{
return nil;
}
name = [node name];
children = elementNode([node children]);
content = [children content];
if ([name isEqualToString: @"string"])
{
return content;
}
else if ([name isEqualToString: @"key"])
{
return content;
}
else if ([name isEqualToString: @"true"])
{
return [NSNumber numberWithBool: YES];
}
else if ([name isEqualToString: @"false"])
{
return [NSNumber numberWithBool: NO];
}
else if ([name isEqualToString: @"integer"])
{
return [NSNumber numberWithInt: [content intValue]];
}
else if ([name isEqualToString: @"real"])
{
return [NSNumber numberWithDouble: [content doubleValue]];
}
else if ([name isEqualToString: @"date"])
{
return [NSCalendarDate dateWithString: content
calendarFormat: @"%Y-%m-%d %H:%M:%S"];
}
else if ([name isEqualToString: @"data"])
{
return decodeBase64([content cString]);
}
// container class
else if ([name isEqualToString: @"array"])
{
NSMutableArray *container = [NSMutableArray array];
while (children != nil)
{
[container addObject: nodeToObject(children)];
children = elementNode([children next]);
}
return container;
}
else if ([name isEqualToString: @"dict"])
{
NSMutableDictionary *container = [NSMutableDictionary dictionary];
while (children != nil)
{
NSString *key = nodeToObject(children);
children = elementNode([children next]);
[container setObject: nodeToObject(children) forKey: key];
children = elementNode([children next]);
}
return container;
}
else
{
return nil;
}
}
#endif
static id parsePl(pldata* pld)
{
#if HAVE_LIBXML
while (pld->pos < pld->end && isspace(pld->ptr[pld->pos]))
{
pld->pos++;
}
/*
* A string beginning with a '<?' must be an XML file
*/
if (pld->pos + 1 < pld->end && pld->ptr[pld->pos] == '<'
&& pld->ptr[pld->pos+1] == '?')
{
NSData *data;
GSXMLParser *parser;
data = [NSData dataWithBytes: pld->ptr length: pld->end];
NSLog(@"Parsing '%*s'", pld->end, pld->ptr);
parser = [GSXMLParser parser: data];
if ([parser parse] == YES)
{
if (![[[[parser doc] root] name] isEqualToString: @"plist"])
{
NSLog(@"not a property list - because name node is %@",
[[[parser doc] root] name]);
return nil;
}
return nodeToObject([[[parser doc] root] children]);
}
else
{
NSLog(@"not a property list - failed to parse as XML");
return nil;
}
}
#endif
return parsePlItem(pld);
}
static id parseSfItem(pldata* pld)
{
NSMutableDictionary *dict;

View file

@ -110,8 +110,6 @@ nstimezone_OBJC_FILES = nstimezone.m
prepend_OBJC_FILES = prepend.m
release_OBJC_FILES = release.m
string_OBJC_FILES = string.m
test01_OBJC_FILES = test01.m
test02_OBJC_FILES = test02.m
testtool_OBJC_FILES = testtool.m
thread-except_OBJC_FILES = thread-except.m
values_OBJC_FILES = values.m

View file

@ -24,6 +24,9 @@ int main()
id s2, s3;
int a;
NSMutableString *fo = [NSMutableString stringWithString: @"abcdefg"];
[fo replaceCharactersInRange: [fo rangeOfString: @"xx"] withString: @"aa"];
print_string(s);
s2 = NSStringFromPoint(NSMakePoint(1.374, 5.100));

View file

@ -55,11 +55,6 @@ ADDITIONAL_INCLUDE_DIRS += -I../Headers/gnustep -I../Headers \
# Additional library directories the linker should search
ADDITIONAL_LIB_DIRS += -L../Source/$(GNUSTEP_OBJ_DIR)
# Additional libraries for XML parsing
ifeq ($(HAVE_LIBXML),1)
ADDITIONAL_TOOL_LIBS += -lxml -lz
endif
#
# Flags dealing with installing and uninstalling
#

View file

@ -771,7 +771,7 @@ AC_SUBST(GS_FAKE_MAIN)
AC_MSG_RESULT($enable_fake_main)
#--------------------------------------------------------------------
# Check recent libxlm for GSDoc etc.
# Check recent libxlm for Properytlists, GSXML, GSDoc etc.
#--------------------------------------------------------------------
echo "Checking for libxml"
AC_CHECK_HEADERS(libxml/xmlversion.h)