mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-24 04:46:01 +08:00
Replace the XMLParser with one based on Insert-Witty-Name/XMLReader
This commit is contained in:
@@ -84,7 +84,7 @@ RKParserRegistry* gSharedRegistry;
|
||||
}
|
||||
|
||||
// XML
|
||||
parserClass = NSClassFromString(@"RKXMLParserLibXML");
|
||||
parserClass = NSClassFromString(@"RKXMLParserXMLReader");
|
||||
if (parserClass) {
|
||||
[self setParserClass:parserClass forMIMEType:RKMIMETypeXML];
|
||||
[self setParserClass:parserClass forMIMEType:RKMIMETypeTextXML];
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
//
|
||||
// RKXMLParser.h
|
||||
//
|
||||
// Created by Jeremy Ellison on 2011-02-28.
|
||||
// Copyright 2011 RestKit
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "RKParser.h"
|
||||
|
||||
/**
|
||||
This is a dead simple XML parser that uses libxml2 to parse an XML document
|
||||
into a dictionary. It is designed specifically for use with RestKit. It
|
||||
does not support any fanciness like Namespaces, DTDs, or other nonsense.
|
||||
It handles text nodes, attributes, and nesting structures and builds key-value
|
||||
coding compliant representations of the XML structure.
|
||||
|
||||
It currently does not support XML generation -- only parsing.
|
||||
*/
|
||||
@interface RKXMLParserLibXML : NSObject <RKParser> {
|
||||
}
|
||||
|
||||
- (NSDictionary *)parseXML:(NSString *)XML;
|
||||
|
||||
@end
|
||||
@@ -1,158 +0,0 @@
|
||||
//
|
||||
// RKXMLParserLibXML.m
|
||||
//
|
||||
// Created by Jeremy Ellison on 2011-02-28.
|
||||
// Copyright 2011 RestKit
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#import <libxml2/libxml/parser.h>
|
||||
#import "RKXMLParserLibXML.h"
|
||||
|
||||
@implementation RKXMLParserLibXML
|
||||
|
||||
- (id)parseNode:(xmlNode*)node {
|
||||
NSMutableArray* nodes = [NSMutableArray array];
|
||||
NSMutableDictionary* attrs = [NSMutableDictionary dictionary];
|
||||
|
||||
xmlNode* currentNode = NULL;
|
||||
for (currentNode = node; currentNode; currentNode = currentNode->next) {
|
||||
if (currentNode->type == XML_ELEMENT_NODE) {
|
||||
NSString* nodeName = [NSString stringWithCString:(char*)currentNode->name encoding:NSUTF8StringEncoding];
|
||||
id val = [self parseNode:currentNode->children];
|
||||
if ([val isKindOfClass:[NSString class]]) {
|
||||
id oldVal = [attrs valueForKey:nodeName];
|
||||
if (nil == oldVal) {
|
||||
// Assume that empty strings are irrelevant and go for an attribute-collection instead
|
||||
if ([val length] == 0) {
|
||||
val = [NSMutableDictionary dictionary];
|
||||
NSMutableDictionary* elem = [NSMutableDictionary dictionaryWithObject:val forKey:nodeName];
|
||||
[nodes addObject:elem];
|
||||
} else {
|
||||
[attrs setValue:val forKey:nodeName];
|
||||
}
|
||||
} else if ([oldVal isKindOfClass:[NSMutableArray class]]) {
|
||||
[oldVal addObject:val];
|
||||
} else {
|
||||
NSMutableArray* array = [NSMutableArray arrayWithObjects:oldVal, val, nil];
|
||||
[attrs setValue:array forKey:nodeName];
|
||||
}
|
||||
|
||||
// Only add attributes to nodes if there actually is one.
|
||||
if (![nodes containsObject:attrs]) {
|
||||
[nodes addObject:attrs];
|
||||
}
|
||||
} else {
|
||||
NSMutableDictionary* elem = [NSMutableDictionary dictionaryWithObject:val forKey:nodeName];
|
||||
[nodes addObject:elem];
|
||||
}
|
||||
xmlElement* element = (xmlElement*)currentNode;
|
||||
xmlAttribute* currentAttribute = NULL;
|
||||
for (currentAttribute = (xmlAttribute*)element->attributes; currentAttribute; currentAttribute = (xmlAttribute*)currentAttribute->next) {
|
||||
NSString* name = [NSString stringWithCString:(char*)currentAttribute->name encoding:NSUTF8StringEncoding];
|
||||
xmlChar* str = xmlNodeGetContent((xmlNode*)currentAttribute);
|
||||
NSString* value = [NSString stringWithCString:(char*)str encoding:NSUTF8StringEncoding];
|
||||
xmlFree(str);
|
||||
[attrs setValue:value forKey:name];
|
||||
if ([val isKindOfClass:[NSDictionary class]]) {
|
||||
// Add attributes as properties of the class
|
||||
[val setObject:value forKey:name];
|
||||
} else if (![nodes containsObject:attrs]) {
|
||||
// Only add attributes to nodes if there actually is one.
|
||||
[nodes addObject:attrs];
|
||||
}
|
||||
}
|
||||
} else if (currentNode->type == XML_TEXT_NODE || currentNode->type == XML_CDATA_SECTION_NODE) {
|
||||
xmlChar* str = xmlNodeGetContent(currentNode);
|
||||
NSString* part = [[NSString stringWithCString:(const char*)str encoding:NSUTF8StringEncoding] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
if ([part length] > 0) {
|
||||
[nodes addObject:part];
|
||||
}
|
||||
xmlFree(str);
|
||||
}
|
||||
}
|
||||
if ([nodes count] == 1) {
|
||||
return [nodes objectAtIndex:0];
|
||||
}
|
||||
if ([nodes count] == 0) {
|
||||
return @"";
|
||||
}
|
||||
if (YES || [nodes containsObject:attrs]) {
|
||||
// We have both attributes and children. merge everything together.
|
||||
NSMutableDictionary* results = [NSMutableDictionary dictionary];
|
||||
for (NSDictionary* dict in nodes) {
|
||||
for (NSString* key in dict) {
|
||||
id value = [dict valueForKey:key];
|
||||
id currentValue = [results valueForKey:key];
|
||||
if (nil == currentValue) {
|
||||
[results setValue:value forKey:key];
|
||||
} else if ([currentValue isKindOfClass:[NSMutableArray class]]) {
|
||||
[currentValue addObject:value];
|
||||
} else {
|
||||
NSMutableArray* array = [NSMutableArray arrayWithObjects: currentValue, value, nil];
|
||||
[results setValue:array forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
- (NSDictionary*)parseXML:(NSString*)xml {
|
||||
xmlParserCtxtPtr ctxt; /* the parser context */
|
||||
xmlDocPtr doc; /* the resulting document tree */
|
||||
id result = nil;;
|
||||
|
||||
/* create a parser context */
|
||||
ctxt = xmlNewParserCtxt();
|
||||
if (ctxt == NULL) {
|
||||
fprintf(stderr, "Failed to allocate parser context\n");
|
||||
return nil;
|
||||
}
|
||||
/* Parse the string. */
|
||||
const char* buffer = [xml cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
doc = xmlParseMemory(buffer, (int) strlen(buffer));
|
||||
|
||||
/* check if parsing suceeded */
|
||||
if (doc == NULL) {
|
||||
fprintf(stderr, "Failed to parse\n");
|
||||
} else {
|
||||
/* check if validation suceeded */
|
||||
if (ctxt->valid == 0) {
|
||||
fprintf(stderr, "Failed to validate\n");
|
||||
}
|
||||
|
||||
/* Parse Doc into Dict */
|
||||
result = [self parseNode:doc->xmlRootNode];
|
||||
|
||||
/* free up the resulting document */
|
||||
xmlFreeDoc(doc);
|
||||
}
|
||||
/* free up the parser context */
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
return result;
|
||||
}
|
||||
|
||||
- (id)objectFromString:(NSString*)string error:(NSError **)error {
|
||||
// TODO: Add error handling...
|
||||
return [self parseXML:string];
|
||||
}
|
||||
|
||||
- (NSString*)stringFromObject:(id)object error:(NSError **)error {
|
||||
[self doesNotRecognizeSelector:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
32
Code/Support/Parsers/XML/RKXMLParserXMLReader.h
Normal file
32
Code/Support/Parsers/XML/RKXMLParserXMLReader.h
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// RKXMLParserXMLReader.h
|
||||
// RestKit
|
||||
//
|
||||
// Created by Christopher Swasey on 1/24/12.
|
||||
// Copyright (c) 2012 GateGuru. All rights reserved.
|
||||
//
|
||||
|
||||
/**
|
||||
Provides a basic XML implementation using an adapted version
|
||||
of the XMLReader class by "Insert-Witty-Name" available at:
|
||||
https://github.com/RestKit/XML-to-NSDictionary
|
||||
|
||||
RKXMLParserXMLReader will parse an XML document into an NSDictionary
|
||||
representation suitable for use with RestKit's key-value coding based
|
||||
object mapping implementation.
|
||||
|
||||
XML attributes are represented as keys in a dictionary.
|
||||
|
||||
**NOTE** When an XML tag is parsed containing both XML attributes and
|
||||
an enclosed text node, the value of the text node will be inserted in
|
||||
the parsed dictionary at the `@"text"` key.
|
||||
*/
|
||||
|
||||
#import "XMLReader.h"
|
||||
#import "RKParser.h"
|
||||
|
||||
@interface RKXMLParserXMLReader : NSObject <RKParser> {
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
22
Code/Support/Parsers/XML/RKXMLParserXMLReader.m
Normal file
22
Code/Support/Parsers/XML/RKXMLParserXMLReader.m
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// RKXMLParserXMLReader.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Christopher Swasey on 1/24/12.
|
||||
// Copyright (c) 2012 GateGuru. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKXMLParserXMLReader.h"
|
||||
|
||||
@implementation RKXMLParserXMLReader
|
||||
|
||||
- (id)objectFromString:(NSString*)string error:(NSError**)error {
|
||||
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
|
||||
return [XMLReader dictionaryForXMLData:data error:error];
|
||||
}
|
||||
|
||||
- (NSString*)stringFromObject:(id)object error:(NSError**)error {
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user