一些额外的助手来简化XML解析代码。
在Xcode 5.0上开发,启用了ARC。
一个XML示例
<TODOList>
<list date="2013-09-21 18:28">
<name>
Shopping List
</name>
<item date="2013-09-21 18:28">
Apple juice
</item>
<item date="2013-09-21 18:28">
Whole-wheat bread
</item>
<item date="2013-09-21 18:28">
Eggs
</item>
</list>
</TODOList>
使用TBXML的常规解析代码。
TBXMLElement *listElement = [TBXML childElementNamed:@"list" parentElement:tbXML.rootXMLElement];
while (listElement) {
NSString *listDate = [TBXML valueOfAttributeNamed:@"date" forElement:listElement];
TBXMLElement *nameElement = [TBXML childElementNamed:@"name" parentElement:listElement];
if (nameElement) {
NSString *listName = [TBXML textForElement:nameElement];
}
TBXMLElement *itemElement = [TBXML childElementNamed:@"item" parentElement:listElement];
while (itemElement) {
NSString *itemDate = [TBXML valueOfAttributeNamed:@"date" forElement:itemElement];
NSString *itemText = [TBXML textForElement:itemElement];
itemElement = [TBXML nextSiblingNamed:@"item" searchFromElement:itemElement];
}
listElement = [TBXML nextSiblingNamed:@"list" searchFromElement:tbXML.rootXMLElement];
}
使用CBAdditions简化的代码,得益于Objective-C字面量和块。
[TBXML handleElement:tbXML.rootXMLElement
handlers:@{@"list":@{kHandler:listHandler}}
context:NULL
stop:NULL];
当然,我们仍需要实现所有细节。
TBXMLElementHandler listHandler = ^void (TBXMLElement *element, void *context, BOOL *stop) {
NSString *listDate = [TBXML valueOfAttributeNamed:@"date" forElement:element];
YourListClass *aList = [YourListClass new];
[TBXML handleElement:element
handlers:@{@"name":listNameHandler,
kAnyNode:listItemHandler}
context:(__bridge void *)aList
stop:NULL];
};
TBXMLElementHandler listItemHandler = ^void (TBXMLElement *element, void *context, BOOL *stop) {
YourListClass *aList = (__bridge YourListClass *)context;
YourItemClass *anItem = [YourItemClass new];
anItem.date = [TBXML valueOfAttributeNamed:@"date" forElement:element];
anItem.text = [TBXML textForElement:element];
[aList addItem:anItem];
};
TBXMLElementHandler listNameHandler = ^void (TBXMLElement *element, void *context, BOOL *stop) {
YourListClass *aList = (__bridge YourListClass *)context;
aList.name = [TBXML textForElement:element];
};
实际上,如果您只想处理节点,则可以省略kHandler
。例如,@{@"list":@{kHandler:listHandler}}
,您只需使用@{@"list":listHandler}
即可。
在我的一个项目中,我有这样一个更复杂的情况
[TBXML handleElement:[self.xmlObj rootXMLElement]
handlers:@{@"config":@{@"renderMode":@{kAnyNode:renderModeHandler},// All faces
@"outputMode":@{@"format":outputModeHandler},// All output formats
@"startpoint":startPointHandler},
@"content":@{@"crosspoints":@{kAnyNode:crossPointHandler},// All crosspoints
@"routes":@{kAnyNode:routeHandler}},// All routes
@"special":@{@"plans":@{kAnyNode:planHandler}}}// All plans
context:(__bridge void *)(newDocument)
stop:NULL];
根据我的测试,它至少比纯TBXML解决方案慢15%。
TBXML-CBAdditions根据MIT许可证许可。