上篇我们讲了 parser 的基本使用方式和一些前置的 function 实作,像是 parseChannel
和 skip
,接下来我们就要来讲其他实用的取值方式。首先,我们可以拿到指定 tag 的 value ,我们需要写一个针对 XmlPullParser 来写一个 readString 的 extension function 。
@Throws(IOException::class, XmlPullParserException::class)
protected fun XmlPullParser.readString(tagName: String): String? {
require(XmlPullParser.START_TAG, null, tagName)
var content: String? = null
if (next() == XmlPullParser.TEXT) {
content = text
nextTag()
if (eventType != XmlPullParser.END_TAG) {
skip()
nextTag()
content = null
}
}
require(XmlPullParser.END_TAG, null, tagName)
return content
}
我们可以取得指定 tagName
里的值,假设 tag 的名称叫做 title ,那代表的就是要拿 <title>title1</title>
里面的 title1 。在 function 的最前面和最後面,我们都要检查 event type 和现在的 tag 名称,这主要是要检查 RSS 的基本格式是不是正确的,因为有可能拿到的格式缺了前面的 <title>
或是後面的 </title>
,这都会导致我们後面的 parsing 结果不正确。在 function 的中间也要检查 event type 是否为 TEXT
,这样才是我们想要的值。
<enclosure length="24986239" type="audio/mpeg" url="http://item.enclosure.url/item.mp3" />
那如果我们是要拿 attribute 里面的值,像是上面范例的 length
、 type
和 url
的话,可以怎麽做?其实他的思路跟 readString
有点像,但不需要额外爬一层 tag 。我们可以设计一个 function 让他可以拿取多个 attribute !
@Throws(IOException::class, XmlPullParserException::class)
protected fun XmlPullParser.readAttributes(
tagName: String,
attributes: List<String>,
action: (String, String?) -> Unit
) {
require(XmlPullParser.START_TAG, null, tagName)
attributes.forEach { attr ->
action(attr, getAttributeValue(null, attr))
}
nextTag()
logD(logTag, "[readAttributes]: tag name = $tagName, attributes = $attributes")
require(XmlPullParser.END_TAG, null, tagName)
}
可以看到 function 的参数里面有 attribute ,这个主要是让使用者指定要爬的 attribute 有哪些,像刚刚的 enclosure 里面我们就可以指定 tagName 是 enclosure ,attribute 是一个阵列,里面包含 length
、 type
和 url
。 action
这个参数则是可以对爬到的值去做指定的动作,塞一个 lambda 进去就可以了!用法可以参考下面的程序码:
@Throws(IOException::class, XmlPullParserException::class)
protected fun XmlPullParser.readEnclosure(): Enclosure {
var url: String? = null
var length: Long? = null
var type: String? = null
readAttributes(ENCLOSURE, listOf(URL, LENGTH, TYPE)) { attr, value ->
when (attr) {
URL -> url = value
LENGTH -> length = value?.toLongOrNull()
TYPE -> type = value
}
}
return Enclosure(url = url, length = length, type = type)
}
>>: Flutter体验 Day 4-Dart CheatSheet (2)
虽然这章节可能有些无聊,迟迟没进入CSS引人兴趣的地方, 但我还是想依我学习时,所想到和纳闷的事物按...
有了商品列表,那应该要能点进去看商品的细节吧。所以今天就是来做点进去後的商品细节页! 今日目标:商品...
Search Console 并不是都是看到使用者主动搜寻的流量,其中探索 (Discover) 与...
前文提到页是Innodb的基本存取单位,一般为16kb,Innodb为了实现功能其实设计了许多不同类...
尾声 最後一天想回归到第一天时对自己说的话「看完这些文章的读者能够对 Next.js 有更多的了解,...