CXMLNode_XPathExtensions.m 3.32 KB
Newer Older
Pierre's avatar
Pierre committed
1 2 3 4 5
//
//  CXMLNode_XPathExtensions.m
//  TouchCode
//
//  Created by Jonathan Wight on 04/01/08.
6
//  Copyright 2011 toxicsoftware.com. All rights reserved.
Pierre's avatar
Pierre committed
7
//
8 9
//  Redistribution and use in source and binary forms, with or without modification, are
//  permitted provided that the following conditions are met:
Pierre's avatar
Pierre committed
10
//
11 12
//     1. Redistributions of source code must retain the above copyright notice, this list of
//        conditions and the following disclaimer.
Pierre's avatar
Pierre committed
13
//
14 15 16
//     2. Redistributions in binary form must reproduce the above copyright notice, this list
//        of conditions and the following disclaimer in the documentation and/or other materials
//        provided with the distribution.
Pierre's avatar
Pierre committed
17
//
18 19 20 21 22 23 24 25 26 27 28 29 30
//  THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED
//  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
//  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//  The views and conclusions contained in the software and documentation are those of the
//  authors and should not be interpreted as representing official policies, either expressed
//  or implied, of toxicsoftware.com.
Pierre's avatar
Pierre committed
31 32 33 34

#import "CXMLNode_XPathExtensions.h"

#import "CXMLDocument.h"
35
#import "CXMLDocument_PrivateExtensions.h"
Pierre's avatar
Pierre committed
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
#import "CXMLNode_PrivateExtensions.h"

#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>

@implementation CXMLNode (CXMLNode_NamespaceExtensions)

- (NSArray *)nodesForXPath:(NSString *)xpath namespaceMappings:(NSDictionary *)inNamespaceMappings error:(NSError **)error;
{
#pragma unused (error)

NSAssert(_node != NULL, @"TODO");

NSArray *theResult = NULL;

xmlXPathContextPtr theXPathContext = xmlXPathNewContext(_node->doc);
theXPathContext->node = _node;

for (NSString *thePrefix in inNamespaceMappings)
	{
56
	xmlXPathRegisterNs(theXPathContext, (xmlChar *)[thePrefix UTF8String], (xmlChar *)[inNamespaceMappings[thePrefix] UTF8String]);
Pierre's avatar
Pierre committed
57 58 59 60 61
	}

// TODO considering putting xmlChar <-> UTF8 into a NSString category
xmlXPathObjectPtr theXPathObject = xmlXPathEvalExpression((const xmlChar *)[xpath UTF8String], theXPathContext);
if (xmlXPathNodeSetIsEmpty(theXPathObject->nodesetval))
62
	theResult = @[]; // TODO better to return NULL?
Pierre's avatar
Pierre committed
63 64 65 66 67 68
else
	{
	NSMutableArray *theArray = [NSMutableArray array];
	int N;
	for (N = 0; N < theXPathObject->nodesetval->nodeNr; N++)
		{
69 70 71 72 73 74
		xmlNodePtr theLibXMLNode = theXPathObject->nodesetval->nodeTab[N];

        CXMLNode *theNode = [CXMLNode nodeWithLibXMLNode:theLibXMLNode freeOnDealloc:YES];
        [self.rootDocument.nodePool addObject:theNode];

		[theArray addObject:theNode];
Pierre's avatar
Pierre committed
75
		}
76

Pierre's avatar
Pierre committed
77 78
	theResult = theArray;
	}
79

Pierre's avatar
Pierre committed
80 81 82 83 84 85 86 87 88 89 90 91
xmlXPathFreeObject(theXPathObject);

xmlXPathFreeContext(theXPathContext);
return(theResult);
}

- (CXMLNode *)nodeForXPath:(NSString *)xpath error:(NSError **)outError
{
return([[self nodesForXPath:xpath error:outError] lastObject]);
}

@end