Xml2Dictionary 1.4

Xml2Dictionary 1.4

测试已测试
Lang语言 Obj-CObjective C
许可证 zlib
发布最后发布2017年1月

evermeer 维护。



  • 作者:
  • Nick Lockwood

目的

XMLDictionary 是一个用于在 iOS 和 Mac OS 上简化 XML 解析和生成的类。XMLDictionary 建立在 NSXMLParser 类之上,但行为更像是一个 DOM 风格的解析器,而不是 SAX 解析器,因为它创建对象的树而不是在每个节点开始和结束时生成事件。

与其他 DOM 解析器不同,XMLDictionary 不会尝试复制 XML 标准的所有细微差别,例如在文本中嵌套标签的能力。如果您需要表示类似 HTML 文档的内容,则 XMLDictionary 不会适用于您。如果您想使用 XML 作为数据交换格式来传递嵌套数据结构,则 XMLDictionary 比其他基于 DOM 的解析器可能提供更简单的解决方案。

支持的操作系统和 SDK 版本

  • 支持的构建目标 - iOS 7.1 / Mac OS 10.9 (Xcode 5.1, Apple LLVM 编译器 5.1)
  • 最早支持的部署目标 - iOS 5.0 / Mac OS 10.7
  • 最早兼容的部署目标 - iOS 4.3 / Mac OS 10.6

注意:“支持”表示已测试过此版本。“兼容”表示库应该运行在这个操作系统版本上(即它不依赖于任何不可用的 SDK 功能),但不再对其进行兼容性测试,可能需要调整或错误修复才能正确运行。

ARC 兼容性

从版本 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

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

  • (NSDictionary *)dictionaryWithXMLParser:(NSParser *)parser;

从现有的 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;

获取给定节点的所有评论的数组。请注意,相对于其他节点的嵌套不会 preserved。如果节点没有评论,则返回 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"];

上面的例子假定您正在使用 collapseTextNodesalwaysUseArrays 的默认设置。如果禁用 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 的 cliché 属性,可以编写如下:

NSString *barCliche = [xmlDoc[@"bar] attributes][@"cliche"];

如果 attributesMode 的设置是默认值 XMLDictionaryAttributesModePrefixed,则也可以这样做

NSString *barCliche = [xmlDoc valueForKeyPath:@"bar._cliche"];

如果它设置为 XMLDictionaryAttributesModeUnprefixed,则可以这样做

NSString *barCliche = [xmlDoc valueForKeyPath:@"bar.cliche"];

发布说明

版本 1.4

  • 添加了 dictionaryWithXMLParser: 构造方法
  • 添加了 wrapRootNode 选项,这是一种更美观地保留根节点名称的方式
  • 不再崩溃,如果用作键或属性的值不是字符串
  • 现在符合 -Weverything 警告级别

版本 1.3

  • 添加了 stripEmptyNodes 属性(默认为 YES)
  • 添加了 arrayValueForKeyPath、stringValueForKeyPath 和 dictionaryValueForKeyPath 方法,以便简化数据处理

版本 1.2.2

  • sharedInstance 方法不再每次都返回一个新的实例

版本 1.2.1

  • 移除了 isa 引用,弃用于 iOS 7

版本 1.2

  • 公开了 XMLDictionaryParser 对象,可以使用它来配置解析器
  • 现在可以更改解析选项,而不必修改库
  • 添加了始终将属性编码为数组的选项
  • __name__coment 键不再默认包含
  • 现在将引号编码为 &apos;
  • 移除了 attributeForKey: 方法

版本 1.1

  • 更新为使用 ARC
  • 添加了 podspec

版本 1.0

  • 初始发布