I'm trying to parse some XML in objective-c, using the TouchXML library. The XML has a namespace in the root element, so I'm using the method in the TouchXML library on the CXMLNode object like:
- (NSArray *)nodesForXPath:(NSString *)xpath namespaceMappings:(NSDictionary *)inNamespaceMappings error:(NSError **)error;
My code uses this method to select a bunch of nodes matching an XPath query, then for each node I do some more XPath queries to read a few properties. For some reason, the second set of queries results in a pointer being freed was not allocated
bug - I can't work out where this is coming from.
OK, here's a snippet of the XML:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
<Placemark>
<name>Place 1</name>
<description><![CDATA[6-20 Luck Street Eltham 3095]]></description>
<Point>
<coordinates>145.151138,-37.712663,0.000000</coordinates>
</Point>
</Placemark>
<Placemark>
<name>Place 2</name>
<description><![CDATA[The Pines Shopping Centre, Reynolds Road Doncaster East 3109]]></description>
<Point>
<coordinates>145.168620,-37.762135,0.000000</coordinates>
</Point>
</Placemark>
<Placemark>
<name>Place 3</name>
<description><![CDATA[25 Main Street Greensborough 3088]]></description>
<Point>
<coordinates>145.102788,-37.702511,0.000000</coordinates>
</Point>
</Placemark>
</Document>
</kml>
So I read this into a CMLXmlElement, then I've this code to read out each <Placemark> element:
_locations = [NSMutableArray array];
NSDictionary *mappings = [NSDictionary dictionaryWithObjectsAndKeys:@"http://earth.google.com/kml/2.2", @"kmlns", nil];
NSError *error = nil;
for (CXMLNode *node in [element nodesForXPath@"//kmlns:kml/kmlns:Document/kmlns:Placemark" namespaceMappings:mappings error:&error])
{
[_locations addObject:[[ONEMapLocation alloc] initWithXmlElement:(CXMLElement *)node]];
}
This code runs without issue. But then, in that initWithXmlElement
each of the location objects initialises itself like:
NSDictionary *namespaceMappings = [NSDictionary dictionaryWithObjectsAndKeys:@"http://earth.google.com/kml/2.2", @"kmlns", nil];
NSError *error = nil;
_name = ((CXMLNode*)[[xmlElement nodesForXPath:@"./kmlns:name/text()" namespaceMappings:namespaceMappings error:&error] lastObject]).stringValue;
_description = ((CXMLNode*)[[xmlElement nodesForXPath:@"./description/text()" namespaceMappings:namespaceMappings error:&error] lastObject]).stringValue;
NSString *rawCoordinates = _description = ((CXMLNode*)[[xmlElement nodesForXPath:@"./kmlns:Point/kmlns:coordinates/text()" namespaceMappings:namespaceMappings error:&error] lastObject]).stringValue;
NSArray *coordinateArray = [rawCoordinates componentsSeparatedByString:@","];
_latitude = [[coordinateArray objectAtIndex:1] floatValue];
_longitude = [[coordinateArray objectAtIndex:0] floatValue];
When this block of code runs, it successfully parses the XML document, but then about a second later the app crashes with the pointer being freed was not allocated
bug. If I comment out those lines and set the _name
, _description
, etc. to dummy values it all works fine.
I've also tried pulling out the namespace from the XML and using the methods in the TouchXML library which don't bother with the namespace and it works fine (though I won't have the luxury of being able to edit the XML in the real world scenarios).
I know, long, complicated question, probably with a bunch of other possible causes, but I've definitely isolated the problem down to these half a dozen lines.