XMLDictionary是一个用于在iOS和Mac OS中简化XML解析和生成的类。XMLDictionary建立在NSXMLParser类之上,但它更像是一个DOM风格的解析器而不是SAX解析器,因为它创建一个对象树而不是在每个节点开始和结束时生成事件。
与其他DOM解析器不同,XMLDictionary不会试图复制XML标准的所有细微差别,例如在文本中嵌套标签的能力。如果您需要表示类似HTML文档的内容,则XMLDictionary可能不适合您。如果您想要将XML用作传递嵌套数据结构的数据交换格式,则XMLDictionary可能比其他基于DOM的解析器提供了一个更简单的解决方案。
注意:“支持”意味着已对该版本进行了测试。 “兼容”意味着库应该在该操作系统版本上运行(即它不依赖于任何不可用的SDK功能),但不再对该版本进行兼容性测试,并且可能需要调整或错误修复才能正确运行。
自1.1版以来,XMLDictionary需要ARC。如果您希望在非ARC项目中使用XMLDictionary,请仅将-fobjc-arc编译器标志添加到XMLDictionary.m类中。要这样做,请转到目标设置中的构建阶段选项卡,打开编译源组,在列表中双击XMLDictionary.m,并在弹出菜单中键入-fobjc-arc。
如果您想将整个项目转换为ARC,请在XMLDictionary.m中注释掉#error行,然后在Xcode中运行编辑>重构>转换为Objective-C ARC...工具,并确保所有要使用ARC的文件都已选中(包括XMLDictionary.m)。
XMLDictionary的方法都应该是线程安全的。可以在不同的线程上并发使用多个XMLDictionaryParsers,但不能在多个线程上并发调用同一解析器。
要在应用程序中使用XMLDictionary,只需将类文件拖到您的项目中。
XMLDictionaryParser类负责将XML文件解析为字典。您通常不需要显式使用此类,因为您可以直接使用添加到NSDictionary的实用方法,但如果您想修改默认解析器设置,这可能很有用。
如果您需要为不同的字典使用不同的设置,可以创建XMLDictionaryParser的新实例。一旦创建了XMLDictionaryParser,您可以使用以下方法使用该特定解析器实例解析XML文件:
- (NSDictionary *)dictionaryWithData:(NSData *)data;
- (NSDictionary *)dictionaryWithString:(NSString *)string;
- (NSDictionary *)dictionaryWithFile:(NSString *)path;
- (NSDictionary *)dictionaryWithParser:(NSXMLParser *)parser;
或者,您可以通过修改[XMLDictionaryParser sharedInstance]
的设置来影响随后使用NSDictionary类别扩展方法解析的所有字典的设置。
使用以下属性来调整解析行为:
@property (nonatomic, assign) BOOL collapseTextNodes;
如果为YES(默认值),只包含文本且没有子项、属性或注释的标签将被折叠成单个字符串对象,从而简化对象树的遍历。
@property (nonatomic, assign) BOOL stripEmptyNodes;
如果为YES(默认值),空的标签(没有子项、属性、文本或注释)将被删除。
@property (nonatomic, assign) BOOL trimWhiteSpace;
如果为YES(默认值),从文本节点中去除前导和尾部空白,仅包含空白文本的节点将从字典中省略。
@property (nonatomic, assign) BOOL alwaysUseArrays;
如果为YES
,每个子节点都将表示为数组,即使只有一个子节点也是如此。这简化了处理可能重复的属性所需的逻辑,因为不需要使用[value isKindOfClass:[NSArray class]]
来检查单一情况。默认为NO
。
@property (nonatomic, assign) BOOL preserveComments;
如果为YES
,XML注释将被分组到键为__comments
的数组中,并且可以通过comments
方法访问。默认为NO
。
@property (nonatomic, assign) XMLDictionaryAttributesMode attributesMode;
此属性控制如何处理XML属性。默认值为XMLDictionaryAttributesModePrefixed
,这意味着属性将包含在字典中,并带有前缀_(下划线)以避免命名空间冲突。其他值包括XMLDictionaryAttributesModeDictionary
,将所有属性放置在单独的字典中,XMLDictionaryAttributesModeUnprefixed
,不带有前缀包含属性(这可能导致与节点冲突)以及XMLDictionaryAttributesModeDiscard
,这将删除属性。
@property (nonatomic, assign) XMLDictionaryNodeNameMode nodeNameMode;
此属性控制如何处理节点名称。默认值是XMLDictionaryNodeNameModeRootOnly
,这意味着节点名称将仅包含在根字典中(子节点的名称可以由字典键推断出来,但nodeName
方法除了根节点之外不会工作)。其他值包括XMLDictionaryNodeNameModeAlways
,这意味着节点名称将包含在具有键__name
的字典中(并可以使用nodeName
方法访问),或者XMLDictionaryNodeNameModeNever
,这永远不会包含`__name'键。
XMLDictionary通过以下方法扩展NSDictionary:
从一个现有的NSXMLParser创建一个新的NSDictionary对象。用于通过AFNetworking获取数据时很有用。
+ (NSDictionary *)dictionaryWithXMLData:(NSData *)data;
从XML编码的数据创建一个新的NSDictionary对象。
+ (NSDictionary *)dictionaryWithXMLString:(NSString *)string;
从XML编码的字符串创建一个新的NSDictionary对象。
+ (NSDictionary *)dictionaryWithXMLFile:(NSString *)path;
从XML编码的文件创建一个新的NSDictionary对象。
- (NSString *)attributeForKey:(NSString *)key;
获取给定键的XML属性(键名不应包含前缀)。
- (NSDictionary *)attributes;
获取给定节点字典的所有XML属性的字典。如果节点没有属性,则此方法返回nil。
- (NSDictionary *)childNodes;
获取给定节点字典的所有子节点的字典。如果多个节点具有相同的名称,它们将被分组到一个数组中。如果节点没有子节点,则此操作将返回nil。
- (NSArray *)comments;
获取给定节点的所有注释的数组。请注意,与其他节点的嵌套关系不会被保留。如果节点没有注释,则此操作将返回nil。
- (NSString *)nodeName;
获取节点的名称。如果名称未知,则返回nil。
- (NSString *)innerText;
获取节点的文本内容。如果节点没有文本内容,则返回nil。
- (NSString *)innerXML;
获取节点的内容,作为XML编码的字符串。这个XML字符串不包括容器节点本身。
- (NSString *)XMLString;
获取节点及其内容,作为XML编码的字符串。如果节点名称未知,则顶级标签将命名为 <root>
。
- (NSArray *)arrayValueForKeyPath:(NSString *)keyPath;
就像 valueForKeyPath:
一样工作,只不过返回的值始终是数组。所以如果只有一个值,它将以 @[value]
的形式返回。
- (NSString *)stringValueForKeyPath:(NSString *)keyPath;
就像 valueForKeyPath:
一样工作,只不过返回的值始终是字符串。所以如果值是字典,则返回 innerText
的文本值,如果是数组,则返回第一项。
- (NSDictionary *)dictionaryValueForKeyPath:(NSString *)keyPath;
就像 valueForKeyPath:
一样工作,只不过返回的值始终是字典。所以如果启用 collapseTextNodes 选项且值是字符串,则在返回之前将其转换回字典,如果值是数组,则返回第一项。
加载XML文件的最简单方法是如下所示
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"someFile" ofType:@"xml"];
NSDictionary *xmlDoc = [NSDictionary dictionaryWithXMLFile:filePath];
然后您可以像遍历任何其他对象树一样遍历字典,例如从Plist加载的字典。
要访问嵌套节点和属性,您可以使用 valueForKeyPath 语法。例如,要从以下XML中获取 <foo>
的字符串值
<root>
<bar cliche="true">
<foo>Hello World</foo>
</bar>
<banjo>Was his name-oh</banjo>
</root>
您将编写
NSString *foo = [xmlDoc valueForKeyPath:@"bar.foo"];
上面的示例假设您正在使用 collapseTextNodes 和 alwaysUseArrays 的默认设置。如果禁用 collapseTextNodes,则您将改为通过编写以下内容来获取 <foo>
的值
NSString *foo = [[xmlDoc valueForKeyPath:@"bar.foo"] innerText];
如果启用 alwaysUseArrays 选项,则根据 collapseTextNodes 属性,您将使用以下某一项
NSString *foo = [[xmlDoc valueForKeyPath:@"bar.foo"] firstObject];
NSString *foo = [[[xmlDoc valueForKeyPath:@"bar.foo"] firstObject] innerText];
要获取 bar
的 cliche 属性,您可以编写
NSString *barCliche = [xmlDoc[@"bar] attributes][@"cliche"];
如果 attributesMode
设置为默认值 XMLDictionaryAttributesModePrefixed
,则还可以这样做
NSString *barCliche = [xmlDoc valueForKeyPath:@"bar._cliche"];
或者如果它设置为 XMLDictionaryAttributesModeUnprefixed
,则只需这样做
NSString *barCliche = [xmlDoc valueForKeyPath:@"bar.cliche"];
版本 1.4.1
版本 1.4
版本 1.3
版本 1.2.2
版本 1.2.1
版本 1.2
__name
和 __coment
键不再默认包含'
attributeForKey:
方法版本 1.1
版本 1.0