mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 08:26:27 +00:00
Added xpath support
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@14352 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
7e2248c901
commit
505cf97c4f
4 changed files with 263 additions and 4 deletions
|
@ -1,3 +1,9 @@
|
|||
2002-08-27 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/Additions/GSXML.m: Integrated GSXPath code by Nicola Pero
|
||||
provides an API to use the xpath support built into libxml from
|
||||
version 2.3 onwards.
|
||||
|
||||
2002-08-27 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSData.m: ([-writeToFile:atomically:]) Removed bogus line
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
Integrated by Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Date: September 2000
|
||||
GSXPath by Nicola Pero <nicola@brainstorm.co.uk>
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
|
@ -269,6 +270,74 @@
|
|||
@interface GSHTMLSAXHandler : GSSAXHandler
|
||||
@end
|
||||
|
||||
@class GSXPathObject;
|
||||
|
||||
/**
|
||||
* Using this library class is trivial. Get your GSXMLDocument. Create
|
||||
* a GSXPathContext for it.
|
||||
*
|
||||
* GSXPathContext *p = [[GSXPathContext alloc] initWithDocument: document];
|
||||
*
|
||||
* Then, you can use it to evaluate XPath expressions:
|
||||
*
|
||||
* GSXPathString *result = [p evaluateExpression: @"string(/body/text())"];
|
||||
* NSLog (@"Got %@", [result stringValue]);
|
||||
*
|
||||
*/
|
||||
@interface GSXPathContext : NSObject
|
||||
{
|
||||
void *_lib; // xmlXPathContext
|
||||
GSXMLDocument *_document;
|
||||
}
|
||||
- (id) initWithDocument: (GSXMLDocument*)d;
|
||||
- (GSXPathObject*) evaluateExpression: (NSString*)XPathExpression;
|
||||
@end
|
||||
|
||||
/** XPath queries return a GSXPathObject. GSXPathObject in itself is
|
||||
* an abstract class; there are four types of completely different
|
||||
* GSXPathObject types, listed below. I'm afraid you need to check
|
||||
* the returned type of each GSXPath query to make sure it's what you
|
||||
* meant it to be.
|
||||
*/
|
||||
@interface GSXPathObject : NSObject
|
||||
{
|
||||
void *_lib; // xmlXPathObject
|
||||
GSXPathContext *_context;
|
||||
}
|
||||
@end
|
||||
|
||||
/**
|
||||
* For XPath queries returning true/false.
|
||||
*/
|
||||
@interface GSXPathBoolean : GSXPathObject
|
||||
- (BOOL) booleanValue;
|
||||
@end
|
||||
|
||||
/**
|
||||
* For XPath queries returning a number.
|
||||
*/
|
||||
@interface GSXPathNumber : GSXPathObject
|
||||
- (double) doubleValue;
|
||||
@end
|
||||
|
||||
/**
|
||||
* For XPath queries returning a string.
|
||||
*/
|
||||
@interface GSXPathString : GSXPathObject
|
||||
- (NSString *) stringValue;
|
||||
@end
|
||||
|
||||
/**
|
||||
* For XPath queries returning a node set.
|
||||
*/
|
||||
@interface GSXPathNodeSet : GSXPathObject
|
||||
- (unsigned int) length;
|
||||
|
||||
/** Please note that index starts from 0. */
|
||||
- (GSXMLNode *) nodeAtIndex: (unsigned)index;
|
||||
@end
|
||||
|
||||
|
||||
#endif /* STRICT_MACOS_X */
|
||||
#endif /* STRICT_OPENSTEP */
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include <libxml/SAX.h>
|
||||
#include <libxml/HTMLparser.h>
|
||||
#include <libxml/xmlmemory.h>
|
||||
#include <libxml/xpath.h>
|
||||
|
||||
extern int xmlDoValidityCheckingDefaultValue;
|
||||
extern int xmlGetWarningsDefaultValue;
|
||||
|
@ -2826,6 +2827,187 @@ fatalErrorFunction(void *ctx, const char *msg, ...)
|
|||
}
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation GSXPathObject
|
||||
- (id) init
|
||||
{
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Internal method. */
|
||||
- (id) _initWithNativePointer: (xmlXPathObject *)lib
|
||||
context: (GSXPathContext *)context
|
||||
{
|
||||
_lib = lib;
|
||||
/* We RETAIN our context because we might be holding references to nodes
|
||||
* which belong to the document, and we must make sure the document is
|
||||
* not freed before we are. */
|
||||
ASSIGN (_context, context);
|
||||
return self;
|
||||
}
|
||||
|
||||
/* This method is called by GSXPathContext when creating a
|
||||
* GSXPathObject to wrap the results of a query. It assumes that lib
|
||||
* is a pointer created by xmlXPathEval (), and that we are now taking
|
||||
* on responsibility for freeing it. It then examines lib, and
|
||||
* replaces itself with an object of the appropriate subclass. */
|
||||
+ (id) _newWithNativePointer: (xmlXPathObject *)lib
|
||||
context: (GSXPathContext *)context
|
||||
{
|
||||
switch (lib->type)
|
||||
{
|
||||
case XPATH_NODESET:
|
||||
return [[GSXPathNodeSet alloc] _initWithNativePointer: lib
|
||||
context: context];
|
||||
break;
|
||||
case XPATH_BOOLEAN:
|
||||
return [[GSXPathBoolean alloc] _initWithNativePointer: lib
|
||||
context: context];
|
||||
break;
|
||||
case XPATH_NUMBER:
|
||||
return [[GSXPathNumber alloc] _initWithNativePointer: lib
|
||||
context: context];
|
||||
break;
|
||||
case XPATH_STRING:
|
||||
return [[GSXPathString alloc] _initWithNativePointer: lib
|
||||
context: context];
|
||||
break;
|
||||
default:
|
||||
/* This includes:
|
||||
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
|
||||
- (BOOL) booleanValue
|
||||
{
|
||||
return ((xmlXPathObject*)_lib)->boolval;
|
||||
}
|
||||
- (NSString *) description
|
||||
{
|
||||
return ([self booleanValue] ? @"true" : @"false");
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation GSXPathNumber
|
||||
- (double) doubleValue
|
||||
{
|
||||
return ((xmlXPathObject*)_lib)->floatval;
|
||||
}
|
||||
- (NSString *) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"%f", [self doubleValue]];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation GSXPathString
|
||||
- (NSString *) stringValue
|
||||
{
|
||||
xmlChar *string = ((xmlXPathObject*)_lib)->stringval;
|
||||
return [NSString stringWithUTF8String: string];
|
||||
}
|
||||
- (NSString *) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@", [self stringValue]];
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@implementation GSXPathNodeSet
|
||||
- (unsigned int) length
|
||||
{
|
||||
if (xmlXPathNodeSetIsEmpty (((xmlXPathObject*)_lib)->nodesetval))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return xmlXPathNodeSetGetLength (((xmlXPathObject*)_lib)->nodesetval);
|
||||
}
|
||||
|
||||
- (GSXMLNode *) nodeAtIndex: (unsigned)index
|
||||
{
|
||||
if (xmlXPathNodeSetIsEmpty (((xmlXPathObject*)_lib)->nodesetval))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlNode *node;
|
||||
GSXMLNode *n;
|
||||
|
||||
node = xmlXPathNodeSetItem (((xmlXPathObject*)_lib)->nodesetval, index);
|
||||
n = [GSXMLNode alloc];
|
||||
|
||||
return [n _initFrom: node parent: self];
|
||||
}
|
||||
}
|
||||
- (NSString *) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"NodeSet (length %d)", [self length]];
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@implementation GSXPathContext
|
||||
- (id) initWithDocument: (GSXMLDocument *)d
|
||||
{
|
||||
ASSIGN (_document, d);
|
||||
((xmlXPathContext*)_lib) = xmlXPathNewContext ([_document lib]);
|
||||
((xmlXPathContext*)_lib)->node = xmlDocGetRootElement ([_document lib]);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (GSXPathObject *) evaluateExpression: (NSString *)XPathExpression
|
||||
{
|
||||
xmlXPathCompExpr *comp;
|
||||
xmlXPathObject *res;
|
||||
GSXPathObject *result;
|
||||
|
||||
comp = xmlXPathCompile ([XPathExpression UTF8String]);
|
||||
if (comp == NULL)
|
||||
{
|
||||
/* Maybe an exception would be better ? */
|
||||
return nil;
|
||||
}
|
||||
|
||||
res = xmlXPathCompiledEval (comp, ((xmlXPathContext*)_lib));
|
||||
|
||||
result = [GSXPathObject _newWithNativePointer: res context: self];
|
||||
AUTORELEASE (result);
|
||||
|
||||
xmlXPathFreeCompExpr (comp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
xmlXPathFreeContext (_lib);
|
||||
RELEASE (_document);
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* need this to make the linker happy on Windows
|
||||
*/
|
||||
|
|
|
@ -234,10 +234,12 @@ static Class NSURLHandleClass = 0;
|
|||
*/
|
||||
- (void) addClient: (id <NSURLHandleClient>)client
|
||||
{
|
||||
RETAIN((id)client);
|
||||
[_clients removeObjectIdenticalTo: client];
|
||||
[_clients addObject: client];
|
||||
RELEASE((id)client);
|
||||
id o = client;
|
||||
|
||||
RETAIN(o);
|
||||
[_clients removeObjectIdenticalTo: o];
|
||||
[_clients addObject: o];
|
||||
RELEASE(o);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue