implementing nodesForXPath

52 views
Skip to first unread message

Rieffer

unread,
Dec 30, 2008, 10:50:38 PM12/30/08
to KissXML
Have you implemented nodesForXPath? I've got the following so far,
but haven't got it to work yet. I always get true for
xmlXPathNodeSetIsEmpty().

-(NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error {
if(genericPtr == nil || ![DDXMLNode isXmlDocPtr:genericPtr])
return nil;
NSArray *theResult = NULL;

xmlXPathContextPtr theXPathContext = xmlXPathNewContext((xmlDocPtr)
genericPtr);
theXPathContext->node = (xmlNodePtr)genericPtr;

xmlXPathObjectPtr theXPathObject = xmlXPathEvalExpression((const
xmlChar *)[xpath UTF8String], theXPathContext);
if (xmlXPathNodeSetIsEmpty(theXPathObject->nodesetval))
theResult = [NSArray array]; // TODO better to return NULL?
else
{
NSMutableArray *theArray = [NSMutableArray array];
int N;
for (N = 0; N < theXPathObject->nodesetval->nodeNr; N++)
{
xmlNodePtr theNode = theXPathObject->nodesetval->nodeTab[N];
[theArray addObject:[DDXMLNode nodeWithPrimitive:(xmlKindPtr)
theNode]];
}

theResult = theArray;
}

xmlXPathFreeObject(theXPathObject);
xmlXPathFreeContext(theXPathContext);

return(theResult);
}

Robbie Hanson

unread,
Jan 4, 2009, 2:41:16 AM1/4/09
to kis...@googlegroups.com
I'm working on implementing this now. Also adding some more tests,
and correcting a few other things.

-Robbie Hanson
-Deusty Designs

Rieffer

unread,
Jan 4, 2009, 11:17:22 AM1/4/09
to KissXML
I've got the following to work for me pretty well...

- (NSArray *)nodesForXPath:(NSString *)xpath usingNamespaces:
(NSDictionary*)namespaces error:(NSError **)error {
if(genericPtr == nil)
return nil;
// NSAssert(genericPtr != NULL, @"CXMLNode does not have attached
libxml2 _node.");

NSArray *theResult = NULL;

xmlXPathContextPtr theXPathContext = xmlXPathNewContext(((xmlNodePtr)
genericPtr)->doc);
if(theXPathContext == NULL)
return nil;
theXPathContext->node = (xmlNodePtr)genericPtr;

if(namespaces != nil) {
NSString *prefix;
NSEnumerator *namespaceEnumerator = [namespaces keyEnumerator];
while (prefix = [namespaceEnumerator nextObject])
{
NSString *href = [namespaces valueForKey:prefix];
if(xmlXPathRegisterNs(theXPathContext, (const unsigned char*)
[prefix UTF8String], (const unsigned char*)[href UTF8String]) != 0 ) {
NSLog(@"unable to register namespace");
}
}
}

// TODO considering putting xmlChar <-> UTF8 into a NSString category
xmlXPathObjectPtr theXPathObject = xmlXPathEvalExpression((const
xmlChar *)[xpath UTF8String], theXPathContext);
if(theXPathObject!= NULL) {
if (xmlXPathNodeSetIsEmpty(theXPathObject->nodesetval))
theResult = [NSArray array]; // TODO better to return NULL?
else
{
NSMutableArray *theArray = [NSMutableArray array];
int N;
for (N = 0; N < theXPathObject->nodesetval->nodeNr; N++)
{
xmlNodePtr theNode = theXPathObject->nodesetval->nodeTab[N];
[theArray addObject:[DDXMLNode nodeWithPrimitive:(xmlKindPtr)
theNode]];
}

theResult = theArray;
}
}

xmlXPathFreeObject(theXPathObject);
xmlXPathFreeContext(theXPathContext);

return(theResult);
}

Robbie Hanson

unread,
Jan 5, 2009, 11:36:36 PM1/5/09
to kis...@googlegroups.com
Just checked in my implementation of nodesForXPath:error:

Also added a new test to check compliance with Apple's
nodesForXPath:error: method.

-Robbie Hanson
-Deusty Designs
Reply all
Reply to author
Forward
0 new messages