阅读更多

0顶
0踩

移动开发

转载新闻 使用Swift原生库解析XML数据

2015-12-17 17:55 by 副主编 mengyidan1988 评论(1) 有7110人浏览
在实现文件操作的时候我意识到了一个事实:由于NSURL是可支持的路径,很多文件的操作实际上可以扩充到网络上去,比如从网上下载一个文件、拿取一些数据……想到这里,埋藏在心中很久的愿望又开始蠢蠢欲动:写一个新闻客户端!
我有一个常看的新闻网站(不要问我是哪个,要FQ),官方客户端很难用,第三方广告满天飞,严重影响心情。所以当初开始学iOS的时候就把重做一个客户端的目标放在了首位。最开始的时候想得太简单,兴冲冲地开了个project,搞了两下TableView,然后发现……对于我这种从来只写底层代码,swift/OC语法都不会的人,做这个简直是异想天开好嘛!
折腾的过程中,为了拿到数据,还跑去下了Android的官方客户端反编译,find + grep出来了人家的数据接口地址(论一个爱折腾的程序员是怎么给自己挖坑的),返回的是XML数据,连蒙带猜试了试,可以用!不过后来做UI受挫(其实不止做UI,挫败感太大),就把那份东西闲置起来了。这两天突然想起来,现在我貌似感觉有点良好,何不捡起来继续写我的客户端?
因为UI我还一窍不通,不懂怎么调试,也不懂怎么把数据显示出来,为了避免到处打印的麻烦,我选择playground。这样也就是需要用原生库,这个很简单,搜一下就有了:NSXMLParserDelegate,还有好些源码,虽然大多是OC的。
问题是有源码,我依!然!看!不!懂!怎么用!每个教程都是扔了源码上来,可没人解释清楚到底怎么运行。我研究了好一阵,终于明白了大概的机制:
引用
自己写一个类继承NSXMLParserDelegate,就叫它XmlReader吧;并且实现一些必须的callback函数,在XmlReader的Init中调用.parse()方法,最后在new XmlReader的时候就会自动完成整个parse了

当然你也可以不把parse()放在init()中调用,而是在new了XmlReader之后强制调用,重要的是那些callback函数的实现。XmlReader中还可以声明一些变量,来保存解析过程中的状态,而具体的获得到的数据填充,也是需要你自己做的(数据结构自行定义)。
鉴于XML是一个有层级的带递归意味的数据结构,程序会层层解析下去直到结束,中间遇到的各种类似section开始、结束、拿到字符串等情况都会call一个固定的函数,将解析出来的数据作为参数传进去,而你要做的,就是实现这些callback以完成自己想要做的事。
下面是具体的代码示范。首先是定义一个新的类:
class XmlReader: NSObject, NSXMLParserDelegate {
var currentName :String? = nil
var level :Int = 0

 init(add :String ) {

    super.init()
    let url = NSURL(string:add)!
    guard let parserXML = NSXMLParser(contentsOfURL: url) else {
        return
    }

    parserXML.delegate = self
    parserXML.parse()
    }

func parserDidStartDocument(parser: NSXMLParser) {}

func parserDidEndDocument(parser: NSXMLParser){}

func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {}

func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {}

func parser(parser: NSXMLParser, var foundCharacters string: String) {}

func parser(parser: NSXMLParser, parseErrorOccurred parseError: NSError) {}
}

这是一个基础部分,里面定义了一些callback但没有实现它。我把xml的地址作为参数传给了init(),并且声明了两个变量currentName和level分别用来保存当前的标签名字和递归深度。然后我们基于下面这个简单的XML文件继续完成callback部分:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<language cat="it">
    <lan id="1">
        <name>C#</name>
        <IDE>vs</IDE>
    </lan>
    <lan id="2" />
</language>

首先是文档开始和结束时:
//文档开始解析时触发,只触发一次
func parserDidStartDocument(parser: NSXMLParser) {
    print("    start")
}

//文档结束时触发,只触发一次,通常需要在这里给出一个信号告诉上层或其他人解析已经结束
func parserDidEndDocument(parser: NSXMLParser){
    print("    end")
}

然后是标签的开始和结束事件:
//遇到一个开始标签触发,elementName为当前标签,如果当前标签有属性,则字典sttributeDict不为空
func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]()) {
    self.currentName = elementName
    self.level++
    print("\(level) start, \(elementName), \(attributeDict)")
    if currentName == "language" { // 获取language属性的内容
        //print("language: \(attributeDict)")
    }
}

//遇到结束标签触发,该方法主要是做一些清理工作,在这里我修改了当前的深度
func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
    print("\(level) end, \(elementName)")
    self.currentName = nil
    self.level--
}

接下来是字符串值的handler
// 遇到字符串时触发
func parser(parser: NSXMLParser, var foundCharacters string: String) {
    //删除首尾的回车符和空格
    string = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
    if string.isEmpty {
        return
    }
    print("---- \(string)")
}

最后是Error Handler
// 文档出错时触发
func parser(parser: NSXMLParser, parseErrorOccurred parseError: NSError) {
    print(parseError)
}

以上的callback函数实现都只放了些打印信息,在实际操作中需要把这些获取的信息一一填充进自己的数据结构中。说实话是挺麻烦的,难怪都说XML快要被JSON全面取代(其实对于曾被libxml折磨过的码农来说,这已经挺好了)。全部的代码传送门:这里

本文转自:http://conanwhf.gitcafe.io/
0
0
评论 共 1 条 请登录后发表评论
1 楼 YiBuXiaoCai 2015-12-18 10:15
程序员群 2177712 

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • Swift 原生Xml解析

    XMLParser解析 1.XML数据 &lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&gt; &lt;person id="1"&gt; &lt;name&gt;xiaopao&lt;/name&gt; &lt;age&gt;21&lt;/age&gt; &lt;/person&gt; ...

  • SwiftUI学习笔记【XML解析】

    对于接触过IOS解析XML的应该很多吧…我是写Android的我司项目会涉及到很多xml解析导出给CAD然后CAD解析完成之后进行绘制编辑等。原生Android有很多对于XML的解析方式[SAX,Pull,DOM等],Flutter的对于XML解析很少了...

  • iOS XML数据解析

    最近公司的活比较少,空闲时间...在这个过程中便有使用到XML数据,于是研究了一下。目前写的这个是本地阅读软件,后续会把在写这个APP用到的技术以及遇到的问题都整理出来,通过博客的形式分享给大家。奇迹读书地址。

  • iOS开发之Swift 4 JSON 解析指南

    Apple 终于在 Swift 4 的 Foundation 的模块中添加了对 JSON 解析的原生支持。 虽然已经有很多第三方类库实现了 JSON 解析,但是能够看到这样一个功能强大、易于使用的官方实现还是不免有些兴奋。 值得注意的是,...

  • Swift4 JSON解析指南

    Apple 终于在 Swift 4 的 Foundation 的模块中添加了对 JSON 解析的原生支持。 虽然已经有很多第三方类库实现了 JSON 解析,但是能够看到这样一个功能强大、易于使用的官方实现还是不免有些兴奋。 值得注意的是,...

  • Swift 4 JSON 解析指南

    Apple 终于在 Swift 4 的 Foundation 的模块中添加了对 JSON 解析的原生支持。 虽然已经有很多第三方类库实现了 JSON 解析,但是能够看到这样一个功能强大、易于使用的官方实现还是不免有些兴奋。 值得注意的是,...

  • iOS开发最常用三方库集合Swift版(三方库、插件、博客等等)

    Swift学习资料@SwiftGuide很赞 的Swift学习资料leetcode一个练习、评估自己水平的代码平台,跟ACM有点类似完整App@Swift 30 Projects- 最新 Swift 3.0 的30个小App,更注重代码规范和架构设计(故胤道长)V2ex-Swift- ...

  • model存储 swift_iOS ~ Swift之数据存储(.plist,NSUserDefaults,NSKeyedArchiver)

    最近公司项目中使用了本地存储,所以趁着周六日来整理一下在Swift中的几种数据存储方式。一、plist文件存储存储目录:Documents每次在Xcode中新建一个iOS项目后,都会自己产生一个.plist文件,里面记录项目的一些...

  • 读取与解析json类型数据

    读取与解析json类型数据 一、什么是JSON? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式, 是理想的数据交换格式,同时,JSON是 JavaScript 原生格式。 非常...

  • RAG知识库问答LangChain+LLM的二次开发:商用时的典型问题及其改进方案

    如之前的文章所述,我司下半年成立大模型项目团队之后,我兼管整个项目团队,但为让项目的推进效率更高,故分成了三大项目组对于知识库问答,现在有两种方案,一种基于llamaindex,一种基于langchain +LLM,考虑到我...

  • 强烈推荐大家看这篇文章:iOS开发常用三方库、插件、知名博客等等(特别有用)

    Swift版本点击这里欢迎加入交QQ流群: 594119878github排名 https://github.com/trending,github搜索:https://github.com/search使用方法:根据目录关键字搜索,记得包含@,以保证搜索目录关键字的唯一性。...

  • iOS之网络—— JSON解析、XML解析、文件下载、文件的压缩和解压缩

    (2)服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外) 002 相关说明 (1)JSON的格式很像OC中的字典和数组 (2)标准JSON格式key必须是双引号 003 JSON解析方案

  • go 生成基于 graphql 服务器库.zip

    格奇尔根 首页 > 文件 > gqlgen是什么?gqlgen是一个 Go 库,用于轻松构建 GraphQL 服务器。gqlgen 基于 Schema 优先方法— 您可以使用 GraphQL Schema 定义语言来定义您的 API 。gqlgen 优先考虑类型安全— 您永远不应该看到map[string]interface{}这里。gqlgen 启用 Codegen — 我们生成无聊的部分,以便您可以专注于快速构建您的应用程序。还不太确定如何使用gqlgen?将gqlgen与其他 Go graphql实现进行比较快速启动初始化一个新的 go 模块mkdir examplecd examplego mod init example添加github.com/99designs/gqlgen到项目的 tools.goprintf '//go:build tools\npackage tools\nimport (_ "github.com/99designs/gqlgen"\n _ "github.com/99designs/gqlgen

  • 基于JAVA+SpringBoot+Vue+MySQL的社区物资交易互助平台 源码+数据库+论文(高分毕业设计).zip

    项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql8.0 部署环境:maven 数据库工具:navicat

  • 法研杯2021类案检索赛道三等奖方案源码+项目说明+数据.zip

    法研杯2021类案检索赛道三等奖方案源码+项目说明+数据.zip是一个专为计算机相关专业(如计科、信息安全、数据科学与大数据技术等)学生设计的宝贵学习资源。该压缩包包含了完整的项目源码、详细的项目说明文档以及用于训练和测试的数据集,旨在帮助参赛者深入理解并掌握类案检索的相关技术和方法。该项目通过实际案例,展示了如何运用自然语言处理和机器学习技术对法律案件进行智能检索和匹配。项目内容涵盖了从数据预处理、特征提取到模型训练和评估的全过程,为学习和研究类案检索技术提供了全面的参考。本项目不仅适合作为课程设计、期末大作业或毕设项目的参考,也是企业员工提升技能、进行实践操作的优质学习资料。通过实际操作和学习该项目,用户可以加深对类案检索技术的理解,并在实践中不断提升自己的技能水平。请注意,由于该资源包含完整的项目源码和数据集,下载和使用时请确保遵守相关法律法规和道德规范,尊重知识产权和隐私权。同时,建议用户在使用前仔细阅读项目说明文档,了解项目的整体架构和使用方法,以便更好地利用该资源进行学习和研究。

  • 基于Cesium实现的对倾斜摄影模型的单体化分层方案源码.zip

    本资源提供了基于Cesium实现的倾斜摄影模型单体化分层方案的完整源码,旨在帮助开发者深入理解并实践三维地理空间数据的处理与展示。通过Cesium平台,用户能够将倾斜摄影获取的高精度三维模型进行单体化和分层处理,实现对模型中每个独立元素的精细管理和交互操作。该资源适合具备一定计算机编程基础的学习者,特别是对Cesium感兴趣的学生、研究人员及GIS行业从业者。通过下载并学习这些源码,用户可以掌握倾斜摄影模型在Cesium中的加载、单体化以及分层显示等关键技术,进而提升自己在三维地理信息系统开发领域的技能水平。

  • Go 的 PostgreSQL 驱动程序和工具包.zip

    Go 的 PostgreSQL 驱动程序和工具包 pgx - PostgreSQL 驱动程序和工具包pgx 是 PostgreSQL 的纯 Go 驱动程序和工具包。pgx 驱动程序是一个低级、高性能接口,它公开了 PostgreSQL 特定的功能,例如LISTEN/ NOTIFY和COPY。它还包括一个标准database/sql接口的适配器。工具包组件是一组相关的软件包,用于实现 PostgreSQL 功能,例如解析线路协议以及 PostgreSQL 与 Go 之间的类型映射。这些底层软件包可用于实现替代驱动程序、代理、负载均衡器、逻辑复制客户端等。示例用法package mainimport ( "context" "fmt" "os" "github.com/jackc/pgx/v5")func main() { // urlExample := "postgres://username:password@localhost:5432/database_name" conn, err := pgx.Connect(context.B

  • C#ASP.NET中小型超市管理系统源码数据库 SQL2012源码类型 WinForm

    ASP.NET中小型超市管理系统源码 超市管理系统是专门为中小型超市打造的管理系统,可以方便管理时更加准确清晰的查看商品信息, 仓库出售与进货的信息,还有每一个部门员工的信息,也更加直观的体现出每一阶段的商品销售情况; 从而提高项目管理水平,实现了工作的协同化、提高了工作效率 二、功能介绍 1.1 UI Requirements界面要求 (1)界面美观,给用户一种很舒心的感觉。 (2)界面所体现出的功能清晰明了,让用户一目了然。 (3)界面的背景颜色搭配符合超市管理系统界面的设计理念。 1.2 UI Requirements界面要求 (1) 使用ADO.NET与数据库交互制作 (2) 使用Visual Studio设计窗体布局 (3) 使用提供的用控件快速开发 1.3 Development Environment 开发环境 (1) 开发工具:Visua

  • 毕设&课程作业_基于C#的易知仓库管理系统.zip

    计算机系毕业设计

  • Go 编程教程的主列表、其撰写、其源代码以及其当前构建状态!.zip

    教程边缘TutorialEdge.net Go 教程 ‍‍欢迎来到 TutorialEdge Go 存储库!此 repo 的目标是能够跟踪所有 Go 教程及其各自的 github repo 位置和构建状态。这些将在 Go 最新版本发布时更新和运行。目录初学者教程中级教程高级教程DevOps项目数据格式并发教程挑战初学者教程这些教程主要针对那些希望提高对 Go 语言工作原理的基本理解的语言新手!教程标题 教程边缘 Github 构建状态 更新日期01 - Go 入门 阅读教程 TutorialEdge/getting-started-with-go 不适用02 - Go 基本类型教程 阅读教程 TutorialEdge/go-basic-types-tutorial 不适用03 - Go 复合类型教程 阅读教程 TutorialEdge/go-complex-types-tutorial 不适用04 - Go 函数教程 阅读教程 TutorialEdge/go-functions-tutorial 2019 年 3 月 27 日

Global site tag (gtag.js) - Google Analytics