OC学习第十二节 XML解析

==============
day12 xml解析
==============
xml是可扩展性标记语言Extensible Markup Language。
类似于HTML,是从HTML衍生出来的一种语言。但HTML被设计出来的目的是展示数据,而XML被设计出来是为了展示和存储数据。
XML没什么特别的,就是单纯的文本文档,有能力处理文本文档的软件,通过不兼容的系统之间可以轻松的交换数据(不同手机客户端)
XML是用简单具有自我描述性的语法:
首先第一行是XML的声明,它定义XML的版本(1.0)和所使用的编码格式
第二行为文档的根元素root
接下来是根中的子元素
XML文档形成一种树结构
XML文档中必须包含根元素,该元素是其他所有的父元素
相同层级上的子元素称为同胞(兄弟或姐妹)
所有元素必须有关闭标签
XML对大小写敏感  <title>错误的  </Title>
XML也是有属性的(attribute )目的为提供关于元素的额外(附加)信息,属性必须加双引号。
<root></root>节点、标签
根节点
<books></books>相对应存在
id="1" language="ch" price="80.00”XML中节点的属性
XML是一种以树状结构存在的数据格式
XML数据只存在一个根节点
20050928
www.w3school.com.cn


JSON & XML
JSON
JSON(JavaScript Object Notation)一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。可在不同平台之间进行数据交换。JSON采用兼容性很高的、完全独立于语言文本格式,同时也具备类似于C语言的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)体系的行为。这些特性使JSON成为理想的数据交换语言。

XML
扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML使用DTD(document type definition)文档类型定义来组织数据;格式统一,跨平台和语言,早已成为业界公认的标准

客户端和服务器交互常用什么格式的数据?区别是什么?
json(相对于xml的数据,轻巧,传输速率高,冗余的数据少。缺点:可读性差些) 
xml(冗余的数据多,优点:可读性强, 扩展性强)
/*xml 可扩展标记语言,主要用于客户端与服务端进行数据交互。
     *xml数据特点:一种自上而下的树形结构,有且只有一个根节点:<root>...</root>
     *解析xml数据的过程,就是获取节点内容的过程
     *xml 与json: xml数据可读性强、扩展性强,但是没有json格式的数据轻巧,冗余的数据较多
 */




XML
解析 XML 通常有两种方式,DOM 和 SAX:
1. DOM解析XML时,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取它的属性和值。而且通常情况下,可以借助XPath,直接查询XML节点。比如GData
2. SAX解析XML,是基于事件通知的模式,一边读取XML文档一边处理,不必等整个文档加载完之后才采取操作,当在读取解析过程中遇到需要处理的对象,会发出通知对其进行处理。比如:NSXMLParser

一般在iOS平台下,比较常用的XML解析类库有如下几种:
NSXMLParser,http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/Reference/Reference.html ,这是一个SAX方式解析XML的类库,默认包含在iOS SDK中.
libxml2,http://xmlsoft.org/,是一套默认包含在iOS SDK中的开源类库,它是基于C语言的API,所以使用起来可能不如NSXMLParser方便。这套类库同时支持DOM和SAX解析,libxml2的SAX解析方式还是非常酷的,因为它可以边读取边解析,尤其是在从网上下载一个很大的XML文件,就可以一边下载一边对已经下载好的内容进行解析,极大的提高解析效率。

TouchXML,https://github.com/TouchCode/TouchXML,这是一套DOM方式的XML解析类库,支持XPath,不支持XML的修改。

KissXML,http://code.google.com/p/kissxml/,这是一套基于TouchXML的XML解析类库,和TouchXML相比,支持了XML的修改。

GDataXML,http://code.google.com/p/gdata-objectivec-client/source/browse/trunk/Source/XMLSupport/,这是一套Google开发的DOM方式XML解析类库,支持读取和修改XML文档,支持XPath方式查询。
底层是libxml2

解析库的对比 :
http://www.raywenderlich.com/553/xml-tutorial-for-ios-how-to-choose-the-best-xml-parser-for-your-iphone-project

git clone url

GData的配置
    解析xml经常使用库:    GData
        底层使用系统的libxml2库, 使用的时候添加libxml2
        (1)导入GData库, 直接拖进来
        (2)设置头文件搜索路径  
            Build Setting--->header  search Path
            添加   /usr/include/libxml2
        (3)添加libxml二进制库
            Build Phases ---> Link Binary
            添加  libxml2.dylib
        (4)如果是arc的工程
            Build Phases ---> Compile Source File
            GDataXmlNode.m(非arc的)
GData是用mrc写的,手动管理内存.
GDataXMLNode.h
GDataXMLNode.m
因为我们的项目是用的arc, 而gdata用的mrc, 所以你要告诉编译器,特别是的对这个gdata采用mrc的方式去编译。

GDataXMLNode

获取当前节点的值
- (NSString *)stringValue;
//获取当前节点子节点的个数
- (NSUInteger)childCount;
//获取子节点数组
- (NSArray *)children;
//根据索引获取子节点
- (GDataXMLNode *)childAtIndex:(unsigned)index;

GDataXMLElement
//根据节点名字获取所有的节点名为name的节点数组
- (NSArray *)elementsForName:(NSString *)name;
//获取节点的属性
- (NSArray *)attributes;
//根据属性名获取属性节点
- (GDataXMLNode *)attributeForName:(NSString *)name;

GDataXMLDocument
//创建文档树
- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding error:(NSError **)error;
//获取跟节点
- (GDataXMLElement *)rootElement;

//根据xpath 语法 获取 指定的节点数组
- (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error;


解析xml文件:
<?xml version="1.0" encoding="utf-8" ?>
<root>
    <books>
        <book id="1" language="ch" price="80.00">
            <name>甄嬛传</name>
            <auther>
                <name>流潋紫</name>
            </auther>
            <price>80.00</price>
            <summary>一部宫廷情感大戏,口碑极佳,被称为宫廷剧的终结篇,是一部具有里程碑意义的经典之作。在日本,韩国,美国等相继播出。</summary>
        </book>
        <book id="2" language="ch">
            <name>呐喊</name>
            <auther>
                <name>鲁迅</name>
            </auther>
            <price>12.00</price>
            <summary>揭示了中国的社会面貌,控诉了封建制度的罪恶,喊出了“五四”时期革命者的心声。它反映了“五四”彻底不妥协地反封建主义的革命精神,适应了中国革命从旧民主主义向新民主主义转变的需要,在中国现代文化史和文学史上占有重要地位!</summary>
        </book>
        <book id="3" language="en">
            <name>哈利波特</name>
            <auther>
                <name>JK罗琳</name>
            </auther>
            <price>365.00</price>
            <summary>主人公哈利·波特在霍格沃茨魔法学校六年的学习生活和冒险故事。</summary>
        </book>
    </books>
</root>
1. 读取文件数据
2. 构建文档树对象GDataXMLDocument
3. 根据根节点取对象

GDataXMLDocument * doc = [[GDataXMLDocument alloc] initWithXMLString:xml options:0 error:nil];
GDataXMLElement * rootEle = [doc rootElement];
GDataXMLElement * booksEle = (GDataXMLElement*)[rootEle childAtIndex:0];
NSArray * booksArray = [booksEle children];
for (GDataXMLElement * bookEle in booksArray) {
GDataXMLElement * nameEle = [[bookEle elementsForName:@"name"]firstObject];
        //取得书名
        //nameEle.name 属性的名字 nameEle.stringValue 属性的值 XMLString
        NSLog(@"%@",nameEle.stringValue);
        
        GDataXMLElement * priceEle = [[bookEle elementsForName:@"price"]lastObject];
        NSLog(@"%@",priceEle.stringValue);
        
        GDataXMLElement * summaryEle = [[bookEle elementsForName:@"summary"]lastObject];
        NSLog(@"%@",summaryEle.stringValue);
        
        //得到书的作者的名字 可以直接使用stringValue直接取值,但是为了保险,最好每层每层的寻找
        for (GDataXMLElement * autherNameEle in [bookEle elementsForName:@"auther"]) {
            NSLog(@"%@",[[[autherNameEle elementsForName:@"name"]lastObject] stringValue]);
        }
}

XPATH:
- (void)getXpath{
    //把XML转换为字符串
    NSString * xml = [NSString stringWithContentsOfFile:PATH encoding:NSUTF8StringEncoding error:nil];
    //实例化解析工具 包含头文件
    GDataXMLDocument * doc = [[GDataXMLDocument alloc]initWithXMLString:xml options:0 error:nil];
    //Xpath
    /*
     //name 找到所有的name
     //auther/name  作者的名字
     //book[1]/name 第一本书的名字  从1开始
     //book[last()]/name 取得最后一本书的名字
     //book[position()<3]/name 取得前两本书
     //book[@id=1]/name 找到有属性id 并且id=1节点下的name
     //book[@price]/name 找到有属性price节点下的name
     //book/name|//summary 多路径取出xml中的值
     */
    NSArray * array = [doc nodesForXPath:@"//book/name|//summary" error:nil];
    for (GDataXMLElement * ele in array) {
        NSLog(@"%@",ele.stringValue);
    }
}

—————————————————————————————————————————————————————————————

// book —> bookItem对象
- (BookItem *)getBookItemWithElement:(GDataXMLElement *)bookElement {
    BookItem *book = [[BookItem alloc] init];
    
    // name
    GDataXMLElement *nameElement = [bookElement elementsForName:@"name"][0];
    book.name = nameElement.stringValue; // <name>乔布斯传</name> --> 乔布斯传
    
    // authorName
    GDataXMLElement *authorNameElement = [bookElement nodesForXPath:@"author/name" error:nil][0];
    book.authorName = authorNameElement.stringValue;
    
    // price
    GDataXMLElement *priceElement = [bookElement elementsForName:@"price"][0];
    book.price = priceElement.stringValue;
    
    // summary
    GDataXMLElement *summaryElement = [bookElement elementsForName:@"summary"][0];
    book.summary = summaryElement.stringValue;
    
    // language
    GDataXMLNode *languageNode = [bookElement attributeForName:@"language"];
    book.language = languageNode.stringValue;
    
    return book;
}

也可以用XPath语法更方便的取出我们想要的东西:
[doc.rootElement nodesForXPath:@“//book” error:nil];

我们可以对GData进行扩展

@implementation GDataXMLElement (util)

- (NSString *)firstStrValueWithXPath:(NSString *)xpath {
    GDataXMLElement *element = [self nodesForXPath:xpath error:nil][0];
    return element.stringValue;
}

- (NSString *)attributeStrValueWithKey:(NSString *)key {
    GDataXMLNode *node = [self attributeForName:key];
    return node.stringValue;
}

@end

你可能感兴趣的:(ios,xml,标签,可扩展,oc学习)