在去年的時候,好像 podcast 特別的夯,就想跟一群朋友玩玩看 podcast 的資料,看能不能玩出什麼東西。然後我們就發現了 podcast 的資料格式真的滿複雜的,而且各家平台的資料格式又有點不太一樣,像是有 RSS 2.0 的標準格式、google play 平台格式和 iTunes 的格式 等。更不用說有一些 RSS 會塞一些自定義的 tag 或 attribute ,自己程式來處理這種東西,通常格式一修改,或是 attribute 換個位置,程式就要修改,但程式碼就只是換個地方寫來處理差不多的格式。
舉例來說,以下是 RSS 2.0 的格式:
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<image>
<link>http://channel.image.link</link>
<title>channel image title</title>
<url>http://channel.image.url</url>
<description>channel image description</description>
<height>32</height>
<width>96</width>
</image>
</channel>
</rss>
然後我們從 iTunes 有可能拿到長這樣的格式:
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
<channel>
<itunes:image href="https://channel.image.itunes" />
<image>
<link>http://channel.image.link</link>
<title>channel image title</title>
<url>http://channel.image.url</url>
<description>channel image description</description>
<height>32</height>
<width>96</width>
</image>
</channel>
</rss>
可以看到中間多了一個 itunes:image 的 tag ,這個就是 iTunes 的平台格式。
那如果我們又加上 google play 的格式,就會長這樣:
<?xml version="1.0"?>
<rss xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
<channel>
<googleplay:image href="http://channel.image" />
<itunes:image href="https://channel.image" />
<image>
<link>http://channel.image</link>
<title>channel image title</title>
<url>http://channel.image.url</url>
<description>channel image description</description>
<height>32</height>
<width>96</width>
</image>
</channel>
</rss>
看到這裡你可能會想說,那有什麼難的?我就 <image>
、 <itunes:image>
和 <googleplay:image>
這個三個 tag 都 parse 一遍就好了?對,如果今天只有一個 tag 要 parse 的話,我覺得這樣應該沒問題。
但仔細想想,現在出現的格式有:
<googleplay:image href="http://channel.image" />
<itunes:image href="https://channel.image" />
<image>
<link>http://channel.image</link>
<title>channel image title</title>
<url>http://channel.image.url</url>
<description>channel image description</description>
<height>32</height>
<width>96</width>
</image>
好,這根本大亂鬥吧! ?
我們來思考一下目前的問題有:
如果有很多這種的格式要取值,而且還有取值優先權和格式結構不同的問題時,這樣就要寫很多類似的程式碼去做一樣的事情。同樣是取 image url 的值,我想要先取 google play 的值,再取 iTunes 的,前面兩個都沒有的時候,再用 RSS 2.0 的值,而 RSS 2.0 的 url 又擺在更裡面一層的結構裡。如此一來,我們自己寫程式去 parse 這些資料會變的很繁瑣。在 podcast 格式中,image 這個 tag 只是冰山一角,要有效率地處理不同格式的問題,我們就要借助 custom annotation 和 annotation processor 的力量。
後來,我們就針對了這個 RSS 格式寫了一個 KtRssReader 的 library 專門幫助大家去讀取 RSS 資料。這個系列的文章就是在講述寫這個 library 的原理、實作和測試的心路歷程,同時,我們也會提到新的 KSP 技術和它可以怎麼改進我們 library 。如果你不熟 annotation 或者 annotation processor 的話也不用擔心,這個系列會一步一步帶你了解和實作 annotation processor 。這個 library 是使用 Kotlin 開發的,所以本系列文章的程式碼範例都會使用 Kotlin 進行解說。