上篇我们介绍了 XmlPullParser 和常用的几个 event type ,现在我们来介绍它的实作。首先我们要拿到 parser 的实体才能够操作 tag ,我们可以定义一个 function 来拿 parser ,XML 字串拿到之後要先转成 ByteArrayInputStream
,然後安全使用 use
来读 inputStream 。为什麽会讲它安全呢?因为 Kotlin 原生的 use
extension 可以让我们操作 inputStream 的时候,不用自己写 try/catch/finally ,它里面帮你包好好的,只要传一个 code block 进去执行就好。
fun getXmlParser(xml: String): XmlPullParser {
ByteArrayInputStream(xml.toByteArray()).use { inputStream ->
return Xml.newPullParser().apply {
setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)
setInput(inputStream, null)
nextTag()
}
}
}
拿到parser 实体後,让我们先从怎麽 parse 最外层的 <channel>
开始吧!
fun <T> parseChannel(xml: String, action: XmlPullParser.() -> T): T {
val parser = getXmlParser(xml)
var result: T? = null
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.eventType != XmlPullParser.START_TAG) continue
if (parser.name == CHANNEL) {
result = action(parser)
break
} else {
parser.skip()
}
}
return result ?: throw XmlPullParserException("No valid channel tag in the RSS feed.")
}
这段程序码可以看到我们参数里面放了个 action: XmlPullParser.() -> T
,这个是一个 Kotlin receiver type 的 lambda ,主要是想要让外面使用的人在 lambda 里面可以使用 XmlPullPaser
的 API ,另外,还有个泛型 T
,会使用泛型的主要原因是便於这个 function 被重复使用,毕竟我们有可能会定义不同型态的资料格式,举例来说像是我可以把 RSS 2.0 的标准资料定义成 RssStandardChannel
,iTunes 平台格式定义成 ITunesChannel
,google 的就放在 GoogleChannel
,这些都可以放进这个 function 来用。
使用 parser 的时候,我们可以透过回圈去拿取下一个 event ,拿 eventType 和 name 来判断是不是 Channel
,这边因为我们只需要扫到 channel 其他的 event 就可以跳过。拿到 channel 的 event 後,我们就可以用已经定义好的 lambda 去爬下一层的 tag 。
这边还有个小细节就是跳过 tag 的方式,这边一样是写成一个 extension 方便之後重复使用。跳过的 tag 有可能会有很多子 tag , depth
就是在记录层数,当它回到 0 的时候,代表这个 tag 底下整颗子树都跳过了。
@Throws(XmlPullParserException::class, IOException::class)
protected fun XmlPullParser.skip() {
if (eventType!= XmlPullParser.START_TAG) {
throw IllegalStateException()
}
var depth = 1
while (depth != 0) {
when (next()) {
XmlPullParser.END_TAG-> depth--
XmlPullParser.START_TAG-> depth++
}
}
}
<<: Day9 - pandas(4)Series与DataFrame的运算
>>: Day 11 Chatbot integration- 看图学英文
前言 今天是铁人赛文章发文的最後一天 (在此我要谢谢我的爸爸、妈妈、老婆、小狗..),本篇会做个简单...
https://plan.seek.intel.com/TW_ICX_Event-REG?track...
今天要讲的是if...else,昨天只讲了if 那if...else 就是 如果...否则 来看看c...
今天介绍一下Yolo v3, 首先在v3中使用了darknet-53的架构,架构如下图: 相比v2的...
如果我有一个数字的阵列变数[2, 1, 2, 3, 5, 6, 8, 9],想要计算(0~9)各个数...