XMLDictionary 1.4.1

XMLDictionary 1.4.1

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

Nick Lockwood维护。



  • Nick Lockwood

目的

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

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

支持的操作系统和SDK版本

  • 支持构建目标 - iOS 10.2 / Mac OS 10.12(Xcode 8.2,Apple LLVM编译器8.0)
  • 最早支持部署目标 - iOS 8.0 / Mac OS 10.10
  • 最早兼容部署目标 - 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;

获取给定节点的所有注释的数组。请注意,与其他节点的嵌套关系不会被保留。如果节点没有注释,则此操作将返回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

  • 升级为 Xcode 8.2
  • 将 tvOS 和 watchOS 支持添加到 podspec

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

  • 首次发布